LCOV - code coverage report
Current view: top level - src - sbuf.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 140 156 89.7 %
Date: 2018-03-30 Functions: 14 15 93.3 %

          Line data    Source code
       1             : #include "burp.h"
       2             : #include "sbuf.h"
       3             : #include "alloc.h"
       4             : #include "asfd.h"
       5             : #include "attribs.h"
       6             : #include "cmd.h"
       7             : #include "conf.h"
       8             : #include "handy.h"
       9             : #include "log.h"
      10             : #include "msg.h"
      11             : #include "protocol2/blk.h"
      12             : 
      13      132952 : struct sbuf *sbuf_alloc(enum protocol protocol)
      14             : {
      15             :         struct sbuf *sb;
      16      132952 :         if(!(sb=(struct sbuf *)calloc_w(1, sizeof(struct sbuf), __func__)))
      17             :                 return NULL;
      18      132952 :         iobuf_init(&sb->path);
      19      132952 :         iobuf_init(&sb->attr);
      20      132952 :         sb->attr.cmd=CMD_ATTRIBS;
      21      132952 :         iobuf_init(&sb->link);
      22      132952 :         iobuf_init(&sb->endfile);
      23      132952 :         sb->compression=-1;
      24      132952 :         if(protocol==PROTO_1)
      25             :         {
      26       32297 :                 if(!(sb->protocol1=sbuf_protocol1_alloc())) return NULL;
      27             :         }
      28             :         else
      29             :         {
      30      100655 :                 if(!(sb->protocol2=sbuf_protocol2_alloc())) return NULL;
      31             :         }
      32      132952 :         return sb;
      33             : }
      34             : 
      35      229752 : void sbuf_free_content(struct sbuf *sb)
      36             : {
      37      229752 :         iobuf_free_content(&sb->path);
      38      229752 :         iobuf_free_content(&sb->attr);
      39      229752 :         iobuf_free_content(&sb->link);
      40      229752 :         iobuf_free_content(&sb->endfile);
      41      229752 :         memset(&(sb->statp), 0, sizeof(sb->statp));
      42      229752 :         sb->compression=-1;
      43      229752 :         sb->winattr=0;
      44      229752 :         sb->flags=0;
      45      229752 :         sbuf_protocol1_free_content(sb->protocol1);
      46      229752 :         sbuf_protocol2_free_content();
      47      229752 : }
      48             : 
      49      383712 : void sbuf_free(struct sbuf **sb)
      50             : {
      51      767424 :         if(!sb || !*sb) return;
      52      132952 :         sbuf_free_content(*sb);
      53      132952 :         free_v((void **)&((*sb)->protocol1));
      54      132952 :         free_v((void **)&((*sb)->protocol2));
      55      132952 :         free_v((void **)sb);
      56             : }
      57             : 
      58         110 : int sbuf_is_link(struct sbuf *sb)
      59             : {
      60         110 :         return iobuf_is_link(&sb->path);
      61             : }
      62             : 
      63      219249 : int sbuf_is_filedata(struct sbuf *sb)
      64             : {
      65      227518 :         return iobuf_is_filedata(&sb->path);
      66             : }
      67             : 
      68       10733 : int sbuf_is_vssdata(struct sbuf *sb)
      69             : {
      70       10831 :         return iobuf_is_vssdata(&sb->path);
      71             : }
      72             : 
      73       85249 : int sbuf_is_encrypted(struct sbuf *sb)
      74             : {
      75       85249 :         return iobuf_is_encrypted(&sb->path);
      76             : }
      77             : 
      78         115 : int sbuf_is_metadata(struct sbuf *sb)
      79             : {
      80         115 :         return iobuf_is_metadata(&sb->path);
      81             : }
      82             : 
      83           0 : int sbuf_is_estimatable(struct sbuf *sb)
      84             : {
      85           0 :         return iobuf_is_estimatable(&sb->path);
      86             : }
      87             : 
      88       91874 : int sbuf_to_manifest(struct sbuf *sb, struct fzp *fzp)
      89             : {
      90       91874 :         if(!sb->path.buf) return 0;
      91             : 
      92       91874 :         if(sb->protocol1)
      93             :         {
      94       11912 :                 if(sb->protocol1->datapth.buf
      95        6311 :                   && iobuf_send_msg_fzp(&(sb->protocol1->datapth), fzp))
      96             :                         return -1;
      97             : 
      98       11912 :                 if(iobuf_send_msg_fzp(&sb->attr, fzp))
      99             :                         return -1;
     100             :         }
     101             :         else
     102             :         {
     103             :                 // Hackity hack: Strip the file index from the beginning of
     104             :                 // the attribs so that manifests where nothing changed are
     105             :                 // identical to each other. Better would be to preserve the
     106             :                 // index.
     107             :                 char *cp;
     108       79962 :                 if(!(cp=strchr(sb->attr.buf, ' ')))
     109             :                 {
     110           0 :                         logp("Strange attributes: %s\n",
     111             :                                 iobuf_to_printable(&sb->attr));
     112           0 :                         return -1;
     113             :                 }
     114       79962 :                 if(send_msg_fzp(fzp, CMD_ATTRIBS,
     115       79962 :                         cp, sb->attr.len-(cp-sb->attr.buf)))
     116             :                                 return -1;
     117             :         }
     118       91874 :         if(iobuf_send_msg_fzp(&sb->path, fzp))
     119             :                 return -1;
     120       91874 :         if(sb->link.buf
     121       15876 :           && iobuf_send_msg_fzp(&sb->link, fzp))
     122             :                 return -1;
     123       91874 :         if(sb->endfile.buf
     124        6315 :           && iobuf_send_msg_fzp(&sb->endfile, fzp))
     125             :                 return -1;
     126             : 
     127             :         return 0;
     128             : }
     129             : 
     130             : // Like pathcmp, but sort entries that have the same paths so that metadata
     131             : // comes later, and vss comes earlier, and trailing vss comes later.
     132          23 : int sbuf_pathcmp(struct sbuf *a, struct sbuf *b)
     133             : {
     134          23 :         return iobuf_pathcmp(&a->path, &b->path);
     135             : }
     136             : 
     137             : enum parse_ret
     138             : {
     139             :         PARSE_RET_ERROR=-1,
     140             :         PARSE_RET_NEED_MORE=0,
     141             :         PARSE_RET_COMPLETE=1,
     142             :         PARSE_RET_FINISHED=2,
     143             : };
     144             : 
     145      354856 : static enum parse_ret parse_cmd(struct sbuf *sb, struct asfd *asfd,
     146             :         struct iobuf *rbuf, struct blk *blk, struct cntr *cntr)
     147             : {
     148      354856 :         switch(rbuf->cmd)
     149             :         {
     150             :                 case CMD_ATTRIBS:
     151       60754 :                         if(sb->protocol2)
     152       47097 :                                 sbuf_free_content(sb);
     153             :                         else
     154             :                         {
     155       13657 :                                 if(sb->protocol1->datapth.buf)
     156             :                                         // protocol 1 phase 2+ file data
     157             :                                         // starts with datapth.
     158        8303 :                                         iobuf_free_content(&sb->attr);
     159             :                                 else
     160             :                                         // protocol 1 phase 1 or non file data
     161             :                                         // starts with attribs
     162        5354 :                                         sbuf_free_content(sb);
     163             :                         }
     164       60754 :                         iobuf_move(&sb->attr, rbuf);
     165       60754 :                         attribs_decode(sb);
     166       60754 :                         return PARSE_RET_NEED_MORE;
     167             : 
     168             :                 case CMD_FILE:
     169             :                 case CMD_DIRECTORY:
     170             :                 case CMD_SOFT_LINK:
     171             :                 case CMD_HARD_LINK:
     172             :                 case CMD_SPECIAL:
     173             :                 // Stuff not currently supported in burp-2, but OK
     174             :                 // to find in burp-1.
     175             :                 case CMD_ENC_FILE:
     176             :                 case CMD_METADATA:
     177             :                 case CMD_ENC_METADATA:
     178             :                 case CMD_EFS_FILE:
     179             :                 case CMD_VSS:
     180             :                 case CMD_ENC_VSS:
     181             :                 case CMD_VSS_T:
     182             :                 case CMD_ENC_VSS_T:
     183       69859 :                         if(!sb->attr.buf)
     184             :                         {
     185           1 :                                 log_and_send(asfd, "read cmd with no attribs");
     186           1 :                                 return PARSE_RET_ERROR;
     187             :                         }
     188       69858 :                         if(sb->flags & SBUF_NEED_LINK)
     189             :                         {
     190        9124 :                                 if(cmd_is_link(rbuf->cmd))
     191             :                                 {
     192        9124 :                                         iobuf_free_content(&sb->link);
     193        9124 :                                         iobuf_move(&sb->link, rbuf);
     194        9124 :                                         sb->flags &= ~SBUF_NEED_LINK;
     195        9124 :                                         return PARSE_RET_COMPLETE;
     196             :                                 }
     197             :                                 else
     198             :                                 {
     199           0 :                                         log_and_send(asfd, "got non-link after link in manifest");
     200           0 :                                         return PARSE_RET_NEED_MORE;
     201             :                                 }
     202             :                         }
     203             :                         else
     204             :                         {
     205       60734 :                                 iobuf_free_content(&sb->path);
     206       60734 :                                 iobuf_move(&sb->path, rbuf);
     207       60734 :                                 if(cmd_is_link(rbuf->cmd))
     208             :                                 {
     209        9124 :                                         sb->flags |= SBUF_NEED_LINK;
     210        9124 :                                         return PARSE_RET_NEED_MORE;
     211             :                                 }
     212       51610 :                                 else if(sb->protocol1
     213       12254 :                                   && sb->protocol1->datapth.buf)
     214             :                                 {
     215             :                                         // Protocol1 client restore reads
     216             :                                         // CMD_APPEND and CMD_END_FILE in the
     217             :                                         // calling function, so pretend it is
     218             :                                         // complete if we have the hack flag.
     219        8303 :                                         if(sb->flags & SBUF_CLIENT_RESTORE_HACK)
     220             :                                                 return PARSE_RET_COMPLETE;
     221        8299 :                                         return PARSE_RET_NEED_MORE;
     222             :                                 }
     223             :                                 return PARSE_RET_COMPLETE;
     224             :                         }
     225             : #ifndef HAVE_WIN32
     226             :                 case CMD_SIG:
     227             :                         // Fill in the sig/block, if the caller provided
     228             :                         // a pointer for one. Server only.
     229      198651 :                         if(!blk) return PARSE_RET_NEED_MORE;
     230             : 
     231             :                         // Just fill in the sig details.
     232       46462 :                         if(blk_set_from_iobuf_sig_and_savepath(blk, rbuf))
     233             :                                 return PARSE_RET_ERROR;
     234       46462 :                         blk->got_save_path=1;
     235       46462 :                         iobuf_free_content(rbuf);
     236       46462 :                         return PARSE_RET_COMPLETE;
     237             : #endif
     238             :                 case CMD_DATA:
     239             :                         // Need to write the block to disk.
     240             :                         // Client only.
     241          14 :                         if(!blk) return PARSE_RET_NEED_MORE;
     242          14 :                         blk->data=rbuf->buf;
     243          14 :                         blk->length=rbuf->len;
     244          14 :                         rbuf->buf=NULL;
     245          14 :                         return PARSE_RET_COMPLETE;
     246             :                 case CMD_MESSAGE:
     247             :                 case CMD_WARNING:
     248           0 :                         log_recvd(rbuf, cntr, 1);
     249           0 :                         return PARSE_RET_NEED_MORE;
     250             :                 case CMD_GEN:
     251          43 :                         if(!strcmp(rbuf->buf, "restoreend")
     252          39 :                           || !strcmp(rbuf->buf, "phase1end")
     253           1 :                           || !strcmp(rbuf->buf, "backupphase2")
     254             :                         // Think these are protocol1 things.
     255           1 :                           || !strcmp(rbuf->buf, "backupend")
     256           1 :                           || !strcmp(rbuf->buf, "estimateend"))
     257             :                                 return PARSE_RET_FINISHED;
     258           1 :                         iobuf_log_unexpected(rbuf, __func__);
     259           1 :                         return PARSE_RET_ERROR;
     260             :                 case CMD_FINGERPRINT:
     261         698 :                         if(blk && blk_set_from_iobuf_fingerprint(blk, rbuf))
     262             :                                 return PARSE_RET_ERROR;
     263             :                         // Fall through.
     264             :                 case CMD_MANIFEST:
     265         778 :                         iobuf_free_content(&sb->path);
     266         778 :                         iobuf_move(&sb->path, rbuf);
     267         778 :                         return PARSE_RET_COMPLETE;
     268             :                 case CMD_ERROR:
     269           0 :                         logp("got error: %s\n", rbuf->buf);
     270           0 :                         return PARSE_RET_ERROR;
     271             :                 case CMD_DATAPTH:
     272        8304 :                         if(!sb->protocol1)
     273             :                         {
     274           0 :                                 iobuf_log_unexpected(rbuf, __func__);
     275           0 :                                 return PARSE_RET_ERROR;
     276             :                         }
     277        8304 :                         if(sb->flags & SBUF_CLIENT_RESTORE_HACK)
     278             :                         {
     279           5 :                                 sbuf_free_content(sb);
     280           5 :                                 sb->flags |= SBUF_CLIENT_RESTORE_HACK;
     281             :                         }
     282             :                         else
     283        8299 :                                 sbuf_free_content(sb);
     284             :                         
     285        8304 :                         iobuf_move(&sb->protocol1->datapth, rbuf);
     286        8304 :                         return PARSE_RET_NEED_MORE;
     287             :                 case CMD_END_FILE:
     288       16453 :                         iobuf_free_content(&sb->endfile);
     289       16453 :                         iobuf_move(&sb->endfile, rbuf);
     290       16453 :                         if(sb->protocol1)
     291             :                         {
     292        8269 :                                 if(!sb->attr.buf
     293        8269 :                                   || !sb->protocol1->datapth.buf
     294        8269 :                                   || (!sbuf_is_filedata(sb)
     295          98 :                                         && !sbuf_is_vssdata(sb)))
     296             :                                 {
     297           0 :                                         logp("got unexpected cmd_endfile");
     298           0 :                                         return PARSE_RET_ERROR;
     299             :                                 }
     300             :                         }
     301             :                         return PARSE_RET_COMPLETE;
     302             :                 default:
     303           0 :                         iobuf_log_unexpected(rbuf, __func__);
     304           0 :                         return PARSE_RET_ERROR;
     305             :         }
     306             :         logp("Fell out of switch unexpectedly in %s()\n", __func__);
     307             :         return PARSE_RET_ERROR;
     308             : }
     309             : 
     310      116571 : static int sbuf_fill(struct sbuf *sb, struct asfd *asfd, struct fzp *fzp,
     311             :         struct blk *blk, struct cntr *cntr)
     312             : {
     313             :         static struct iobuf *rbuf;
     314             :         static struct iobuf localrbuf;
     315      116571 :         int ret=-1;
     316             : 
     317      116571 :         if(asfd) rbuf=asfd->rbuf;
     318             :         else
     319             :         {
     320             :                 // If not given asfd, use our own iobuf.
     321             :                 memset(&localrbuf, 0, sizeof(struct iobuf));
     322      116518 :                 rbuf=&localrbuf;
     323             :         }
     324             :         while(1)
     325             :         {
     326      355241 :                 iobuf_free_content(rbuf);
     327      355241 :                 if(fzp)
     328             :                 {
     329      355145 :                         if((ret=iobuf_fill_from_fzp(rbuf, fzp)))
     330             :                                 goto end;
     331             :                 }
     332             :                 else
     333             :                 {
     334          96 :                         if(asfd->read(asfd))
     335             :                         {
     336           1 :                                 logp("error in async_read\n");
     337           1 :                                 break;
     338             :                         }
     339             :                 }
     340      354856 :                 switch(parse_cmd(sb, asfd, rbuf, blk, cntr))
     341             :                 {
     342             :                         case PARSE_RET_NEED_MORE:
     343      238670 :                                 continue;
     344             :                         case PARSE_RET_COMPLETE:
     345             :                                 return 0;
     346             :                         case PARSE_RET_FINISHED:
     347             :                                 ret=1;
     348             :                                 goto end;
     349             :                         case PARSE_RET_ERROR:
     350             :                         default:
     351           2 :                                 ret=-1;
     352           2 :                                 goto end;
     353             :                 }
     354      238670 :         }
     355             : end:
     356         429 :         iobuf_free_content(rbuf);
     357         429 :         return ret;
     358             : }
     359             : 
     360          53 : int sbuf_fill_from_net(struct sbuf *sb, struct asfd *asfd,
     361             :         struct blk *blk, struct cntr *cntr)
     362             : {
     363          53 :         return sbuf_fill(sb, asfd, NULL, blk, cntr);
     364             : }
     365             : 
     366      116518 : int sbuf_fill_from_file(struct sbuf *sb, struct fzp *fzp,
     367             :         struct blk *blk)
     368             : {
     369      116518 :         return sbuf_fill(sb, NULL, fzp, blk, NULL);
     370             : }

Generated by: LCOV version 1.10