LCOV - code coverage report
Current view: top level - src/server/monitor - cstat.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 127 131 96.9 %
Date: 2022-08-30 22:36:43 Functions: 10 10 100.0 %

          Line data    Source code
       1             : #include "../../burp.h"
       2             : #include "../../alloc.h"
       3             : #include "../../bu.h"
       4             : #include "../../cstat.h"
       5             : #include "../../conffile.h"
       6             : #include "../../fsops.h"
       7             : #include "../../lock.h"
       8             : #include "../../log.h"
       9             : #include "../../strlist.h"
      10             : #include "../bu_get.h"
      11             : #include "../sdirs.h"
      12             : #include "cstat.h"
      13             : 
      14             : #ifndef UTEST
      15             : static 
      16             : #endif
      17          19 : int cstat_permitted(struct cstat *cstat,
      18             :         struct conf **monitor_cconfs, struct conf **cconfs)
      19             : {
      20             :         struct strlist *rclient;
      21             :         const char *monitorconf_cname;
      22             : 
      23          19 :         monitorconf_cname=get_string(monitor_cconfs[OPT_CNAME]);
      24          19 :         if(!monitorconf_cname)
      25             :                 return 0;
      26             : 
      27             :         // Allow clients to look at themselves.
      28           4 :         if(!strcmp(cstat->name, monitorconf_cname))
      29             :                 return 1;
      30             : 
      31             :         // Do not allow clients using the super_client option to see more
      32             :         // than the client that it is pretending to be.
      33           3 :         if(get_string(monitor_cconfs[OPT_SUPER_CLIENT]))
      34             :                 return 0;
      35             : 
      36             :         // If we are listed in this restore_client list, or super_client list.
      37           6 :         for(rclient=get_strlist(cconfs[OPT_RESTORE_CLIENTS]);
      38           2 :           rclient; rclient=rclient->next)
      39           3 :             if(!strcmp(get_string(monitor_cconfs[OPT_CNAME]), rclient->path))
      40             :                 return 1;
      41           2 :         for(rclient=get_strlist(cconfs[OPT_SUPER_CLIENTS]);
      42           0 :           rclient; rclient=rclient->next)
      43           0 :             if(!strcmp(get_string(monitor_cconfs[OPT_CNAME]), rclient->path))
      44             :                 return 1;
      45             :         return 0;
      46             : }
      47             : 
      48          15 : static int cstat_set_sdirs_protocol_known(struct cstat *cstat,
      49             :         struct conf **cconfs)
      50             : {
      51          15 :         struct sdirs *sdirs=NULL;
      52             : 
      53          15 :         if(!(sdirs=sdirs_alloc()))
      54             :                 return -1;
      55          15 :         if(sdirs_init_from_confs(sdirs, cconfs))
      56             :         {
      57           0 :                 sdirs_free(&sdirs);
      58             :                 return -1;
      59             :         }
      60          15 :         cstat->sdirs=sdirs;
      61             :         return 0;
      62             : }
      63             : 
      64             : static int cstat_set_sdirs(struct cstat *cstat, struct conf **cconfs)
      65             : {
      66          15 :         sdirs_free((struct sdirs **)&cstat->sdirs);
      67             : 
      68          15 :         return cstat_set_sdirs_protocol_known(cstat, cconfs);
      69             : }
      70             : 
      71          15 : static int set_cstat_from_conf(struct cstat *cstat,
      72             :         struct conf **monitor_cconfs, struct conf **cconfs)
      73             : {
      74          15 :         struct strlist *s=NULL;
      75             :         // Make sure the permitted flag is set appropriately.
      76          15 :         cstat->permitted=cstat_permitted(cstat, monitor_cconfs, cconfs);
      77             : 
      78          15 :         if(cstat_set_sdirs(cstat, cconfs))
      79             :                 return -1;
      80          15 :         strlists_free(&cstat->labels);
      81          21 :         for(s=get_strlist(cconfs[OPT_LABEL]); s; s=s->next)
      82           6 :                 if(strlist_add_sorted(&cstat->labels, s->path, s->flag))
      83             :                         return -1;
      84             :         return 0;
      85             : }
      86             : 
      87             : #ifndef UTEST
      88             : static
      89             : #endif
      90          24 : int cstat_get_client_names(struct cstat **clist, const char *clientconfdir)
      91             : {
      92          24 :         int i=0;
      93          24 :         int n=0;
      94          24 :         int ret=-1;
      95             :         struct cstat *c;
      96             :         struct cstat *cnew;
      97          24 :         struct dirent **dir=NULL;
      98             : 
      99          24 :         if((n=scandir(clientconfdir, &dir, filter_dot, NULL))<0)
     100             :         {
     101           1 :                 logp("scandir failed for %s in %s: %s\n",
     102           1 :                         clientconfdir, __func__, strerror(errno));
     103           1 :                 goto end;
     104             :         }
     105          75 :         for(i=0; i<n; i++)
     106             :         {
     107          75 :                 if(!cname_valid(dir[i]->d_name))
     108           2 :                         continue;
     109         175 :                 for(c=*clist; c; c=c->next)
     110             :                 {
     111         119 :                         if(!c->name) continue;
     112         119 :                         if(!strcmp(dir[i]->d_name, c->name))
     113             :                                 break;
     114             :                 }
     115          73 :                 if(c) continue;
     116             : 
     117             :                 // We do not have this client yet. Add it.
     118          56 :                 if(!(cnew=cstat_alloc())
     119          56 :                   || cstat_init(cnew, dir[i]->d_name, clientconfdir))
     120             :                         goto end;
     121          56 :                 cstat_add_to_list(clist, cnew);
     122             :         }
     123             : 
     124             :         ret=0;
     125             : end:
     126          24 :         if(dir)
     127             :         {
     128          75 :                 for(i=0; i<n; i++)
     129          75 :                         free(dir[i]);
     130          23 :                 free(dir);
     131             :         }
     132          24 :         return ret;
     133             : }
     134             : 
     135             : static void cstat_free_w(struct cstat **cstat)
     136             : {
     137           8 :         sdirs_free((struct sdirs **)&(*cstat)->sdirs);
     138           8 :         cstat_free(cstat);
     139             : }
     140             : 
     141             : #ifndef UTEST
     142             : static
     143             : #endif
     144           8 : void cstat_remove(struct cstat **clist, struct cstat **cstat)
     145             : {
     146             :         struct cstat *c;
     147           8 :         if(!cstat || !*cstat) return;
     148           8 :         if(*clist==*cstat)
     149             :         {
     150           4 :                 *clist=(*clist)->next;
     151           4 :                 if(*clist) (*clist)->prev=NULL;
     152           4 :                 cstat_free_w(cstat);
     153           4 :                 *cstat=*clist;
     154           4 :                 return;
     155             :         }
     156          10 :         for(c=*clist; c; c=c->next)
     157             :         {
     158           7 :                 if(c->next!=*cstat)
     159           3 :                         continue;
     160           4 :                 c->next=(*cstat)->next;
     161           4 :                 if(c->next)
     162           3 :                         c->next->prev=(*cstat)->prev;
     163           4 :                 cstat_free_w(cstat);
     164           4 :                 *cstat=*clist;
     165           4 :                 return;
     166             :         }
     167             : }
     168             : 
     169             : // Returns -1 on error, otherwise the number of clients that were reloaded.
     170             : #ifndef UTEST
     171             : static
     172             : #endif
     173          12 : int cstat_reload_from_client_confs(struct cstat **clist,
     174             :         struct conf **monitor_cconfs,
     175             :         struct conf **globalcs, struct conf **cconfs)
     176             : {
     177             :         struct cstat *c;
     178             :         struct stat statp;
     179             :         static time_t global_mtime=0;
     180          12 :         time_t global_mtime_new=0;
     181             :         const char *globalconffile;
     182          12 :         int reloaded=0;
     183             : 
     184          12 :         globalconffile=get_string(globalcs[OPT_CONFFILE]);
     185             : 
     186          12 :         if(stat(globalconffile, &statp)
     187          11 :           || !S_ISREG(statp.st_mode))
     188             :         {
     189           1 :                 logp("Could not stat main conf file %s: %s\n",
     190           1 :                         globalconffile, strerror(errno));
     191           1 :                 return -1;
     192             :         }
     193          11 :         global_mtime_new=statp.st_mtime;
     194             : 
     195             :         // FIX THIS: If '. included' conf files have changed, this code will
     196             :         // not detect them. I guess that conf.c should make a list of them.
     197             :         while(1)
     198             :         {
     199          41 :                 for(c=*clist; c; c=c->next)
     200             :                 {
     201             :                         // Look at the client conf files to see if they have
     202             :                         // changed, and reload bits and pieces if they have.
     203             : 
     204          31 :                         if(!c->conffile) continue;
     205          62 :                         if(stat(c->conffile, &statp)
     206          28 :                           || !S_ISREG(statp.st_mode))
     207             :                         {
     208           3 :                                 cstat_remove(clist, &c);
     209           3 :                                 break; // Go to the beginning of the list.
     210             :                         }
     211          28 :                         if(statp.st_mtime==c->conf_mtime
     212          12 :                           && global_mtime_new==global_mtime)
     213             :                         {
     214             :                                 // The conf files have not changed - no need to
     215             :                                 // do anything.
     216          12 :                                 continue;
     217             :                         }
     218          16 :                         c->conf_mtime=statp.st_mtime;
     219             : 
     220          16 :                         confs_free_content(cconfs);
     221          16 :                         if(set_string(cconfs[OPT_CNAME], c->name))
     222             :                                 return -1;
     223          16 :                         if(conf_load_clientconfdir(globalcs, cconfs))
     224             :                         {
     225             :                                 // If the file has junk in it, we will keep
     226             :                                 // trying to reload it after removal.
     227             :                                 // So, just deny permission to view it.
     228           1 :                                 c->permitted=0;
     229           1 :                                 continue;
     230             :                         }
     231             : 
     232          15 :                         if(set_cstat_from_conf(c, monitor_cconfs, cconfs))
     233             :                                 return -1;
     234          15 :                         reloaded++;
     235             :                 }
     236             :                 // Only stop if the end of the list was not reached.
     237          13 :                 if(!c) break;
     238             :         }
     239          11 :         if(global_mtime!=global_mtime_new)
     240           3 :                 global_mtime=global_mtime_new;
     241             :         return reloaded;
     242             : }
     243             : 
     244          19 : void cstat_set_run_status(struct cstat *cstat, enum run_status run_status)
     245             : {
     246          19 :         if(!cstat->permitted)
     247             :                 return;
     248          18 :         cstat->run_status=run_status;
     249             : }
     250             : 
     251             : // Return -1 on error, or the number of reloaded clients.
     252             : #ifndef UTEST
     253             : static
     254             : #endif
     255           5 : int reload_from_clientdir(struct cstat **clist)
     256             : {
     257           5 :         int reloaded=0;
     258             :         struct cstat *c;
     259          18 :         for(c=*clist; c; c=c->next)
     260             :         {
     261             :                 struct stat statp;
     262             :                 struct sdirs *sdirs;
     263             : 
     264          25 :                 if(!c->permitted) continue;
     265             : 
     266           3 :                 sdirs=(struct sdirs *)c->sdirs;
     267           3 :                 if(!sdirs || !sdirs->client) continue;
     268           6 :                 if(stat(sdirs->client, &statp))
     269           1 :                         continue;
     270             : 
     271           2 :                 if(statp.st_mtime==c->clientdir_mtime)
     272             :                 {
     273             :                         // clientdir has not changed - no need to do anything.
     274           1 :                         continue;
     275             :                 }
     276           1 :                 c->clientdir_mtime=statp.st_mtime;
     277             : 
     278           1 :                 bu_list_free(&c->bu);
     279             : // FIX THIS: should probably not load everything each time.
     280             : //              if(bu_get_current(sdirs, &c->bu))
     281             : //                      goto error;
     282           1 :                 if(bu_get_list_with_working(sdirs, &c->bu))
     283             :                         goto error;
     284           1 :                 reloaded++;
     285             :         }
     286             :         return reloaded;
     287             : error:
     288           0 :         return -1;
     289             : }
     290             : 
     291           2 : int cstat_load_data_from_disk(struct cstat **clist,
     292             :         struct conf **monitor_cconfs,
     293             :         struct conf **globalcs, struct conf **cconfs)
     294             : {
     295           2 :         if(!globalcs) return -1;
     296           2 :         return cstat_get_client_names(clist,
     297           2 :                 get_string(globalcs[OPT_CLIENTCONFDIR]))
     298           2 :           || cstat_reload_from_client_confs(clist,
     299             :                 monitor_cconfs, globalcs, cconfs)<0
     300           4 :           || reload_from_clientdir(clist)<0;
     301             : }
     302             : 
     303          21 : int cstat_set_backup_list(struct cstat *cstat)
     304             : {
     305          21 :         struct bu *bu=NULL;
     306             : 
     307             :         // Free any previous list.
     308          21 :         bu_list_free(&cstat->bu);
     309             : 
     310          21 :         if(!cstat->permitted) return 0;
     311             : 
     312          20 :         if(bu_get_list_with_working((struct sdirs *)cstat->sdirs, &bu))
     313             :         {
     314             :                 //logp("error when looking up current backups\n");
     315             :                 return 0;
     316             :         }
     317             : 
     318             :         // Find the end of the list just loaded, so we can traverse
     319             :         // it backwards later.
     320          43 :         while(bu && bu->next) bu=bu->next;
     321             : 
     322          19 :         cstat->bu=bu;
     323          19 :         return 0;
     324             : }

Generated by: LCOV version 1.13