LCOV - code coverage report
Current view: top level - src - sbuf.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 149 165 90.3 %
Date: 2020-11-06 04:06:22 Functions: 15 16 93.8 %

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

Generated by: LCOV version 1.13