LCOV - code coverage report
Current view: top level - src/server - run_action.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 0 228 0.0 %
Date: 2015-10-31 Functions: 0 12 0.0 %

          Line data    Source code
       1             : #include "../burp.h"
       2             : #include "../action.h"
       3             : #include "../asfd.h"
       4             : #include "../async.h"
       5             : #include "../cmd.h"
       6             : #include "../cntr.h"
       7             : #include "../handy.h"
       8             : #include "../fsops.h"
       9             : #include "../iobuf.h"
      10             : #include "../lock.h"
      11             : #include "../log.h"
      12             : #include "../regexp.h"
      13             : #include "../run_script.h"
      14             : #include "backup.h"
      15             : #include "delete.h"
      16             : #include "diff.h"
      17             : #include "list.h"
      18             : #include "protocol2/restore.h"
      19             : #include "restore.h"
      20             : #include "rubble.h"
      21             : #include "sdirs.h"
      22             : 
      23             : // FIX THIS: Somewhat haphazard.
      24             : /* Return 0 for everything OK. -1 for error, or 1 to mean that there was
      25             :    another process that has the lock. */
      26           0 : static int get_lock_sdirs(struct asfd *asfd, struct sdirs *sdirs)
      27             : {
      28             :         struct stat statp;
      29             : 
      30             :         // Make sure the lock directory exists.
      31           0 :         if(mkpath(&sdirs->lock->path, sdirs->lockdir))
      32             :         {
      33           0 :                 asfd->write_str(asfd, CMD_ERROR, "problem with lock directory");
      34           0 :                 goto error;
      35             :         }
      36             : 
      37           0 :         lock_get(sdirs->lock);
      38           0 :         switch(sdirs->lock->status)
      39             :         {
      40           0 :                 case GET_LOCK_GOT: break;
      41             :                 case GET_LOCK_NOT_GOT:
      42           0 :                         if(!lstat(sdirs->finishing, &statp))
      43             :                         {
      44           0 :                                 char msg[256]="";
      45           0 :                                 logp("finalising previous backup\n");
      46             :                                 snprintf(msg, sizeof(msg),
      47             :                                         "Finalising previous backup of client. "
      48           0 :                                         "Please try again later.");
      49           0 :                                 asfd->write_str(asfd, CMD_ERROR, msg);
      50             :                         }
      51             :                         else
      52             :                         {
      53           0 :                                 logp("Another instance of client is already running.\n");
      54             :                                 asfd->write_str(asfd, CMD_ERROR,
      55           0 :                                         "another instance is already running");
      56             :                         }
      57           0 :                         goto lockedout;
      58             :                 case GET_LOCK_ERROR:
      59             :                 default:
      60             :                         logp("Problem with lock file on server: %s\n",
      61           0 :                                 sdirs->lock->path);
      62             :                         asfd->write_str(asfd, CMD_ERROR,
      63           0 :                                 "problem with lock file on server");
      64           0 :                         goto error;
      65             :         }
      66             : 
      67           0 :         return 0;
      68             : lockedout:
      69           0 :         return 1;
      70             : error:
      71           0 :         return -1;
      72             : }
      73             : 
      74           0 : static int client_can_generic(struct conf **cconfs, enum conf_opt o)
      75             : {
      76             :         // Always allow restore_clients, unless we are talking about forcing
      77             :         // a backup.
      78           0 :         if(get_string(cconfs[OPT_RESTORE_CLIENT])
      79           0 :           && o!=OPT_CLIENT_CAN_FORCE_BACKUP)
      80           0 :                 return 1;
      81             : 
      82           0 :         return get_int(cconfs[o]);
      83             : }
      84             : 
      85           0 : static int client_can_restore(struct conf **cconfs)
      86             : {
      87             :         struct stat statp;
      88           0 :         const char *restore_path=get_string(cconfs[OPT_RESTORE_PATH]);
      89             : 
      90             :         // If there is a restore file on the server, it is always OK.
      91           0 :         if(restore_path
      92           0 :           && !lstat(restore_path, &statp))
      93             :         {
      94             :                 // Remove the file.
      95           0 :                 unlink(restore_path);
      96           0 :                 return 1;
      97             :         }
      98             : 
      99           0 :         return client_can_generic(cconfs, OPT_CLIENT_CAN_RESTORE);
     100             : }
     101             : 
     102           0 : static void maybe_do_notification(struct asfd *asfd,
     103             :         int status, const char *clientdir,
     104             :         const char *storagedir, const char *filename,
     105             :         const char *brv, struct conf **cconfs)
     106             : {
     107           0 :         int a=0;
     108             :         const char *args[12];
     109           0 :         struct cntr *cntr=get_cntr(cconfs);
     110           0 :         args[a++]=NULL; // Fill in the script name later.
     111           0 :         args[a++]=get_string(cconfs[OPT_CNAME]);
     112           0 :         args[a++]=clientdir;
     113           0 :         args[a++]=storagedir;
     114           0 :         args[a++]=filename;
     115           0 :         args[a++]=brv;
     116           0 :         if(status)
     117             :         {
     118           0 :                 args[0]=get_string(cconfs[OPT_N_FAILURE_SCRIPT]);
     119           0 :                 args[a++]="0";
     120           0 :                 args[a++]=NULL;
     121           0 :                 run_script(asfd, args, get_strlist(cconfs[OPT_N_FAILURE_ARG]),
     122           0 :                         cconfs, 1, 1, 1);
     123             :         }
     124           0 :         else if((get_int(cconfs[OPT_N_SUCCESS_WARNINGS_ONLY])
     125           0 :                 && cntr->ent[CMD_WARNING]->count > 0)
     126           0 :           || (get_int(cconfs[OPT_N_SUCCESS_CHANGES_ONLY])
     127           0 :                 && cntr->ent[CMD_TOTAL]->changed > 0)
     128           0 :           || (!get_int(cconfs[OPT_N_SUCCESS_WARNINGS_ONLY])
     129           0 :                 && !get_int(cconfs[OPT_N_SUCCESS_CHANGES_ONLY])))
     130             :         {
     131           0 :                 char warnings[32]="";
     132             :                 snprintf(warnings, sizeof(warnings), "%"PRIu64,
     133           0 :                         cntr->ent[CMD_WARNING]->count);
     134           0 :                 args[0]=get_string(cconfs[OPT_N_SUCCESS_SCRIPT]);
     135           0 :                 args[a++]=warnings;
     136           0 :                 args[a++]=NULL;
     137           0 :                 run_script(asfd, args, get_strlist(cconfs[OPT_N_SUCCESS_ARG]),
     138           0 :                         cconfs, 1, 1, 1);
     139             :         }
     140           0 : }
     141             : 
     142           0 : static int run_restore(struct asfd *asfd,
     143             :         struct sdirs *sdirs, struct conf **cconfs, int srestore)
     144             : {
     145           0 :         int ret=-1;
     146           0 :         char *cp=NULL;
     147           0 :         char *copy=NULL;
     148             :         enum action act;
     149           0 :         char *backupnostr=NULL;
     150           0 :         char *restoreregex=NULL;
     151           0 :         char *dir_for_notify=NULL;
     152           0 :         struct iobuf *rbuf=asfd->rbuf;
     153           0 :         const char *cname=get_string(cconfs[OPT_CNAME]);
     154             : 
     155           0 :         if(!(copy=strdup_w(rbuf->buf, __func__)))
     156           0 :                 goto end;
     157             : 
     158           0 :         iobuf_free_content(rbuf);
     159             : 
     160           0 :         if(!strncmp_w(copy, "restore ")) act=ACTION_RESTORE;
     161           0 :         else act=ACTION_VERIFY;
     162             : 
     163           0 :         if(!(backupnostr=strchr(copy, ' ')))
     164             :         {
     165           0 :                 logp("Could not parse %s in %s\n", copy, __func__);
     166           0 :                 goto end;
     167             :         }
     168           0 :         if(set_string(cconfs[OPT_BACKUP], backupnostr))
     169           0 :                 goto end;
     170             :         // FIX THIS.
     171           0 :         if((cp=strchr(cconfs[OPT_BACKUP]->data.s, ':'))) *cp='\0';
     172             : 
     173           0 :         if(act==ACTION_RESTORE)
     174             :         {
     175             :                 int r;
     176           0 :                 if((r=client_can_restore(cconfs))<0)
     177           0 :                         goto end;
     178           0 :                 else if(!r)
     179             :                 {
     180           0 :                         logp("Not allowing restore of %s\n", cname);
     181           0 :                         if(!asfd->write_str(asfd, CMD_GEN,
     182           0 :                                 "Client restore is not allowed")) ret=0;
     183           0 :                         goto end;
     184             :                 }
     185             :         }
     186           0 :         if(act==ACTION_VERIFY
     187           0 :           && !(client_can_generic(cconfs, OPT_CLIENT_CAN_VERIFY)))
     188             :         {
     189           0 :                 logp("Not allowing verify of %s\n", cname);
     190           0 :                 if(!asfd->write_str(asfd, CMD_GEN,
     191           0 :                         "Client verify is not allowed")) ret=0;
     192           0 :                 goto end;
     193             :         }
     194             : 
     195           0 :         if((restoreregex=strchr(copy, ':')))
     196             :         {
     197           0 :                 *restoreregex='\0';
     198           0 :                 restoreregex++;
     199             :         }
     200           0 :         if(set_string(cconfs[OPT_REGEX], restoreregex)
     201           0 :           || asfd->write_str(asfd, CMD_GEN, "ok"))
     202           0 :                 goto end;
     203             :         ret=do_restore_server(asfd, sdirs, act,
     204           0 :                 srestore, &dir_for_notify, cconfs);
     205           0 :         if(dir_for_notify)
     206             :                 maybe_do_notification(asfd, ret,
     207             :                         sdirs->client, dir_for_notify,
     208             :                         act==ACTION_RESTORE?"restorelog":"verifylog",
     209             :                         act==ACTION_RESTORE?"restore":"verify",
     210           0 :                         cconfs);
     211             : end:
     212           0 :         free_w(&copy);
     213           0 :         free_w(&dir_for_notify);
     214           0 :         return ret;
     215             : }
     216             : 
     217           0 : static int run_delete(struct asfd *asfd,
     218             :         struct sdirs *sdirs, struct conf **cconfs)
     219             : {
     220           0 :         char *backupno=NULL;
     221           0 :         struct iobuf *rbuf=asfd->rbuf;
     222           0 :         const char *cname=get_string(cconfs[OPT_CNAME]);
     223           0 :         if(!client_can_generic(cconfs, OPT_CLIENT_CAN_DELETE))
     224             :         {
     225           0 :                 logp("Not allowing delete of %s\n", cname);
     226           0 :                 asfd->write_str(asfd, CMD_GEN, "Client delete is not allowed");
     227           0 :                 return -1;
     228             :         }
     229           0 :         backupno=rbuf->buf+strlen("delete ");
     230             :         return do_delete_server(asfd, sdirs,
     231             :                 get_cntr(cconfs), cname, backupno,
     232           0 :                 get_string(cconfs[OPT_MANUAL_DELETE]));
     233             : }
     234             : 
     235           0 : static int run_list(struct asfd *asfd,
     236             :         struct sdirs *sdirs, struct conf **cconfs)
     237             : {
     238           0 :         int ret=-1;
     239           0 :         char *cp=NULL;
     240           0 :         char *backupno=NULL;
     241           0 :         char *browsedir=NULL;
     242           0 :         char *listregex=NULL;
     243           0 :         struct iobuf *rbuf=asfd->rbuf;
     244             : 
     245           0 :         if(!client_can_generic(cconfs, OPT_CLIENT_CAN_LIST))
     246             :         {
     247             :                 logp("Not allowing list of %s\n",
     248           0 :                         get_string(cconfs[OPT_CNAME]));
     249           0 :                 asfd->write_str(asfd, CMD_GEN, "Client list is not allowed");
     250           0 :                 goto end;
     251             :         }
     252             : 
     253           0 :         if(!strncmp_w(rbuf->buf, "list "))
     254             :         {
     255           0 :                 if((cp=strchr(rbuf->buf, ':')))
     256             :                 {
     257           0 :                         *cp='\0';
     258           0 :                         if(!(listregex=strdup_w(cp+1, __func__)))
     259           0 :                                 goto end;
     260             :                 }
     261           0 :                 if(!(backupno=strdup_w(rbuf->buf+strlen("list "), __func__)))
     262           0 :                         goto end;
     263             :                 
     264             :         }
     265           0 :         else if(!strncmp_w(rbuf->buf, "listb "))
     266             :         {
     267           0 :                 if((cp=strchr(rbuf->buf, ':')))
     268             :                 {
     269           0 :                         *cp='\0';
     270           0 :                         if(!(browsedir=strdup_w(cp+1, __func__)))
     271           0 :                                 goto end;
     272             :                 }
     273           0 :                 strip_trailing_slashes(&browsedir);
     274           0 :                 if(!(backupno=strdup_w(rbuf->buf+strlen("listb "), __func__)))
     275           0 :                         goto end;
     276             :         }
     277           0 :         if(asfd->write_str(asfd, CMD_GEN, "ok")) goto end;
     278             : 
     279           0 :         iobuf_free_content(asfd->rbuf);
     280             : 
     281             :         ret=do_list_server(asfd, sdirs, get_cntr(cconfs),
     282           0 :                 get_protocol(cconfs), backupno, listregex, browsedir);
     283             : end:
     284           0 :         free_w(&backupno);
     285           0 :         free_w(&browsedir);
     286           0 :         free_w(&listregex);
     287           0 :         return ret;
     288             : }
     289             : 
     290           0 : static int run_diff(struct asfd *asfd,
     291             :         struct sdirs *sdirs, struct conf **cconfs)
     292             : {
     293           0 :         int ret=-1;
     294           0 :         char *backupno=NULL;
     295           0 :         struct iobuf *rbuf=asfd->rbuf;
     296             : 
     297           0 :         if(!client_can_generic(cconfs, OPT_CLIENT_CAN_DIFF))
     298             :         {
     299             :                 logp("Not allowing diff of %s\n",
     300           0 :                         get_string(cconfs[OPT_CNAME]));
     301           0 :                 asfd->write_str(asfd, CMD_GEN, "Client diff is not allowed");
     302           0 :                 goto end;
     303             :         }
     304             : 
     305           0 :         if(!strncmp_w(rbuf->buf, "diff "))
     306             :         {
     307           0 :                 if((backupno=strdup_w(rbuf->buf+strlen("diff "), __func__)))
     308           0 :                         goto end;
     309             :         }
     310           0 :         if(asfd->write_str(asfd, CMD_GEN, "ok")) goto end;
     311             : 
     312           0 :         iobuf_free_content(asfd->rbuf);
     313             : 
     314             :         ret=do_diff_server(asfd, sdirs,
     315           0 :                 get_cntr(cconfs), get_protocol(cconfs), backupno);
     316             : end:
     317           0 :         return ret;
     318             : }
     319             : 
     320           0 : static int unknown_command(struct asfd *asfd)
     321             : {
     322           0 :         iobuf_log_unexpected(asfd->rbuf, __func__);
     323           0 :         asfd->write_str(asfd, CMD_ERROR, "unknown command");
     324           0 :         return -1;
     325             : }
     326             : 
     327           0 : static const char *buf_to_notify_str(struct iobuf *rbuf)
     328             : {
     329           0 :         const char *buf=rbuf->buf;
     330           0 :         if(!strncmp_w(buf, "backup")) return "backup";
     331           0 :         else if(!strncmp_w(buf, "restore")) return "restore";
     332           0 :         else if(!strncmp_w(buf, "verify")) return "verify";
     333           0 :         else if(!strncmp_w(buf, "delete")) return "delete";
     334           0 :         else if(!strncmp_w(buf, "list")) return "list";
     335           0 :         else return "unknown";
     336             : }
     337             : 
     338           0 : static int run_action_server_do(struct async *as, struct sdirs *sdirs,
     339             :         const char *incexc, int srestore, int *timer_ret, struct conf **cconfs)
     340             : {
     341             :         int ret;
     342           0 :         int resume=0;
     343           0 :         char msg[256]="";
     344           0 :         struct iobuf *rbuf=as->asfd->rbuf;
     345             : 
     346             :         // Make sure some directories exist.
     347           0 :         if(mkpath(&sdirs->current, sdirs->dedup))
     348             :         {
     349             :                 snprintf(msg, sizeof(msg),
     350           0 :                         "could not mkpath %s", sdirs->current);
     351           0 :                 log_and_send(as->asfd, msg);
     352           0 :                 return -1;
     353             :         }
     354             : 
     355           0 :         if(rbuf->cmd!=CMD_GEN) return unknown_command(as->asfd);
     356             : 
     357             :         // List and diff should work even while backups are running.
     358           0 :         if(!strncmp_w(rbuf->buf, "list ")
     359           0 :           || !strncmp_w(rbuf->buf, "listb "))
     360           0 :                 return run_list(as->asfd, sdirs, cconfs);
     361             : 
     362           0 :         if(!strncmp_w(rbuf->buf, "diff "))
     363           0 :                 return run_diff(as->asfd, sdirs, cconfs);
     364             : 
     365           0 :         switch((ret=get_lock_sdirs(as->asfd, sdirs)))
     366             :         {
     367           0 :                 case 0: break; // OK.
     368           0 :                 case 1: return 1; // Locked out.
     369             :                 default: // Error.
     370             :                         maybe_do_notification(as->asfd, ret,
     371             :                                 "", "error in get_lock_sdirs()",
     372           0 :                                 "", buf_to_notify_str(rbuf), cconfs);
     373           0 :                         return -1;
     374             :         }
     375             : 
     376           0 :         switch((ret=check_for_rubble(as, sdirs, incexc, &resume, cconfs)))
     377             :         {
     378           0 :                 case 0: break; // OK.
     379           0 :                 case 1: return 1; // Now finalising.
     380             :                 default: // Error.
     381             :                         maybe_do_notification(as->asfd, ret,
     382             :                                 "", "error in check_for_rubble()",
     383           0 :                                 "", buf_to_notify_str(rbuf), cconfs);
     384           0 :                         return -1;
     385             :         }
     386             : 
     387           0 :         if(!strncmp_w(rbuf->buf, "backup"))
     388             :         {
     389           0 :                 ret=run_backup(as, sdirs, cconfs, incexc, timer_ret, resume);
     390           0 :                 if(*timer_ret<0)
     391             :                         maybe_do_notification(as->asfd, ret, "",
     392             :                                 "error running timer script",
     393           0 :                                 "", "backup", cconfs);
     394           0 :                 else if(!*timer_ret)
     395             :                         maybe_do_notification(as->asfd, ret, sdirs->client,
     396           0 :                                 sdirs->current, "log", "backup", cconfs);
     397           0 :                 return ret;
     398             :         }
     399             : 
     400           0 :         if(!strncmp_w(rbuf->buf, "restore ")
     401           0 :           || !strncmp_w(rbuf->buf, "verify "))
     402           0 :                 return run_restore(as->asfd, sdirs, cconfs, srestore);
     403             : 
     404           0 :         if(!strncmp_w(rbuf->buf, "Delete "))
     405           0 :                 return run_delete(as->asfd, sdirs, cconfs);
     406             : 
     407             :         // Old clients will send 'delete', possibly accidentally due to the
     408             :         // user trying to use the new diff/long diff options.
     409             :         // Stop them from working, just to be safe.
     410           0 :         if(!strncmp_w(rbuf->buf, "delete "))
     411             :         {
     412             :                 logp("old style delete from %s denied\n",
     413           0 :                         get_string(cconfs[OPT_CNAME]));
     414             :                 as->asfd->write_str(as->asfd, CMD_ERROR,
     415           0 :                         "old style delete is not supported on this server");
     416           0 :                 return -1;
     417             :         }
     418             : 
     419           0 :         return unknown_command(as->asfd);
     420             : }
     421             : 
     422           0 : int run_action_server(struct async *as,
     423             :         const char *incexc, int srestore, int *timer_ret, struct conf **cconfs)
     424             : {
     425           0 :         int ret=-1;
     426           0 :         struct sdirs *sdirs=NULL;
     427           0 :         if((sdirs=sdirs_alloc())
     428           0 :           && !sdirs_init_from_confs(sdirs, cconfs))
     429             :                 ret=run_action_server_do(as,
     430           0 :                         sdirs, incexc, srestore, timer_ret, cconfs);
     431           0 :         if(sdirs) lock_release(sdirs->lock);
     432           0 :         sdirs_free(&sdirs);
     433           0 :         return ret;
     434             : }

Generated by: LCOV version 1.10