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 2 : 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 2 : 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 4 : {
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 : }
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 : forget++;
246 0 : goto end;
247 : }
248 :
249 8 : if(size_checks(asfd, sb, confs))
250 : {
251 : forget++;
252 : goto end;
253 : }
254 :
255 8 : sb->compression=in_exclude_comp(get_strlist(confs[OPT_EXCOM]),
256 8 : sb->path.buf, conf_compression);
257 8 : if(attribs_encode(sb)) goto error;
258 :
259 16 : if(sb->path.cmd!=CMD_METADATA
260 8 : && sb->path.cmd!=CMD_ENC_METADATA)
261 : {
262 24 : if(bfd->open_for_send(bfd, asfd,
263 16 : sb->path.buf, sb->winattr,
264 : get_int(confs[OPT_ATIME]), cntr, PROTO_1))
265 : {
266 : forget++;
267 : goto end;
268 : }
269 : }
270 :
271 16 : if(sb->path.cmd==CMD_METADATA
272 : || sb->path.cmd==CMD_ENC_METADATA
273 8 : || sb->path.cmd==CMD_VSS
274 8 : || sb->path.cmd==CMD_ENC_VSS
275 : #ifdef HAVE_WIN32
276 : || get_int(confs[OPT_STRIP_VSS])
277 : #endif
278 : )
279 : {
280 0 : if(get_extrameta(asfd,
281 : #ifdef HAVE_WIN32
282 : bfd,
283 : #endif
284 0 : sb->path.buf,
285 0 : S_ISDIR(sb->statp.st_mode),
286 : &extrameta, &elen, cntr))
287 : {
288 0 : logw(asfd, cntr,
289 : "Meta data error for %s\n",
290 : iobuf_to_printable(&sb->path));
291 0 : forget++;
292 0 : goto end;
293 : }
294 0 : if(extrameta)
295 : {
296 : #ifdef HAVE_WIN32
297 : if(get_int(confs[OPT_STRIP_VSS]))
298 : {
299 : free_w(&extrameta);
300 : elen=0;
301 : }
302 : #endif
303 : }
304 : else
305 : {
306 0 : logw(asfd, cntr,
307 : "No meta data after all: %s\n",
308 : iobuf_to_printable(&sb->path));
309 0 : forget++;
310 0 : goto end;
311 : }
312 : }
313 :
314 8 : if(sb->path.cmd==CMD_FILE
315 4 : && sb->protocol1->datapth.buf)
316 2 : {
317 2 : uint64_t sentbytes=0;
318 : // Need to do sig/delta stuff.
319 2 : if(asfd->write(asfd, &(sb->protocol1->datapth))
320 2 : || asfd->write(asfd, &sb->attr)
321 2 : || asfd->write(asfd, &sb->path)
322 2 : || load_signature_and_send_delta(asfd, bfd,
323 : &bytes, &sentbytes, cntr))
324 : {
325 0 : logp("error in sig/delta for %s (%s)\n",
326 : iobuf_to_printable(&sb->path),
327 0 : iobuf_to_printable(&sb->protocol1->datapth));
328 0 : forget++;
329 0 : goto end;
330 : }
331 2 : cntr_add(cntr, CMD_FILE_CHANGED, 1);
332 : }
333 : else
334 : {
335 : //logp("need to send whole file: %s\n", sb.path);
336 : // send the whole file.
337 :
338 6 : if(asfd->write(asfd, &sb->attr)
339 6 : || asfd->write(asfd, &sb->path))
340 : goto end;
341 :
342 6 : switch(send_whole_file_w(asfd, sb, NULL, 0, &bytes,
343 : enc_password,
344 : cntr, sb->compression,
345 : bfd, extrameta, elen))
346 : {
347 : case SEND_OK:
348 : break;
349 : case SEND_ERROR:
350 0 : forget++;
351 0 : break;
352 : case SEND_FATAL:
353 : default:
354 : goto error;
355 : }
356 6 : cntr_add(cntr, sb->path.cmd, 1);
357 : }
358 8 : cntr_add_bytes(cntr, bytes);
359 :
360 : end:
361 8 : ret=0;
362 8 : if(forget && forget_file(asfd, sb, confs))
363 0 : ret=-1;
364 : error:
365 : #ifdef HAVE_WIN32
366 : // If using Windows do not close bfd - it needs
367 : // to stay open to read VSS/file data/VSS.
368 : // It will get closed either when given a
369 : // different file path, or when this function
370 : // exits.
371 : #else
372 8 : bfd->close(bfd, asfd);
373 : #endif
374 8 : sbuf_free_content(sb);
375 8 : free_w(&extrameta);
376 8 : return ret;
377 : }
378 :
379 19 : static int parse_rbuf(struct asfd *asfd, struct sbuf *sb,
380 : struct BFILE *bfd, struct conf **confs)
381 : {
382 : static struct iobuf *rbuf;
383 19 : rbuf=asfd->rbuf;
384 19 : if(rbuf->cmd==CMD_DATAPTH)
385 : {
386 2 : iobuf_move(&(sb->protocol1->datapth), rbuf);
387 : }
388 17 : else if(rbuf->cmd==CMD_ATTRIBS)
389 : {
390 : // Ignore the stat data - we will fill it
391 : // in again. Some time may have passed by now,
392 : // and it is best to make it as fresh as
393 : // possible.
394 : }
395 9 : else if(iobuf_is_filedata(rbuf)
396 1 : || iobuf_is_vssdata(rbuf))
397 : {
398 8 : if(deal_with_data(asfd, sb, bfd, confs))
399 : return -1;
400 : }
401 2 : else if(rbuf->cmd==CMD_MESSAGE
402 1 : || rbuf->cmd==CMD_WARNING)
403 : {
404 1 : struct cntr *cntr=NULL;
405 1 : if(confs) cntr=get_cntr(confs);
406 1 : log_recvd(rbuf, cntr, 0);
407 : }
408 : else
409 : {
410 0 : iobuf_log_unexpected(rbuf, __func__);
411 0 : return -1;
412 : }
413 : return 0;
414 : }
415 :
416 6 : static int do_backup_phase2_client(struct asfd *asfd,
417 : struct conf **confs, int resume)
418 : {
419 6 : int ret=-1;
420 : // For efficiency, open Windows files for the VSS data, and do not
421 : // close them until another time around the loop, when the actual
422 : // data is read.
423 6 : struct BFILE *bfd=NULL;
424 6 : struct sbuf *sb=NULL;
425 6 : struct iobuf *rbuf=NULL;
426 6 : struct cntr *cntr=NULL;
427 6 : if(confs) cntr=get_cntr(confs);
428 :
429 6 : if(!asfd)
430 : {
431 1 : logp("%s() called without asfd!\n", __func__);
432 1 : goto end;
433 : }
434 5 : rbuf=asfd->rbuf;
435 :
436 5 : if(!(bfd=bfile_alloc())
437 5 : || !(sb=sbuf_alloc(PROTO_1)))
438 : goto end;
439 5 : bfile_init(bfd, 0, cntr);
440 :
441 5 : if(!resume)
442 : {
443 : // Only do this bit if the server did not tell us to resume.
444 5 : if(asfd->write_str(asfd, CMD_GEN, "backupphase2")
445 5 : || asfd_read_expect(asfd, CMD_GEN, "ok"))
446 : goto end;
447 : }
448 : else
449 : {
450 : // On resume, the server might update the client with cntr.
451 0 : if(cntr_recv(asfd, confs))
452 : goto end;
453 : }
454 :
455 : while(1)
456 : {
457 24 : iobuf_free_content(rbuf);
458 24 : if(asfd->read(asfd)) goto end;
459 23 : else if(!rbuf->buf) continue;
460 :
461 23 : if(rbuf->cmd==CMD_GEN && !strcmp(rbuf->buf, "backupphase2end"))
462 : {
463 4 : if(asfd->write_str(asfd, CMD_GEN, "okbackupphase2end"))
464 : goto end;
465 4 : ret=0;
466 4 : break;
467 : }
468 :
469 19 : if(parse_rbuf(asfd, sb, bfd, confs))
470 : goto end;
471 : }
472 :
473 : end:
474 : // It is possible for a bfd to still be open.
475 6 : if(bfd) bfd->close(bfd, asfd);
476 6 : bfile_free(&bfd);
477 6 : iobuf_free_content(rbuf);
478 6 : sbuf_free(&sb);
479 6 : return ret;
480 : }
481 :
482 6 : int backup_phase2_client_protocol1(struct asfd *asfd,
483 : struct conf **confs, int resume)
484 : {
485 6 : int ret=0;
486 6 : struct cntr *cntr=NULL;
487 6 : if(confs) cntr=get_cntr(confs);
488 :
489 6 : logp("Phase 2 begin (send backup data)\n");
490 6 : logfmt("\n");
491 :
492 6 : ret=do_backup_phase2_client(asfd, confs, resume);
493 :
494 6 : cntr_print_end(cntr);
495 6 : cntr_print(cntr, ACTION_BACKUP, asfd);
496 :
497 6 : if(ret) logp("Error in phase 2\n");
498 6 : logp("Phase 2 end (send file data)\n");
499 :
500 6 : return ret;
501 : }
|