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

Generated by: LCOV version 1.13