LCOV - code coverage report
Current view: top level - src/client - main.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 0 212 0.0 %
Date: 2016-01-03 Functions: 0 8 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 "../fsops.h"
       8             : #include "../handy.h"
       9             : #include "../iobuf.h"
      10             : #include "../log.h"
      11             : #include "../run_script.h"
      12             : #include "auth.h"
      13             : #include "backup.h"
      14             : #include "ca.h"
      15             : #include "delete.h"
      16             : #include "extra_comms.h"
      17             : #include "list.h"
      18             : #include "monitor.h"
      19             : #include "monitor/status_client_ncurses.h"
      20             : #include "protocol2/restore.h"
      21             : #include "restore.h"
      22             : 
      23             : #ifndef HAVE_WIN32
      24             : #include <sys/utsname.h>
      25             : #endif
      26             : 
      27             : // These will also be used as the exit codes of the program and are therefore
      28             : // unsigned integers.
      29             : // Remember to update the man page if you update these.
      30             : enum cliret
      31             : {
      32             :         CLIENT_OK=0,
      33             :         CLIENT_ERROR=1,
      34             :         CLIENT_RESTORE_WARNINGS=2,
      35             :         CLIENT_SERVER_TIMER_NOT_MET=3,
      36             :         CLIENT_COULD_NOT_CONNECT=4,
      37             :         // This one happens after a successful certificate signing request so
      38             :         // that it connects again straight away with the new key/certificate.
      39             :         CLIENT_RECONNECT=100
      40             : };
      41             : 
      42             : struct tchk
      43             : {
      44             :         int resume;
      45             :         enum cliret ret;
      46             : };
      47             : 
      48           0 : static enum asl_ret maybe_check_timer_func(struct asfd *asfd,
      49             :         struct conf **confs, void *param)
      50             : {
      51           0 :         int complen=0;
      52           0 :         struct tchk *tchk=(struct tchk *)param;
      53             : 
      54           0 :         if(!strcmp(asfd->rbuf->buf, "timer conditions not met"))
      55             :         {
      56           0 :                 logp("Timer conditions on the server were not met\n");
      57           0 :                 tchk->ret=CLIENT_SERVER_TIMER_NOT_MET;
      58           0 :                 return ASL_END_OK;
      59             :         }
      60           0 :         else if(!strcmp(asfd->rbuf->buf, "timer conditions met"))
      61             :         {
      62             :                 // Only happens on 'timer check only'.
      63           0 :                 logp("Timer conditions on the server were met\n");
      64           0 :                 tchk->ret=CLIENT_OK;
      65           0 :                 return ASL_END_OK;
      66             :         }
      67             : 
      68           0 :         if(!strncmp_w(asfd->rbuf->buf, "ok"))
      69             :                 complen=3;
      70           0 :         else if(!strncmp_w(asfd->rbuf->buf, "resume"))
      71             :         {
      72           0 :                 complen=7;
      73           0 :                 tchk->resume=1;
      74           0 :                 logp("server wants to resume previous backup.\n");
      75             :         }
      76             :         else
      77             :         {
      78           0 :                 iobuf_log_unexpected(asfd->rbuf, __func__);
      79           0 :                 return ASL_END_ERROR;
      80             :         }
      81             : 
      82             :         // The server now tells us the compression level in the OK response.
      83           0 :         if(strlen(asfd->rbuf->buf)>3)
      84           0 :                 set_int(confs[OPT_COMPRESSION], atoi(asfd->rbuf->buf+complen));
      85             :         logp("Compression level: %d\n",
      86           0 :                 get_int(confs[OPT_COMPRESSION]));
      87             : 
      88           0 :         return ASL_END_OK;
      89             : }
      90             : 
      91           0 : static enum cliret maybe_check_timer(struct asfd *asfd,
      92             :         enum action action, const char *phase1str,
      93             :         struct conf **confs, int *resume)
      94             : {
      95             :         struct tchk tchk;
      96             :         memset(&tchk, 0, sizeof(tchk));
      97           0 :         if(asfd->write_str(asfd, CMD_GEN, phase1str))
      98             :                 return CLIENT_ERROR;
      99             : 
     100           0 :         if(asfd->simple_loop(asfd, confs, &tchk,
     101           0 :                 __func__, maybe_check_timer_func)) return CLIENT_ERROR;
     102           0 :         *resume=tchk.resume;
     103           0 :         return tchk.ret;
     104             : }
     105             : 
     106           0 : static enum cliret backup_wrapper(struct asfd *asfd,
     107             :         enum action action, const char *phase1str,
     108             :         const char *incexc, struct conf **confs)
     109             : {
     110           0 :         int resume=0;
     111           0 :         enum cliret ret=CLIENT_OK;
     112           0 :         const char *b_script_pre=get_string(confs[OPT_B_SCRIPT_PRE]);
     113           0 :         const char *b_script_post=get_string(confs[OPT_B_SCRIPT_POST]);
     114             : 
     115             :         // Set bulk packets quality of service flags on backup.
     116           0 :         if(incexc)
     117             :         {
     118           0 :                 logp("Server is overriding the configuration\n");
     119           0 :                 logp("with the following settings:\n");
     120           0 :                 if(log_incexcs_buf(incexc)) goto error;
     121             :         }
     122           0 :         if(!get_strlist(confs[OPT_STARTDIR]))
     123             :         {
     124           0 :                 logp("Found no include paths!\n");
     125           0 :                 goto error;
     126             :         }
     127             : 
     128           0 :         switch(maybe_check_timer(asfd, action, phase1str, confs, &resume))
     129             :         {
     130             :                 case CLIENT_OK:
     131           0 :                         if(action==ACTION_TIMER_CHECK) goto end;
     132             :                         break;
     133             :                 case CLIENT_SERVER_TIMER_NOT_MET:
     134             :                         goto timer_not_met;
     135             :                 default:
     136             :                         goto error;
     137             :         }
     138             : 
     139           0 :         if(b_script_pre)
     140             :         {
     141           0 :                 int a=0;
     142             :                 const char *args[12];
     143           0 :                 args[a++]=b_script_pre;
     144           0 :                 if(get_int(confs[OPT_B_SCRIPT_RESERVED_ARGS]))
     145             :                 {
     146           0 :                         args[a++]="pre";
     147           0 :                         args[a++]="reserved2";
     148           0 :                         args[a++]="reserved3";
     149           0 :                         args[a++]="reserved4";
     150           0 :                         args[a++]="reserved5";
     151             :                 }
     152           0 :                 args[a++]=NULL;
     153           0 :                 if(run_script(asfd,
     154             :                         args, get_strlist(confs[OPT_B_SCRIPT_PRE_ARG]),
     155           0 :                         confs, 1, 1, 1))
     156           0 :                                  ret=CLIENT_ERROR;
     157             :         }
     158             : 
     159           0 :         if(ret==CLIENT_OK && do_backup_client(asfd,
     160           0 :                 confs, action, resume)) ret=CLIENT_ERROR;
     161             : 
     162           0 :         if((ret==CLIENT_OK || get_int(confs[OPT_B_SCRIPT_POST_RUN_ON_FAIL]))
     163           0 :           && b_script_post)
     164             :         {
     165           0 :                 int a=0;
     166             :                 const char *args[12];
     167           0 :                 if(get_int(confs[OPT_B_SCRIPT_RESERVED_ARGS]))
     168             :                 {
     169           0 :                         args[a++]=b_script_post;
     170           0 :                         args[a++]="post";
     171             :                         // Tell post script whether the restore failed.
     172           0 :                         args[a++]=ret?"1":"0";
     173           0 :                         args[a++]="reserved3";
     174           0 :                         args[a++]="reserved4";
     175           0 :                         args[a++]="reserved5";
     176             :                 }
     177           0 :                 args[a++]=NULL;
     178           0 :                 if(run_script(asfd,
     179             :                         args, get_strlist(confs[OPT_B_SCRIPT_POST_ARG]),
     180           0 :                         confs, 1, 1, 1))
     181           0 :                                 ret=CLIENT_ERROR;
     182             :         }
     183             : 
     184           0 :         if(ret==CLIENT_OK) logp("backup finished ok\n");
     185             : 
     186             : end:
     187           0 :         return ret;
     188             : error:
     189           0 :         logp("error in backup\n");
     190           0 :         return CLIENT_ERROR;
     191             : timer_not_met:
     192             :         return CLIENT_SERVER_TIMER_NOT_MET;
     193             : }
     194             : 
     195             : static int s_server_session_id_context=1;
     196             : 
     197           0 : static int ssl_setup(int *rfd, SSL **ssl, SSL_CTX **ctx,
     198             :         enum action action, struct conf **confs)
     199             : {
     200           0 :         BIO *sbio=NULL;
     201           0 :         ssl_load_globals();
     202           0 :         if(!(*ctx=ssl_initialise_ctx(confs)))
     203             :         {
     204           0 :                 logp("error initialising ssl ctx\n");
     205           0 :                 return -1;
     206             :         }
     207             : 
     208             :         SSL_CTX_set_session_id_context(*ctx,
     209             :                 (const uint8_t *)&s_server_session_id_context,
     210           0 :                 sizeof(s_server_session_id_context));
     211             : 
     212           0 :         if((*rfd=init_client_socket(get_string(confs[OPT_SERVER]),
     213             :           action==ACTION_MONITOR?
     214           0 :           get_string(confs[OPT_STATUS_PORT]):get_string(confs[OPT_PORT])))<0)
     215             :                 return -1;
     216             : 
     217           0 :         if(!(*ssl=SSL_new(*ctx))
     218           0 :           || !(sbio=BIO_new_socket(*rfd, BIO_NOCLOSE)))
     219             :         {
     220           0 :                 logp_ssl_err("Problem joining SSL to the socket\n");
     221           0 :                 return -1;
     222             :         }
     223           0 :         SSL_set_bio(*ssl, sbio, sbio);
     224           0 :         if(SSL_connect(*ssl)<=0)
     225             :         {
     226           0 :                 logp_ssl_err("SSL connect error\n");
     227           0 :                 return -1;
     228             :         }
     229             :         return 0;
     230             : }
     231             : 
     232           0 : static enum cliret initial_comms(struct async *as,
     233             :         enum action *action, char **incexc, struct conf **confs)
     234             : {
     235             :         struct asfd *asfd;
     236           0 :         char *server_version=NULL;
     237           0 :         enum cliret ret=CLIENT_OK;
     238           0 :         asfd=as->asfd;
     239             : 
     240           0 :         if(authorise_client(asfd, &server_version,
     241           0 :           get_string(confs[OPT_CNAME]),
     242           0 :           get_string(confs[OPT_PASSWORD]),
     243           0 :           get_cntr(confs)))
     244             :                 goto error;
     245             : 
     246           0 :         if(server_version)
     247             :         {
     248           0 :                 logp("Server version: %s\n", server_version);
     249             :                 // Servers before 1.3.2 did not tell us their versions.
     250             :                 // 1.3.2 and above can do the automatic CA stuff that
     251             :                 // follows.
     252           0 :                 switch(ca_client_setup(asfd, confs))
     253             :                 {
     254             :                         case 0:
     255             :                                 break; // All OK.
     256             :                         case 1:
     257             :                                 // Certificate signed successfully.
     258             :                                 // Everything is OK, but we will reconnect now,
     259             :                                 // in order to use the new keys/certificates.
     260             :                                 goto reconnect;
     261             :                         default:
     262           0 :                                 logp("Error with cert signing request\n");
     263           0 :                                 goto error;
     264             :                 }
     265             :         }
     266             : 
     267           0 :         set_non_blocking(asfd->fd);
     268             : 
     269           0 :         if(ssl_check_cert(asfd->ssl, NULL, confs))
     270             :         {
     271           0 :                 logp("check cert failed\n");
     272           0 :                 goto error;
     273             :         }
     274             : 
     275           0 :         if(extra_comms(as, confs, action, incexc))
     276             :         {
     277           0 :                 logp("extra comms failed\n");
     278           0 :                 goto error;
     279             :         }
     280             : 
     281             :         ret=CLIENT_OK; goto end;
     282             : error:
     283             :         ret=CLIENT_ERROR; goto end;
     284             : reconnect:
     285             :         ret=CLIENT_RECONNECT; goto end;
     286             : end:
     287           0 :         free_w(&server_version);
     288           0 :         return ret;
     289             : }
     290             : 
     291           0 : static enum cliret restore_wrapper(struct asfd *asfd, enum action action,
     292             :         int vss_restore, struct conf **confs)
     293             : {
     294           0 :         enum cliret ret=CLIENT_OK;
     295           0 :         const char *r_script_pre=get_string(confs[OPT_R_SCRIPT_PRE]);
     296           0 :         const char *r_script_post=get_string(confs[OPT_R_SCRIPT_POST]);
     297             : 
     298           0 :         if(r_script_pre)
     299             :         {
     300           0 :                 int a=0;
     301             :                 const char *args[12];
     302           0 :                 args[a++]=r_script_pre;
     303           0 :                 if(get_int(confs[OPT_R_SCRIPT_RESERVED_ARGS]))
     304             :                 {
     305           0 :                         args[a++]="pre";
     306           0 :                         args[a++]="reserved2";
     307           0 :                         args[a++]="reserved3";
     308           0 :                         args[a++]="reserved4";
     309           0 :                         args[a++]="reserved5";
     310             :                 }
     311           0 :                 args[a++]=NULL;
     312           0 :                 if(run_script(asfd,
     313             :                         args, get_strlist(confs[OPT_R_SCRIPT_PRE_ARG]),
     314           0 :                         confs, 1, 1, 1))
     315           0 :                                 ret=CLIENT_ERROR;
     316             :         }
     317           0 :         if(ret==CLIENT_OK)
     318             :         {
     319           0 :                 if(do_restore_client(asfd, confs,
     320           0 :                         action, vss_restore)) ret=CLIENT_ERROR;
     321             :         }
     322           0 :         if((ret==CLIENT_OK || get_int(confs[OPT_R_SCRIPT_POST_RUN_ON_FAIL]))
     323           0 :           && r_script_post)
     324             :         {
     325           0 :                 int a=0;
     326             :                 const char *args[12];
     327           0 :                 args[a++]=r_script_pre;
     328           0 :                 if(get_int(confs[OPT_R_SCRIPT_RESERVED_ARGS]))
     329             :                 {
     330           0 :                         args[a++]="post";
     331             :                         // Tell post script whether the restore failed.
     332           0 :                         args[a++]=ret?"1":"0";
     333           0 :                         args[a++]="reserved3";
     334           0 :                         args[a++]="reserved4";
     335           0 :                         args[a++]="reserved5";
     336             :                 }
     337           0 :                 args[a++]=NULL;
     338           0 :                 if(run_script(asfd,
     339             :                         args, get_strlist(confs[OPT_R_SCRIPT_POST_ARG]),
     340           0 :                         confs, 1, 1, 1))
     341           0 :                                 ret=CLIENT_ERROR;
     342             :         }
     343             : 
     344             :         // Return non-zero if there were warnings,
     345             :         // so that the test script can easily check.
     346           0 :         if(ret==CLIENT_OK && get_cntr(confs)->ent[CMD_WARNING]->count)
     347           0 :                 ret=CLIENT_RESTORE_WARNINGS;
     348             : 
     349           0 :         return ret;
     350             : }
     351             : 
     352           0 : static enum cliret do_client(struct conf **confs,
     353             :         enum action action, int vss_restore)
     354             : {
     355           0 :         enum cliret ret=CLIENT_OK;
     356           0 :         int rfd=-1;
     357           0 :         SSL *ssl=NULL;
     358           0 :         SSL_CTX *ctx=NULL;
     359           0 :         struct cntr *cntr=NULL;
     360           0 :         char *incexc=NULL;
     361           0 :         enum action act=action;
     362           0 :         struct async *as=NULL;
     363           0 :         struct asfd *asfd=NULL;
     364             : 
     365             : //      as->settimers(0, 100);
     366             : 
     367             : //      logp("begin client\n");
     368             : //      logp("action %d\n", action);
     369             : 
     370             :         // Status monitor forks a child process instead of connecting to
     371             :         // the server directly.
     372           0 :         if(action==ACTION_STATUS
     373           0 :           || action==ACTION_STATUS_SNAPSHOT)
     374             :         {
     375             : #ifdef HAVE_WIN32
     376             :                 logp("Status mode not implemented on Windows.\n");
     377             :                 goto error;
     378             : #endif
     379           0 :                 if(status_client_ncurses(act, confs)) ret=CLIENT_ERROR;
     380             :                 goto end;
     381             :         }
     382             : 
     383           0 :         if(!(cntr=cntr_alloc())
     384           0 :           || cntr_init(cntr, get_string(confs[OPT_CNAME]))) goto error;
     385           0 :         set_cntr(confs[OPT_CNTR], cntr);
     386             : 
     387           0 :         if(act!=ACTION_ESTIMATE
     388           0 :           && ssl_setup(&rfd, &ssl, &ctx, action, confs))
     389             :                 goto could_not_connect;
     390             : 
     391           0 :         if(!(as=async_alloc())
     392           0 :           || !(asfd=asfd_alloc())
     393           0 :           || as->init(as, act==ACTION_ESTIMATE)
     394           0 :           || asfd->init(asfd, "main socket", as, rfd, ssl,
     395           0 :                 ASFD_STREAM_STANDARD, confs))
     396             :                         goto end;
     397           0 :         as->asfd_add(as, asfd);
     398             : 
     399             :         // Set quality of service bits on backup packets.
     400           0 :         if(act==ACTION_BACKUP
     401           0 :           || act==ACTION_BACKUP_TIMED
     402           0 :           || act==ACTION_TIMER_CHECK)
     403           0 :                 as->asfd->set_bulk_packets(as->asfd);
     404             : 
     405           0 :         if(act!=ACTION_ESTIMATE)
     406             :         {
     407           0 :                 if((ret=initial_comms(as, &act, &incexc, confs)))
     408             :                         goto end;
     409             :         }
     410             : 
     411           0 :         rfd=-1;
     412           0 :         switch(act)
     413             :         {
     414             :                 case ACTION_BACKUP:
     415             :                         ret=backup_wrapper(asfd, act, "backupphase1",
     416           0 :                           incexc, confs);
     417           0 :                         break;
     418             :                 case ACTION_BACKUP_TIMED:
     419             :                         ret=backup_wrapper(asfd, act, "backupphase1timed",
     420           0 :                           incexc, confs);
     421           0 :                         break;
     422             :                 case ACTION_TIMER_CHECK:
     423             :                         ret=backup_wrapper(asfd, act, "backupphase1timedcheck",
     424           0 :                           incexc, confs);
     425           0 :                         break;
     426             :                 case ACTION_RESTORE:
     427             :                 case ACTION_VERIFY:
     428           0 :                         ret=restore_wrapper(asfd, act, vss_restore, confs);
     429           0 :                         break;
     430             :                 case ACTION_ESTIMATE:
     431           0 :                         if(do_backup_client(asfd, confs, act, 0))
     432             :                                 goto error;
     433             :                         break;
     434             :                 case ACTION_DELETE:
     435           0 :                         if(do_delete_client(asfd, confs)) goto error;
     436             :                         break;
     437             :                 case ACTION_MONITOR:
     438           0 :                         if(do_monitor_client(asfd, confs)) goto error;
     439             :                         break;
     440             :                 case ACTION_DIFF:
     441             :                 case ACTION_DIFF_LONG:
     442             : /*
     443             :                         if(!strcmp(get_string(confs[OPT_BACKUP2]), "n"))
     444             :                                 // Do a phase1 scan and diff that.
     445             :                                 ret=backup_wrapper(asfd, act,
     446             :                                         "backupphase1diff", incexc, confs);
     447             :                         else
     448             : */
     449             :                         // Diff two backups that already exist.
     450             :                         // Fall through, the list code is all we need
     451             :                         // for simple diffs on the client side.
     452             :                 case ACTION_LIST:
     453             :                 case ACTION_LIST_LONG:
     454             :                 default:
     455           0 :                         if(do_list_client(asfd, act, confs)) goto error;
     456             :                         break;
     457             :         }
     458             : 
     459           0 :         if(asfd_flush_asio(asfd))
     460           0 :                 ret=CLIENT_ERROR;
     461             : 
     462             :         goto end;
     463             : error:
     464             :         ret=CLIENT_ERROR; goto end;
     465             : could_not_connect:
     466             :         ret=CLIENT_COULD_NOT_CONNECT;
     467             : end:
     468           0 :         close_fd(&rfd);
     469           0 :         async_free(&as);
     470           0 :         asfd_free(&asfd);
     471           0 :         if(ctx) ssl_destroy_ctx(ctx);
     472           0 :         free_w(&incexc);
     473           0 :         set_cntr(confs[OPT_CNTR], NULL);
     474           0 :         cntr_free(&cntr);
     475             : 
     476             :         //logp("end client\n");
     477           0 :         return ret;
     478             : }
     479             : 
     480           0 : int client(struct conf **confs, enum action action, int vss_restore)
     481             : {
     482           0 :         enum cliret ret=CLIENT_OK;
     483             : 
     484             : #ifdef HAVE_WIN32
     485             :         // prevent sleep when idle
     486             :         SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED);
     487             : #endif
     488             : 
     489           0 :         switch((ret=do_client(confs, action, vss_restore)))
     490             :         {
     491             :                 case CLIENT_RECONNECT:
     492           0 :                         logp("Re-opening connection to server\n");
     493           0 :                         sleep(5);
     494           0 :                         ret=do_client(confs, action, vss_restore);
     495             :                 default:
     496             :                         break;
     497             :         }
     498             : 
     499             : #ifdef HAVE_WIN32
     500             :         // allow sleep when idle
     501             :         SetThreadExecutionState(ES_CONTINUOUS);
     502             : #endif
     503             : 
     504             :         // See enum cliret for return codes.
     505           0 :         return (int)ret;
     506             : }

Generated by: LCOV version 1.10