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

Generated by: LCOV version 1.10