LCOV - code coverage report
Current view: top level - src/server - list.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 127 169 75.1 %
Date: 2021-05-02 03:18:47 Functions: 10 11 90.9 %

          Line data    Source code
       1             : #include "../burp.h"
       2             : #include "../alloc.h"
       3             : #include "../asfd.h"
       4             : #include "../async.h"
       5             : #include "../attribs.h"
       6             : #include "../bu.h"
       7             : #include "../cmd.h"
       8             : #include "../cntr.h"
       9             : #include "../cstat.h"
      10             : #include "../log.h"
      11             : #include "../prepend.h"
      12             : #include "../regexp.h"
      13             : #include "bu_get.h"
      14             : #include "child.h"
      15             : #include "list.h"
      16             : #include "manio.h"
      17             : 
      18             : enum list_mode
      19             : {
      20             :         LIST_MODE_BACKUPS=0,
      21             :         LIST_MODE_CONTENTS_ONE,
      22             :         LIST_MODE_CONTENTS_MANY,
      23             : };
      24             : 
      25             : static struct asfd *asfd;
      26             : static struct conf **confs;
      27             : static struct cntr *cntr;
      28             : static enum protocol protocol;
      29             : static const char *backup;
      30             : static regex_t *regex=NULL;
      31             : static const char *browsedir;
      32             : static struct bu *bu_list=NULL;
      33             : static enum list_mode list_mode;
      34             : static unsigned long bno=0;
      35             : 
      36          57 : int list_server_init(
      37             :         struct asfd *a,
      38             :         struct sdirs *s,
      39             :         struct conf **c,
      40             :         enum protocol p,
      41             :         const char *backup_str,
      42             :         const char *regex_str,
      43             :         const char *browsedir_str)
      44             : {
      45          57 :         int regex_case_insensitive=0;
      46          57 :         asfd=a;
      47          57 :         confs=c;
      48          57 :         protocol=p;
      49          57 :         backup=backup_str;
      50          57 :         browsedir=browsedir_str;
      51          57 :         if(confs)
      52             :         {
      53           1 :                 cntr=get_cntr(confs);
      54           1 :                 regex_case_insensitive=get_int(
      55           1 :                         confs[OPT_REGEX_CASE_INSENSITIVE]
      56             :                 );
      57             :         }
      58             : 
      59          57 :         if(bu_get_list_with_working(s, &bu_list))
      60             :                 goto error;
      61          57 :         if(regex_str
      62           9 :           && *regex_str
      63           9 :           && !(regex=regex_compile_restore( regex_str, regex_case_insensitive)))
      64             :         {
      65           1 :                 char msg[256]="";
      66           1 :                 snprintf(msg, sizeof(msg), "unable to compile regex: %s\n",
      67             :                         regex_str);
      68           1 :                 log_and_send(asfd, msg);
      69             :                 goto error;
      70             :         }
      71          56 :         list_mode=LIST_MODE_BACKUPS;
      72          56 :         if(regex || browsedir)
      73          16 :                 list_mode=LIST_MODE_CONTENTS_MANY;
      74          56 :         if(backup && *backup)
      75             :         {
      76          42 :                 if((bno=strtoul(backup, NULL, 10))>0)
      77          19 :                         list_mode=LIST_MODE_CONTENTS_ONE;
      78          23 :                 else if(*backup=='c')
      79           8 :                         list_mode=LIST_MODE_CONTENTS_ONE;
      80          15 :                 else if(*backup=='a')
      81          11 :                         list_mode=LIST_MODE_CONTENTS_MANY;
      82             :                 else
      83           4 :                         list_mode=LIST_MODE_CONTENTS_ONE;
      84             :         }
      85             :         return 0;
      86             : error:
      87             :         list_server_free();
      88           1 :         return -1;
      89             : }
      90             : 
      91          57 : void list_server_free(void)
      92             : {
      93          58 :         bu_list_free(&bu_list);
      94          58 :         regex_free(&regex);
      95          57 : }
      96             : 
      97             : #ifndef UTEST
      98             : static
      99             : #endif
     100          51 : void maybe_fake_directory(struct sbuf *mb)
     101             : {
     102          51 :         if(S_ISDIR(mb->statp.st_mode))
     103             :                 return;
     104             :         // We are faking a directory entry.
     105             :         // Make sure the directory bit is set.
     106          49 :         mb->statp.st_mode &= ~(S_IFMT);
     107          49 :         mb->statp.st_mode |= S_IFDIR;
     108             : 
     109             :         // Need to free attr so that it is reallocated, because it may get
     110             :         // longer than what we initially had.
     111          49 :         iobuf_free_content(&mb->attr);
     112          49 :         attribs_encode(mb);
     113             : }
     114             : 
     115          77 : int check_browsedir(const char *browsedir,
     116             :         struct sbuf *mb, size_t bdlen, char **last_bd_match)
     117             : {
     118          77 :         char *cp=mb->path.buf;
     119          77 :         char *copy=NULL;
     120          77 :         if(bdlen>0)
     121             :         {
     122          42 :                 if(strncmp(browsedir, cp, bdlen))
     123             :                         return 0;
     124          30 :                 cp+=bdlen;
     125          30 :                 if(browsedir[bdlen-1]!='/')
     126             :                 {
     127          24 :                         if(*cp!='\0')
     128             :                         {
     129          20 :                                 if(*cp!='/')
     130             :                                         return 0;
     131          18 :                                 cp++;
     132             :                         }
     133             :                 }
     134             :         }
     135          63 :         if(*cp=='\0')
     136           8 :                 cp=(char *)".";
     137          63 :         if(!(copy=strdup_w(cp, __func__)))
     138             :                 goto error;
     139          62 :         if((cp=strchr(copy, '/')))
     140             :         {
     141          40 :                 if(bdlen==0) cp++;
     142          40 :                 *cp='\0';
     143             : 
     144          40 :                 maybe_fake_directory(mb);
     145             :         }
     146          22 :         else if(!strcmp(mb->path.buf, "/")
     147           2 :           && !strcmp(browsedir, "/"))
     148           2 :                 maybe_fake_directory(mb);
     149          20 :         else if(mb->path.cmd==CMD_DIRECTORY)
     150           8 :                 maybe_fake_directory(mb);
     151             : 
     152             :         // Strip off possible trailing slash.
     153          62 :         if((cp=strrchr(copy, '/')) && cp>copy)
     154          14 :                 *cp='\0';
     155             : 
     156          62 :         if(*last_bd_match
     157          50 :           && !strcmp(*last_bd_match, copy))
     158             :         {
     159             :                 // Got a duplicate match.
     160          22 :                 free_w(&copy);
     161          22 :                 return 0;
     162             :         }
     163          40 :         free_w(&mb->path.buf);
     164          40 :         mb->path.buf=copy;
     165          40 :         free_w(last_bd_match);
     166          40 :         if(!(*last_bd_match=strdup_w(copy, __func__)))
     167             :                 goto error;
     168             :         return 1;
     169             : error:
     170           1 :         free_w(&copy);
     171           1 :         log_out_of_memory(__func__);
     172           1 :         return -1;
     173             : }
     174             : 
     175           0 : static int list_manifest(const char *fullpath)
     176             : {
     177           0 :         int ret=0;
     178           0 :         struct sbuf *sb=NULL;
     179           0 :         struct manio *manio=NULL;
     180           0 :         char *manifest_dir=NULL;
     181           0 :         char *last_bd_match=NULL;
     182           0 :         size_t bdlen=0;
     183             : 
     184           0 :         if(!(manifest_dir=prepend_s(fullpath,
     185           0 :                 protocol==PROTO_1?"manifest.gz":"manifest"))
     186           0 :           || !(manio=manio_open(manifest_dir, "rb", protocol))
     187           0 :           || !(sb=sbuf_alloc(protocol)))
     188             :         {
     189           0 :                 log_and_send_oom(asfd);
     190           0 :                 goto error;
     191             :         }
     192             : 
     193           0 :         if(browsedir) bdlen=strlen(browsedir);
     194             : 
     195             :         while(1)
     196             :         {
     197           0 :                 sbuf_free_content(sb);
     198             : 
     199           0 :                 switch(manio_read(manio, sb))
     200             :                 {
     201             :                         case 0: break;
     202           0 :                         case 1: if(browsedir && *browsedir && !last_bd_match)
     203           0 :                                         asfd_write_wrapper_str(asfd,
     204             :                                                 CMD_ERROR,
     205             :                                                 "directory not found");
     206             :                                 goto end; // Finished OK.
     207             :                         default: goto error;
     208             :                 }
     209             : 
     210           0 :                 if(protocol==PROTO_2 && sb->endfile.buf)
     211           0 :                         continue;
     212           0 :                 if(sbuf_is_metadata(sb))
     213           0 :                         continue;
     214             : 
     215           0 :                 if(timed_operation_status_only(CNTR_STATUS_LISTING,
     216           0 :                         sb->path.buf, confs)) goto error;
     217             : 
     218           0 :                 if(browsedir)
     219             :                 {
     220             :                         int r;
     221           0 :                         if((r=check_browsedir(browsedir,
     222             :                                 sb, bdlen, &last_bd_match))<0)
     223             :                                         goto error;
     224           0 :                         if(!r) continue;
     225             :                 }
     226             : 
     227           0 :                 if(regex && !regex_check(regex, sb->path.buf))
     228           0 :                         continue;
     229             : 
     230           0 :                 if(asfd_write_wrapper(asfd, &sb->attr)
     231           0 :                   || asfd_write_wrapper(asfd, &sb->path))
     232             :                         goto error;
     233           0 :                 if(sbuf_is_link(sb)
     234           0 :                   && asfd_write_wrapper(asfd, &sb->link))
     235             :                         goto error;
     236             :         }
     237             : 
     238             : error:
     239             :         ret=-1;
     240             : end:
     241           0 :         sbuf_free(&sb);
     242           0 :         free_w(&manifest_dir);
     243           0 :         manio_close(&manio);
     244           0 :         free_w(&last_bd_match);
     245           0 :         return ret;
     246             : }
     247             : 
     248          73 : static char *get_extradesc(struct bu *bu)
     249             : {
     250          73 :         if(bu->flags & BU_WORKING)
     251           0 :                 return strdup_w(" (working)", __func__);
     252          73 :         else if(bu->flags & BU_FINISHING)
     253           0 :                 return strdup_w(" (finishing)", __func__);
     254             :         // Protocol2 backups are all deletable, so do not mention it.
     255          73 :         else if(bu->flags & BU_DELETABLE && protocol==1)
     256          19 :                 return strdup_w(" (deletable)", __func__);
     257          54 :         return strdup_w("", __func__);
     258             : }
     259             : 
     260          73 : static int send_backup_name_to_client(struct bu *bu)
     261             : {
     262             :         int ret;
     263          73 :         char msg[64]="";
     264             :         char *extradesc;
     265          73 :         if(!(extradesc=get_extradesc(bu)))
     266             :                 return -1;
     267          73 :         snprintf(msg, sizeof(msg), "%s%s", bu->timestamp, extradesc);
     268          73 :         ret=asfd_write_wrapper_str(asfd, CMD_TIMESTAMP, msg);
     269          73 :         free_w(&extradesc);
     270          73 :         return ret;
     271             : }
     272             : 
     273             : static int list_all_backups(void)
     274             : {
     275          10 :         int found=0;
     276          10 :         struct bu *bu=NULL;
     277          24 :         for(bu=bu_list; bu; bu=bu->next)
     278             :         {
     279          15 :                 found=1;
     280          15 :                 if(send_backup_name_to_client(bu))
     281             :                         return -1;
     282             :         }
     283             :         return found;
     284             : }
     285             : 
     286          31 : static int list_contents_one(
     287             :         int list_server_callback(const char *fullpath))
     288             : {
     289          31 :         struct bu *bu=NULL;
     290          73 :         for(bu=bu_list; bu; bu=bu->next)
     291             :         {
     292          65 :                 if(!strcmp(bu->timestamp, backup)
     293          65 :                   || bu->bno==bno
     294          50 :                   || (*backup=='c' && (bu->flags & BU_CURRENT)))
     295             :                 {
     296          23 :                         if(cntr)
     297           0 :                                 cntr->bno=bu->bno;
     298          23 :                         if(send_backup_name_to_client(bu)
     299          22 :                           || list_server_callback(bu->path))
     300             :                                 return -1;
     301             :                         return 1;
     302             :                 }
     303             :         }
     304             :         return 0;
     305             : }
     306             : 
     307          15 : static int list_contents_many(
     308             :         int list_server_callback(const char *fullpath))
     309             : {
     310          15 :         int found=0;
     311          15 :         struct bu *bu=NULL;
     312          47 :         for(bu=bu_list; bu; bu=bu->next)
     313             :         {
     314          35 :                 found=1;
     315          35 :                 if(cntr)
     316           0 :                         cntr->bno=bu->bno;
     317          35 :                 if(send_backup_name_to_client(bu)
     318          34 :                   || list_server_callback(bu->path))
     319             :                         return -1;
     320             :         }
     321             :         return found;
     322             : }
     323             : 
     324             : #ifndef UTEST
     325             : static
     326             : #endif
     327          56 : int do_list_server_work(
     328             :         int list_server_callback(const char *fullpath))
     329             : {
     330          56 :         int ret=-1;
     331          56 :         int found=0;
     332             : 
     333             :         //logp("in do_list_server\n");
     334             : 
     335          56 :         if(timed_operation_status_only(CNTR_STATUS_LISTING, NULL, confs))
     336             :                 goto end;
     337             : 
     338          56 :         switch(list_mode)
     339             :         {
     340             :                 case LIST_MODE_BACKUPS:
     341          10 :                         if((found=list_all_backups())<0)
     342             :                                 goto end;
     343             :                         break;
     344             :                 case LIST_MODE_CONTENTS_ONE:
     345          31 :                         if((found=list_contents_one(list_server_callback))<0)
     346             :                                 goto end;
     347             :                         break;
     348             :                 case LIST_MODE_CONTENTS_MANY:
     349          15 :                         if((found=list_contents_many(list_server_callback))<0)
     350             :                                 goto end;
     351             :                         break;
     352             :         }
     353             : 
     354          49 :         if(!found)
     355             :         {
     356          11 :                 if(list_mode==LIST_MODE_BACKUPS)
     357             :                 {
     358           3 :                         asfd_write_wrapper_str(asfd,
     359             :                                 CMD_MESSAGE, "no backups");
     360             :                         // Success.
     361             :                 }
     362             :                 else
     363             :                 {
     364           8 :                         asfd_write_wrapper_str(asfd,
     365             :                                 CMD_MESSAGE, "backup not found");
     366           8 :                         goto end;
     367             :                 }
     368             :         }
     369             : 
     370             :         ret=0;
     371             : end:
     372          56 :         bu_list_free(&bu_list);
     373          56 :         return ret;
     374             : }
     375             : 
     376           1 : int do_list_server(void)
     377             : {
     378           1 :         return do_list_server_work(list_manifest);
     379             : }

Generated by: LCOV version 1.13