LCOV - code coverage report
Current view: top level - src/client/protocol1 - backup_phase2.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 155 212 73.1 %
Date: 2020-11-06 04:06:22 Functions: 9 10 90.0 %

          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_set_bytes(cntr, asfd);
     496           6 :         cntr_print(cntr, ACTION_BACKUP);
     497             : 
     498           6 :         if(ret) logp("Error in phase 2\n");
     499           6 :         logp("Phase 2 end (send file data)\n");
     500             : 
     501           6 :         return ret;
     502             : }

Generated by: LCOV version 1.13