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