Line data Source code
1 : #include "../../burp.h"
2 : #include "../../action.h"
3 : #include "../../alloc.h"
4 : #include "../../asfd.h"
5 : #include "../../async.h"
6 : #include "../../attribs.h"
7 : #include "../../cmd.h"
8 : #include "../../cntr.h"
9 : #include "../../conf.h"
10 : #include "../../log.h"
11 : #include "../../protocol1/handy.h"
12 : #include "../../protocol1/msg.h"
13 : #include "../extrameta.h"
14 : #include "../find.h"
15 : #include "backup_phase2.h"
16 :
17 2 : static int rs_loadsig_network_run(struct asfd *asfd,
18 : rs_job_t *job, struct cntr *cntr)
19 : {
20 2 : int ret=-1;
21 : rs_buffers_t buf;
22 : rs_result result;
23 2 : rs_filebuf_t *in_fb=NULL;
24 : memset(&buf, 0, sizeof(buf));
25 :
26 2 : if(!(in_fb=rs_filebuf_new(NULL,
27 : NULL, asfd, ASYNC_BUF_LEN, -1)))
28 : goto end;
29 :
30 : while(1)
31 : {
32 4 : iobuf_free_content(asfd->rbuf);
33 4 : if(asfd->read(asfd)) goto end;
34 8 : if(asfd->rbuf->cmd==CMD_MESSAGE
35 4 : || asfd->rbuf->cmd==CMD_WARNING)
36 : {
37 0 : log_recvd(asfd->rbuf, cntr, 0);
38 0 : continue;
39 : }
40 4 : switch((result=rs_async(job, &buf, in_fb, NULL)))
41 : {
42 : case RS_BLOCKED:
43 : case RS_RUNNING:
44 2 : continue;
45 : case RS_DONE:
46 : ret=0;
47 : goto end;
48 : default:
49 0 : logp("error in rs_async for sig: %d\n",
50 : result);
51 0 : goto end;
52 : }
53 : }
54 :
55 : end:
56 2 : iobuf_free_content(asfd->rbuf);
57 2 : rs_filebuf_free(&in_fb);
58 2 : return ret;
59 : }
60 :
61 2 : static int load_signature(struct asfd *asfd,
62 : rs_signature_t **sumset, struct cntr *cntr)
63 : {
64 : rs_job_t *job;
65 :
66 2 : if(!(job=rs_loadsig_begin(sumset)))
67 : {
68 0 : logp("could not start sig job.\n");
69 0 : return -1;
70 : }
71 2 : if(rs_loadsig_network_run(asfd, job, cntr))
72 : return -1;
73 2 : if(rs_build_hash_table(*sumset))
74 : return -1;
75 2 : rs_job_free(job);
76 2 : return 0;
77 : }
78 :
79 2 : static int load_signature_and_send_delta(struct asfd *asfd,
80 : struct BFILE *bfd, uint64_t *bytes, uint64_t *sentbytes,
81 : struct cntr *cntr)
82 : {
83 2 : int ret=-1;
84 2 : rs_job_t *job=NULL;
85 2 : rs_signature_t *sumset=NULL;
86 : uint8_t checksum[MD5_DIGEST_LENGTH];
87 2 : rs_filebuf_t *infb=NULL;
88 2 : rs_filebuf_t *outfb=NULL;
89 : rs_buffers_t rsbuf;
90 : memset(&rsbuf, 0, sizeof(rsbuf));
91 :
92 2 : if(load_signature(asfd, &sumset, cntr))
93 : goto end;
94 :
95 2 : if(!(job=rs_delta_begin(sumset)))
96 : {
97 0 : logp("could not start delta job.\n");
98 0 : goto end;
99 : }
100 :
101 2 : if(!(infb=rs_filebuf_new(bfd,
102 : NULL, NULL, ASYNC_BUF_LEN, bfd->datalen))
103 2 : || !(outfb=rs_filebuf_new(NULL,
104 : NULL, asfd, ASYNC_BUF_LEN, -1)))
105 : {
106 0 : logp("could not rs_filebuf_new for delta\n");
107 0 : goto end;
108 : }
109 :
110 : while(1)
111 : {
112 : rs_result result;
113 6 : switch((result=rs_async(job, &rsbuf, infb, outfb)))
114 : {
115 : case RS_DONE:
116 2 : *bytes=infb->bytes;
117 2 : *sentbytes=outfb->bytes;
118 2 : if(!MD5_Final(checksum, &(infb->md5)))
119 : {
120 0 : logp("MD5_Final() failed\n");
121 0 : goto end;
122 : }
123 2 : if(write_endfile(asfd, *bytes, checksum))
124 : goto end;
125 2 : ret=0;
126 2 : goto end;
127 : case RS_BLOCKED:
128 : case RS_RUNNING:
129 : // FIX ME: get it to read stuff here too.
130 : // (errors, for example)
131 4 : if(asfd->as->write(asfd->as))
132 : goto end;
133 4 : continue;
134 : default:
135 0 : logp("error in rs_async for delta: %d\n",
136 : result);
137 0 : goto end;
138 : }
139 4 : }
140 : end:
141 2 : rs_filebuf_free(&infb);
142 2 : rs_filebuf_free(&outfb);
143 2 : if(job) rs_job_free(job);
144 2 : if(sumset) rs_free_sumset(sumset);
145 2 : return ret;
146 : }
147 :
148 6 : static enum send_e send_whole_file_w(struct asfd *asfd,
149 : struct sbuf *sb, const char *datapth,
150 : int quick_read, uint64_t *bytes, const char *encpassword,
151 : struct cntr *cntr, int compression, struct BFILE *bfd,
152 : const char *extrameta, size_t elen)
153 : {
154 6 : if((compression || encpassword) && sb->path.cmd!=CMD_EFS_FILE)
155 : {
156 0 : int key_deriv=sb->encryption==ENCRYPTION_KEY_DERIVED;
157 :
158 0 : return send_whole_file_gzl(asfd, datapth, quick_read, bytes,
159 : encpassword, cntr, compression, bfd, extrameta, elen,
160 0 : key_deriv, sb->protocol1->salt);
161 : }
162 : else
163 6 : return send_whole_filel(asfd,
164 : #ifdef HAVE_WIN32
165 : sb->path.cmd,
166 : #endif
167 : datapth, quick_read, bytes,
168 : cntr, bfd, extrameta, elen);
169 : }
170 :
171 0 : static int forget_file(struct asfd *asfd, struct sbuf *sb, struct conf **confs)
172 : {
173 : // Tell the server to forget about this
174 : // file, otherwise it might get stuck
175 : // on a select waiting for it to arrive.
176 0 : if(asfd->write_str(asfd, CMD_INTERRUPT, sb->path.buf))
177 : return 0;
178 :
179 0 : if(sb->path.cmd==CMD_FILE && sb->protocol1->datapth.buf)
180 : {
181 0 : rs_signature_t *sumset=NULL;
182 : // The server will be sending us a signature.
183 : // Munch it up then carry on.
184 0 : if(load_signature(asfd, &sumset, get_cntr(confs))) return -1;
185 0 : else rs_free_sumset(sumset);
186 : }
187 : return 0;
188 : }
189 :
190 8 : static int size_checks(struct asfd *asfd, struct sbuf *sb, struct conf **confs)
191 : {
192 16 : if(sb->path.cmd!=CMD_FILE
193 8 : && sb->path.cmd!=CMD_ENC_FILE
194 0 : && sb->path.cmd!=CMD_EFS_FILE)
195 : return 0;
196 8 : if(get_uint64_t(confs[OPT_MIN_FILE_SIZE])
197 0 : && (uint64_t)sb->statp.st_size<get_uint64_t(confs[OPT_MIN_FILE_SIZE]))
198 : {
199 0 : logw(asfd, get_cntr(confs), "File size decreased below min_file_size after initial scan: %s\n", iobuf_to_printable(&sb->path));
200 0 : return -1;
201 : }
202 8 : if(get_uint64_t(confs[OPT_MAX_FILE_SIZE])
203 0 : && (uint64_t)sb->statp.st_size>get_uint64_t(confs[OPT_MAX_FILE_SIZE]))
204 : {
205 0 : logw(asfd, get_cntr(confs), "File size increased above max_file_size after initial scan: %s\n", iobuf_to_printable(&sb->path));
206 0 : return -1;
207 : }
208 : return 0;
209 : }
210 :
211 8 : static int deal_with_data(struct asfd *asfd, struct sbuf *sb,
212 : struct BFILE *bfd, struct conf **confs)
213 : {
214 8 : int ret=-1;
215 8 : int forget=0;
216 8 : size_t elen=0;
217 8 : char *extrameta=NULL;
218 8 : uint64_t bytes=0;
219 8 : int conf_compression=get_int(confs[OPT_COMPRESSION]);
220 8 : struct cntr *cntr=get_cntr(confs);
221 8 : const char *enc_password=get_string(confs[OPT_ENCRYPTION_PASSWORD]);
222 :
223 8 : sb->compression=conf_compression;
224 8 : if(enc_password)
225 : {
226 0 : sb->encryption=ENCRYPTION_KEY_DERIVED;
227 0 : if(!RAND_bytes((uint8_t *)&sb->protocol1->salt, 8))
228 : {
229 0 : logp("RAND_bytes() failed\n");
230 0 : return -1;
231 : }
232 : }
233 :
234 8 : iobuf_copy(&sb->path, asfd->rbuf);
235 8 : iobuf_init(asfd->rbuf);
236 :
237 : #ifdef HAVE_WIN32
238 : if(win32_lstat(sb->path.buf, &sb->statp, &sb->winattr))
239 : #else
240 16 : if(lstat(sb->path.buf, &sb->statp))
241 : #endif
242 : {
243 0 : logw(asfd, cntr, "Path has vanished: %s\n",
244 : iobuf_to_printable(&sb->path));
245 0 : if(forget_file(asfd, sb, confs)) goto error;
246 : goto end;
247 : }
248 :
249 8 : if(size_checks(asfd, sb, confs)) forget++;
250 :
251 8 : sb->compression=in_exclude_comp(get_strlist(confs[OPT_EXCOM]),
252 8 : sb->path.buf, conf_compression);
253 8 : if(attribs_encode(sb)) goto error;
254 :
255 16 : if(sb->path.cmd!=CMD_METADATA
256 8 : && sb->path.cmd!=CMD_ENC_METADATA)
257 : {
258 24 : if(bfd->open_for_send(bfd, asfd,
259 16 : sb->path.buf, sb->winattr,
260 : get_int(confs[OPT_ATIME]), cntr, PROTO_1))
261 0 : forget++;
262 : }
263 :
264 8 : if(forget)
265 : {
266 0 : if(forget_file(asfd, sb, confs)) goto error;
267 : goto end;
268 : }
269 :
270 16 : if(sb->path.cmd==CMD_METADATA
271 : || sb->path.cmd==CMD_ENC_METADATA
272 8 : || sb->path.cmd==CMD_VSS
273 8 : || sb->path.cmd==CMD_ENC_VSS
274 : #ifdef HAVE_WIN32
275 : || get_int(confs[OPT_STRIP_VSS])
276 : #endif
277 : )
278 : {
279 0 : if(get_extrameta(asfd,
280 : #ifdef HAVE_WIN32
281 : bfd,
282 : #endif
283 0 : sb->path.buf,
284 0 : S_ISDIR(sb->statp.st_mode),
285 : &extrameta, &elen, cntr))
286 : {
287 0 : logw(asfd, cntr,
288 : "Meta data error for %s\n",
289 : iobuf_to_printable(&sb->path));
290 0 : goto end;
291 : }
292 0 : if(extrameta)
293 : {
294 : #ifdef HAVE_WIN32
295 : if(get_int(confs[OPT_STRIP_VSS]))
296 : {
297 : free_w(&extrameta);
298 : elen=0;
299 : }
300 : #endif
301 : }
302 : else
303 : {
304 0 : logw(asfd, cntr,
305 : "No meta data after all: %s\n",
306 : iobuf_to_printable(&sb->path));
307 0 : goto end;
308 : }
309 : }
310 :
311 8 : if(sb->path.cmd==CMD_FILE
312 4 : && sb->protocol1->datapth.buf)
313 2 : {
314 2 : uint64_t sentbytes=0;
315 : // Need to do sig/delta stuff.
316 2 : if(asfd->write(asfd, &(sb->protocol1->datapth))
317 2 : || asfd->write(asfd, &sb->attr)
318 2 : || asfd->write(asfd, &sb->path)
319 2 : || load_signature_and_send_delta(asfd, bfd,
320 : &bytes, &sentbytes, cntr))
321 : {
322 0 : logp("error in sig/delta for %s (%s)\n",
323 : iobuf_to_printable(&sb->path),
324 0 : iobuf_to_printable(&sb->protocol1->datapth));
325 0 : goto end;
326 : }
327 2 : cntr_add(cntr, CMD_FILE_CHANGED, 1);
328 : }
329 : else
330 : {
331 : //logp("need to send whole file: %s\n", sb.path);
332 : // send the whole file.
333 :
334 6 : if(asfd->write(asfd, &sb->attr)
335 6 : || asfd->write(asfd, &sb->path))
336 : goto end;
337 :
338 6 : switch(send_whole_file_w(asfd, sb, NULL, 0, &bytes,
339 : enc_password,
340 : cntr, sb->compression,
341 : bfd, extrameta, elen))
342 : {
343 : case SEND_OK:
344 : case SEND_ERROR: // Carry on.
345 : break;
346 : case SEND_FATAL:
347 : default:
348 : goto error;
349 : }
350 6 : cntr_add(cntr, sb->path.cmd, 1);
351 : }
352 8 : cntr_add_bytes(cntr, bytes);
353 :
354 : end:
355 : ret=0;
356 : error:
357 : #ifdef HAVE_WIN32
358 : // If using Windows do not close bfd - it needs
359 : // to stay open to read VSS/file data/VSS.
360 : // It will get closed either when given a
361 : // different file path, or when this function
362 : // exits.
363 : #else
364 8 : bfd->close(bfd, asfd);
365 : #endif
366 8 : sbuf_free_content(sb);
367 8 : free_w(&extrameta);
368 8 : return ret;
369 : }
370 :
371 19 : static int parse_rbuf(struct asfd *asfd, struct sbuf *sb,
372 : struct BFILE *bfd, struct conf **confs)
373 : {
374 : static struct iobuf *rbuf;
375 19 : rbuf=asfd->rbuf;
376 19 : if(rbuf->cmd==CMD_DATAPTH)
377 : {
378 2 : iobuf_move(&(sb->protocol1->datapth), rbuf);
379 : }
380 17 : else if(rbuf->cmd==CMD_ATTRIBS)
381 : {
382 : // Ignore the stat data - we will fill it
383 : // in again. Some time may have passed by now,
384 : // and it is best to make it as fresh as
385 : // possible.
386 : }
387 9 : else if(iobuf_is_filedata(rbuf)
388 1 : || iobuf_is_vssdata(rbuf))
389 : {
390 8 : if(deal_with_data(asfd, sb, bfd, confs))
391 : return -1;
392 : }
393 2 : else if(rbuf->cmd==CMD_MESSAGE
394 1 : || rbuf->cmd==CMD_WARNING)
395 : {
396 1 : struct cntr *cntr=NULL;
397 1 : if(confs) cntr=get_cntr(confs);
398 1 : log_recvd(rbuf, cntr, 0);
399 : }
400 : else
401 : {
402 0 : iobuf_log_unexpected(rbuf, __func__);
403 0 : return -1;
404 : }
405 : return 0;
406 : }
407 :
408 6 : static int do_backup_phase2_client(struct asfd *asfd,
409 : struct conf **confs, int resume)
410 : {
411 6 : int ret=-1;
412 : // For efficiency, open Windows files for the VSS data, and do not
413 : // close them until another time around the loop, when the actual
414 : // data is read.
415 6 : struct BFILE *bfd=NULL;
416 6 : struct sbuf *sb=NULL;
417 6 : struct iobuf *rbuf=NULL;
418 6 : struct cntr *cntr=NULL;
419 6 : if(confs) cntr=get_cntr(confs);
420 :
421 6 : if(!asfd)
422 : {
423 1 : logp("%s() called without asfd!\n", __func__);
424 1 : goto end;
425 : }
426 5 : rbuf=asfd->rbuf;
427 :
428 5 : if(!(bfd=bfile_alloc())
429 5 : || !(sb=sbuf_alloc(PROTO_1)))
430 : goto end;
431 5 : bfile_init(bfd, 0, cntr);
432 :
433 5 : if(!resume)
434 : {
435 : // Only do this bit if the server did not tell us to resume.
436 5 : if(asfd->write_str(asfd, CMD_GEN, "backupphase2")
437 5 : || asfd_read_expect(asfd, CMD_GEN, "ok"))
438 : goto end;
439 : }
440 : else
441 : {
442 : // On resume, the server might update the client with cntr.
443 0 : if(cntr_recv(asfd, confs))
444 : goto end;
445 : }
446 :
447 : while(1)
448 : {
449 24 : iobuf_free_content(rbuf);
450 24 : if(asfd->read(asfd)) goto end;
451 23 : else if(!rbuf->buf) continue;
452 :
453 23 : if(rbuf->cmd==CMD_GEN && !strcmp(rbuf->buf, "backupphase2end"))
454 : {
455 4 : if(asfd->write_str(asfd, CMD_GEN, "okbackupphase2end"))
456 : goto end;
457 4 : ret=0;
458 4 : break;
459 : }
460 :
461 19 : if(parse_rbuf(asfd, sb, bfd, confs))
462 : goto end;
463 : }
464 :
465 : end:
466 : // It is possible for a bfd to still be open.
467 6 : if(bfd) bfd->close(bfd, asfd);
468 6 : bfile_free(&bfd);
469 6 : iobuf_free_content(rbuf);
470 6 : sbuf_free(&sb);
471 6 : return ret;
472 : }
473 :
474 6 : int backup_phase2_client_protocol1(struct asfd *asfd,
475 : struct conf **confs, int resume)
476 : {
477 6 : int ret=0;
478 6 : struct cntr *cntr=NULL;
479 6 : if(confs) cntr=get_cntr(confs);
480 :
481 6 : logp("Phase 2 begin (send backup data)\n");
482 6 : logfmt("\n");
483 :
484 6 : ret=do_backup_phase2_client(asfd, confs, resume);
485 :
486 6 : cntr_print_end(cntr);
487 6 : cntr_print(cntr, ACTION_BACKUP, asfd);
488 :
489 6 : if(ret) logp("Error in phase 2\n");
490 6 : logp("Phase 2 end (send file data)\n");
491 :
492 6 : return ret;
493 : }
|