LCOV - code coverage report
Current view: top level - src - sbuf.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 121 146 82.9 %
Date: 2022-05-01 01:22:11 Functions: 14 16 87.5 %

          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             : 
      13       32346 : struct sbuf *sbuf_alloc()
      14             : {
      15             :         struct sbuf *sb;
      16       32346 :         if(!(sb=(struct sbuf *)calloc_w(1, sizeof(struct sbuf), __func__)))
      17             :                 return NULL;
      18       32346 :         iobuf_init(&sb->path);
      19       32346 :         iobuf_init(&sb->attr);
      20       32346 :         sb->attr.cmd=CMD_ATTRIBS;
      21       32346 :         iobuf_init(&sb->link);
      22       32346 :         iobuf_init(&sb->endfile);
      23       32346 :         sb->compression=-1;
      24       32346 :         if(!(sb->protocol1=sbuf_protocol1_alloc())) return NULL;
      25       32346 :         return sb;
      26             : }
      27             : 
      28       59651 : void sbuf_free_content(struct sbuf *sb)
      29             : {
      30       59651 :         iobuf_free_content(&sb->path);
      31       59651 :         iobuf_free_content(&sb->attr);
      32       59651 :         iobuf_free_content(&sb->link);
      33       59651 :         iobuf_free_content(&sb->endfile);
      34       59651 :         memset(&(sb->statp), 0, sizeof(sb->statp));
      35       59651 :         sb->compression=-1;
      36       59651 :         sb->winattr=0;
      37       59651 :         sb->flags=0;
      38       59651 :         sbuf_protocol1_free_content(sb->protocol1);
      39       59651 : }
      40             : 
      41       32367 : void sbuf_free(struct sbuf **sb)
      42             : {
      43       32367 :         if(!sb || !*sb) return;
      44       32346 :         sbuf_free_content(*sb);
      45       32346 :         free_v((void **)&((*sb)->protocol1));
      46       32346 :         free_v((void **)sb);
      47             : }
      48             : 
      49          26 : int sbuf_is_link(struct sbuf *sb)
      50             : {
      51          26 :         return iobuf_is_link(&sb->path);
      52             : }
      53             : 
      54       24462 : int sbuf_is_filedata(struct sbuf *sb)
      55             : {
      56       32744 :         return iobuf_is_filedata(&sb->path);
      57             : }
      58             : 
      59        5060 : int sbuf_is_vssdata(struct sbuf *sb)
      60             : {
      61        5158 :         return iobuf_is_vssdata(&sb->path);
      62             : }
      63             : 
      64          38 : int sbuf_is_encrypted(struct sbuf *sb)
      65             : {
      66          38 :         return iobuf_is_encrypted(&sb->path);
      67             : }
      68             : 
      69           0 : int sbuf_is_metadata(struct sbuf *sb)
      70             : {
      71           0 :         return iobuf_is_metadata(&sb->path);
      72             : }
      73             : 
      74           0 : int sbuf_is_estimatable(struct sbuf *sb)
      75             : {
      76           0 :         return iobuf_is_estimatable(&sb->path);
      77             : }
      78             : 
      79       11932 : int sbuf_to_manifest(struct sbuf *sb, struct fzp *fzp)
      80             : {
      81       11932 :         if(!sb->path.buf) return 0;
      82             : 
      83       11932 :         if(sb->protocol1)
      84             :         {
      85       11932 :                 if(sb->protocol1->datapth.buf
      86        6324 :                   && iobuf_send_msg_fzp(&(sb->protocol1->datapth), fzp))
      87             :                         return -1;
      88             : 
      89       11932 :                 if(iobuf_send_msg_fzp(&sb->attr, fzp))
      90             :                         return -1;
      91             :         }
      92             :         else
      93             :         {
      94             :                 // Hackity hack: Strip the file index from the beginning of
      95             :                 // the attribs so that manifests where nothing changed are
      96             :                 // identical to each other. Better would be to preserve the
      97             :                 // index.
      98             :                 char *cp;
      99           0 :                 if(!(cp=strchr(sb->attr.buf, ' ')))
     100             :                 {
     101           0 :                         logp("Strange attributes: %s\n",
     102             :                                 iobuf_to_printable(&sb->attr));
     103           0 :                         return -1;
     104             :                 }
     105           0 :                 if(send_msg_fzp(fzp, CMD_ATTRIBS,
     106           0 :                         cp, sb->attr.len-(cp-sb->attr.buf)))
     107             :                                 return -1;
     108             :         }
     109       11932 :         if(iobuf_send_msg_fzp(&sb->path, fzp))
     110             :                 return -1;
     111       11932 :         if(sb->link.buf
     112        1426 :           && iobuf_send_msg_fzp(&sb->link, fzp))
     113             :                 return -1;
     114       11932 :         if(sb->endfile.buf
     115        6324 :           && iobuf_send_msg_fzp(&sb->endfile, fzp))
     116             :                 return -1;
     117             : 
     118             :         return 0;
     119             : }
     120             : 
     121          84 : int sbuf_to_manifest_cntr(struct sbuf *sb, struct fzp *fzp,
     122             :         enum cntr_manio what)
     123             : {
     124          84 :         if(!sb->path.buf) return 0;
     125          84 :         fzp_printf(fzp, "%c", (char)what);
     126          84 :         return iobuf_send_msg_fzp(&sb->path, fzp);
     127             : }
     128             : 
     129             : // Like pathcmp, but sort entries that have the same paths so that metadata
     130             : // comes later, and vss comes earlier, and trailing vss comes later.
     131          17 : int sbuf_pathcmp(struct sbuf *a, struct sbuf *b)
     132             : {
     133          17 :         return iobuf_pathcmp(&a->path, &b->path);
     134             : }
     135             : 
     136             : enum parse_ret
     137             : {
     138             :         PARSE_RET_ERROR=-1,
     139             :         PARSE_RET_NEED_MORE=0,
     140             :         PARSE_RET_COMPLETE=1,
     141             :         PARSE_RET_FINISHED=2,
     142             : };
     143             : 
     144       45359 : static enum parse_ret parse_cmd(struct sbuf *sb, struct asfd *asfd,
     145             :         struct iobuf *rbuf, struct cntr *cntr)
     146             : {
     147       45359 :         switch(rbuf->cmd)
     148             :         {
     149             :                 case CMD_ATTRIBS:
     150       13677 :                         if(sb->protocol1->datapth.buf)
     151        8316 :                                 iobuf_free_content(&sb->attr);
     152             :                         else
     153        5361 :                                 sbuf_free_content(sb);
     154       13677 :                         iobuf_move(&sb->attr, rbuf);
     155       13677 :                         attribs_decode(sb);
     156       13677 :                         return PARSE_RET_NEED_MORE;
     157             : 
     158             :                 case CMD_FILE:
     159             :                 case CMD_DIRECTORY:
     160             :                 case CMD_SOFT_LINK:
     161             :                 case CMD_HARD_LINK:
     162             :                 case CMD_SPECIAL:
     163             :                 // Stuff not currently supported in burp-2, but OK
     164             :                 // to find in burp-1.
     165             :                 case CMD_ENC_FILE:
     166             :                 case CMD_METADATA:
     167             :                 case CMD_ENC_METADATA:
     168             :                 case CMD_EFS_FILE:
     169             :                 case CMD_VSS:
     170             :                 case CMD_ENC_VSS:
     171             :                 case CMD_VSS_T:
     172             :                 case CMD_ENC_VSS_T:
     173       15064 :                         if(!sb->attr.buf)
     174             :                         {
     175           1 :                                 log_and_send(asfd, "read cmd with no attribs");
     176           1 :                                 return PARSE_RET_ERROR;
     177             :                         }
     178       15063 :                         if(sb->flags & SBUF_NEED_LINK)
     179             :                         {
     180        1396 :                                 if(cmd_is_link(rbuf->cmd))
     181             :                                 {
     182        1396 :                                         iobuf_free_content(&sb->link);
     183        1396 :                                         iobuf_move(&sb->link, rbuf);
     184        1396 :                                         sb->flags &= ~SBUF_NEED_LINK;
     185        1396 :                                         return PARSE_RET_COMPLETE;
     186             :                                 }
     187             :                                 else
     188             :                                 {
     189           0 :                                         log_and_send(asfd, "got non-link after link in manifest");
     190           0 :                                         return PARSE_RET_NEED_MORE;
     191             :                                 }
     192             :                         }
     193             :                         else
     194             :                         {
     195       13667 :                                 if(iobuf_relative_path_attack(rbuf))
     196             :                                         return PARSE_RET_ERROR;
     197             : 
     198       13667 :                                 iobuf_free_content(&sb->path);
     199       13667 :                                 iobuf_move(&sb->path, rbuf);
     200       13667 :                                 if(cmd_is_link(rbuf->cmd))
     201             :                                 {
     202        1396 :                                         sb->flags |= SBUF_NEED_LINK;
     203        1396 :                                         return PARSE_RET_NEED_MORE;
     204             :                                 }
     205       12271 :                                 else if(sb->protocol1
     206       12271 :                                   && sb->protocol1->datapth.buf)
     207             :                                 {
     208             :                                         // Protocol1 client restore reads
     209             :                                         // CMD_APPEND and CMD_END_FILE in the
     210             :                                         // calling function, so pretend it is
     211             :                                         // complete if we have the hack flag.
     212        8316 :                                         if(sb->flags & SBUF_CLIENT_RESTORE_HACK)
     213             :                                                 return PARSE_RET_COMPLETE;
     214        8312 :                                         return PARSE_RET_NEED_MORE;
     215             :                                 }
     216             :                                 return PARSE_RET_COMPLETE;
     217             :                         }
     218             :                 case CMD_MESSAGE:
     219             :                 case CMD_WARNING:
     220           0 :                         log_recvd(rbuf, cntr, 1);
     221           0 :                         return PARSE_RET_NEED_MORE;
     222             :                 case CMD_GEN:
     223          19 :                         if(!strcmp(rbuf->buf, "restoreend")
     224          17 :                           || !strcmp(rbuf->buf, "phase1end")
     225           1 :                           || !strcmp(rbuf->buf, "backupphase2")
     226             :                         // Think these are protocol1 things.
     227           1 :                           || !strcmp(rbuf->buf, "backupend")
     228           1 :                           || !strcmp(rbuf->buf, "estimateend"))
     229             :                                 return PARSE_RET_FINISHED;
     230           1 :                         iobuf_log_unexpected(rbuf, __func__);
     231           1 :                         return PARSE_RET_ERROR;
     232             :                 case CMD_MANIFEST:
     233           0 :                         if(iobuf_relative_path_attack(rbuf))
     234             :                                 return PARSE_RET_ERROR;
     235           0 :                         iobuf_free_content(&sb->path);
     236           0 :                         iobuf_move(&sb->path, rbuf);
     237           0 :                         return PARSE_RET_COMPLETE;
     238             :                 case CMD_ERROR:
     239           0 :                         logp("got error: %s\n", rbuf->buf);
     240           0 :                         return PARSE_RET_ERROR;
     241             :                 case CMD_DATAPTH:
     242        8317 :                         if(iobuf_relative_path_attack(rbuf))
     243             :                                 return PARSE_RET_ERROR;
     244             : 
     245        8317 :                         if(!sb->protocol1)
     246             :                         {
     247           0 :                                 iobuf_log_unexpected(rbuf, __func__);
     248           0 :                                 return PARSE_RET_ERROR;
     249             :                         }
     250        8317 :                         if(sb->flags & SBUF_CLIENT_RESTORE_HACK)
     251             :                         {
     252           5 :                                 sbuf_free_content(sb);
     253           5 :                                 sb->flags |= SBUF_CLIENT_RESTORE_HACK;
     254             :                         }
     255             :                         else
     256        8312 :                                 sbuf_free_content(sb);
     257             :                         
     258        8317 :                         iobuf_move(&sb->protocol1->datapth, rbuf);
     259        8317 :                         return PARSE_RET_NEED_MORE;
     260             :                 case CMD_END_FILE:
     261        8282 :                         iobuf_free_content(&sb->endfile);
     262        8282 :                         iobuf_move(&sb->endfile, rbuf);
     263        8282 :                         if(sb->protocol1)
     264             :                         {
     265        8282 :                                 if(!sb->attr.buf
     266        8282 :                                   || !sb->protocol1->datapth.buf
     267        8282 :                                   || (!sbuf_is_filedata(sb)
     268          98 :                                         && !sbuf_is_vssdata(sb)))
     269             :                                 {
     270           0 :                                         logp("got unexpected cmd_endfile");
     271           0 :                                         return PARSE_RET_ERROR;
     272             :                                 }
     273             :                         }
     274             :                         return PARSE_RET_COMPLETE;
     275             :                 default:
     276           0 :                         iobuf_log_unexpected(rbuf, __func__);
     277           0 :                         return PARSE_RET_ERROR;
     278             :         }
     279             :         logp("Fell out of switch unexpectedly in %s()\n", __func__);
     280             :         return PARSE_RET_ERROR;
     281             : }
     282             : 
     283       13791 : static int sbuf_fill(struct sbuf *sb, struct asfd *asfd, struct fzp *fzp,
     284             :         struct cntr *cntr)
     285             : {
     286             :         static struct iobuf *rbuf;
     287             :         static struct iobuf localrbuf;
     288       13791 :         int ret=-1;
     289             : 
     290       13791 :         if(asfd) rbuf=asfd->rbuf;
     291             :         else
     292             :         {
     293             :                 // If not given asfd, use our own iobuf.
     294       13777 :                 memset(&localrbuf, 0, sizeof(struct iobuf));
     295       13777 :                 rbuf=&localrbuf;
     296             :         }
     297             :         while(1)
     298             :         {
     299       77195 :                 iobuf_free_content(rbuf);
     300       45493 :                 if(fzp)
     301             :                 {
     302       45461 :                         if((ret=iobuf_fill_from_fzp(rbuf, fzp)))
     303             :                                 goto end;
     304             :                 }
     305             :                 else
     306             :                 {
     307          32 :                         if(asfd->read(asfd))
     308             :                         {
     309           1 :                                 logp("error in async_read\n");
     310           1 :                                 break;
     311             :                         }
     312             :                 }
     313       45359 :                 switch(parse_cmd(sb, asfd, rbuf, cntr))
     314             :                 {
     315             :                         case PARSE_RET_NEED_MORE:
     316       31702 :                                 continue;
     317             :                         case PARSE_RET_COMPLETE:
     318             :                                 return 0;
     319             :                         case PARSE_RET_FINISHED:
     320             :                                 ret=1;
     321             :                                 goto end;
     322             :                         case PARSE_RET_ERROR:
     323             :                         default:
     324           2 :                                 ret=-1;
     325           2 :                                 goto end;
     326             :                 }
     327             :         }
     328             : end:
     329         154 :         iobuf_free_content(rbuf);
     330         154 :         return ret;
     331             : }
     332             : 
     333          14 : int sbuf_fill_from_net(struct sbuf *sb, struct asfd *asfd,
     334             :         struct cntr *cntr)
     335             : {
     336          14 :         return sbuf_fill(sb, asfd, NULL, cntr);
     337             : }
     338             : 
     339       13777 : int sbuf_fill_from_file(struct sbuf *sb, struct fzp *fzp)
     340             : {
     341       13777 :         return sbuf_fill(sb, NULL, fzp, NULL);
     342             : }

Generated by: LCOV version 1.13