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

Generated by: LCOV version 1.13