LCOV - code coverage report
Current view: top level - src/server - extra_comms.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 0 175 0.0 %
Date: 2016-01-31 Functions: 0 6 0.0 %

          Line data    Source code
       1             : #include "../burp.h"
       2             : #include "../alloc.h"
       3             : #include "../asfd.h"
       4             : #include "../async.h"
       5             : #include "../cmd.h"
       6             : #include "../conf.h"
       7             : #include "../conffile.h"
       8             : #include "../handy.h"
       9             : #include "../incexc_recv.h"
      10             : #include "../incexc_send.h"
      11             : #include "../iobuf.h"
      12             : #include "../log.h"
      13             : #include "../prepend.h"
      14             : #include "autoupgrade.h"
      15             : 
      16           0 : static int append_to_feat(char **feat, const char *str)
      17             : {
      18           0 :         char *tmp=NULL;
      19           0 :         if(!*feat)
      20             :         {
      21           0 :                 if(!(*feat=strdup_w(str, __func__)))
      22             :                         return -1;
      23           0 :                 return 0;
      24             :         }
      25           0 :         if(!(tmp=prepend(*feat, str)))
      26             :                 return -1;
      27           0 :         free_w(feat);
      28           0 :         *feat=tmp;
      29           0 :         return 0;
      30             : }
      31             : 
      32           0 : static char *get_restorepath(struct conf **cconfs)
      33             : {
      34           0 :         char *tmp=NULL;
      35           0 :         char *restorepath=NULL;
      36           0 :         if((tmp=prepend_s(get_string(cconfs[OPT_DIRECTORY]),
      37           0 :                 get_string(cconfs[OPT_CNAME]))))
      38           0 :                         restorepath=prepend_s(tmp, "restore");
      39           0 :         free_w(&tmp);
      40           0 :         return restorepath;
      41             : }
      42             : 
      43           0 : static int send_features(struct asfd *asfd, struct conf **cconfs)
      44             : {
      45           0 :         int ret=-1;
      46           0 :         char *feat=NULL;
      47             :         struct stat statp;
      48           0 :         const char *restorepath=NULL;
      49           0 :         enum protocol protocol=get_protocol(cconfs);
      50           0 :         struct strlist *startdir=get_strlist(cconfs[OPT_STARTDIR]);
      51           0 :         struct strlist *incglob=get_strlist(cconfs[OPT_INCGLOB]);
      52             : 
      53           0 :         if(append_to_feat(&feat, "extra_comms_begin ok:")
      54             :                 /* clients can autoupgrade */
      55           0 :           || append_to_feat(&feat, "autoupgrade:")
      56             :                 /* clients can give server incexc conf so that the
      57             :                    server knows better what to do on resume */
      58           0 :           || append_to_feat(&feat, "incexc:")
      59             :                 /* clients can give the server an alternative client
      60             :                    to restore from */
      61           0 :           || append_to_feat(&feat, "orig_client:")
      62             :                 /* clients can tell the server what kind of system they are. */
      63           0 :           || append_to_feat(&feat, "uname:"))
      64             :                 goto end;
      65             : 
      66             :         /* Clients can receive restore initiated from the server. */
      67           0 :         if(!(restorepath=get_restorepath(cconfs))
      68           0 :           || set_string(cconfs[OPT_RESTORE_PATH], restorepath))
      69             :                 goto end;
      70           0 :         if(!lstat(restorepath, &statp) && S_ISREG(statp.st_mode)
      71           0 :           && append_to_feat(&feat, "srestore:"))
      72             :                 goto end;
      73             : 
      74             :         /* Clients can receive incexc conf from the server.
      75             :            Only give it as an option if the server has some starting
      76             :            directory configured in the clientconfdir. */
      77           0 :         if((startdir || incglob)
      78           0 :           && append_to_feat(&feat, "sincexc:"))
      79             :                 goto end;
      80             : 
      81             :         /* Clients can be sent cntrs on resume/verify/restore. */
      82             : /* FIX THIS: Disabled until I rewrite a better protocol.
      83             :         if(append_to_feat(&feat, "counters:"))
      84             :                 goto end;
      85             : */
      86             :         // We support CMD_MESSAGE.
      87           0 :         if(append_to_feat(&feat, "msg:"))
      88             :                 goto end;
      89             : 
      90           0 :         if(protocol==PROTO_AUTO)
      91             :         {
      92             :                 /* If the server is configured to use either protocol, let the
      93             :                    client know that it can choose. */
      94           0 :                 logp("Server is using protocol=0 (auto)\n");
      95           0 :                 if(append_to_feat(&feat, "csetproto:"))
      96             :                         goto end;
      97             :         }
      98             :         else
      99             :         {
     100           0 :                 char p[32]="";
     101             :                 /* Tell the client what we are going to use. */
     102           0 :                 logp("Server is using protocol=%d\n", (int)protocol);
     103           0 :                 snprintf(p, sizeof(p), "forceproto=%d:", (int)protocol);
     104           0 :                 if(append_to_feat(&feat, p))
     105             :                         goto end;
     106             :         }
     107             : 
     108             : #ifndef RS_DEFAULT_STRONG_LEN
     109           0 :         if(append_to_feat(&feat, "rshash=blake2:"))
     110             :                 goto end;
     111             : #endif
     112             : 
     113             :         //printf("feat: %s\n", feat);
     114             : 
     115           0 :         if(asfd->write_str(asfd, CMD_GEN, feat))
     116             :         {
     117           0 :                 logp("problem in extra_comms\n");
     118           0 :                 goto end;
     119             :         }
     120             : 
     121             :         ret=0;
     122             : end:
     123           0 :         free_w(&feat);
     124           0 :         return ret;
     125             : }
     126             : 
     127             : struct vers
     128             : {
     129             :         long min;
     130             :         long cli;
     131             :         long ser;
     132             :         long feat_list;
     133             :         long directory_tree;
     134             :         long burp2;
     135             : };
     136             : 
     137           0 : static int extra_comms_read(struct async *as,
     138             :         struct vers *vers, int *srestore,
     139             :         char **incexc, struct conf **globalcs, struct conf **cconfs)
     140             : {
     141           0 :         int ret=-1;
     142             :         struct asfd *asfd;
     143             :         struct iobuf *rbuf;
     144           0 :         asfd=as->asfd;
     145           0 :         rbuf=asfd->rbuf;
     146             : 
     147             :         while(1)
     148             :         {
     149           0 :                 iobuf_free_content(rbuf);
     150           0 :                 if(asfd->read(asfd)) goto end;
     151             : 
     152           0 :                 if(rbuf->cmd!=CMD_GEN)
     153             :                 {
     154           0 :                         iobuf_log_unexpected(rbuf, __func__);
     155             :                         goto end;
     156             :                 }
     157             : 
     158           0 :                 if(!strcmp(rbuf->buf, "extra_comms_end"))
     159             :                 {
     160           0 :                         if(asfd->write_str(asfd, CMD_GEN, "extra_comms_end ok"))
     161             :                                 goto end;
     162             :                         break;
     163             :                 }
     164           0 :                 else if(!strncmp_w(rbuf->buf, "autoupgrade:"))
     165             :                 {
     166           0 :                         char *os=NULL;
     167             :                         const char *autoupgrade_dir=
     168           0 :                                 get_string(globalcs[OPT_AUTOUPGRADE_DIR]);
     169           0 :                         os=rbuf->buf+strlen("autoupgrade:");
     170           0 :                         iobuf_free_content(rbuf);
     171           0 :                         if(os && *os && autoupgrade_server(as, vers->ser,
     172             :                                 vers->cli, os, get_cntr(globalcs),
     173           0 :                                 autoupgrade_dir))
     174             :                                         goto end;
     175             :                 }
     176           0 :                 else if(!strcmp(rbuf->buf, "srestore ok"))
     177             :                 {
     178           0 :                         iobuf_free_content(rbuf);
     179             :                         // Client can accept the restore.
     180             :                         // Load the restore config, then send it.
     181           0 :                         *srestore=1;
     182           0 :                         if(conf_parse_incexcs_path(cconfs,
     183           0 :                                 get_string(cconfs[OPT_RESTORE_PATH]))
     184           0 :                           || incexc_send_server_restore(asfd, cconfs))
     185             :                                 goto end;
     186             :                         // Do not unlink it here - wait until
     187             :                         // the client says that it wants to do the
     188             :                         // restore.
     189             :                         // Also need to leave it around if the
     190             :                         // restore is to an alternative client, so
     191             :                         // that the code below that reloads the config
     192             :                         // can read it again.
     193             :                         //unlink(get_string(cconfs[OPT_RESTORE_PATH]));
     194             :                 }
     195           0 :                 else if(!strcmp(rbuf->buf, "srestore not ok"))
     196             :                 {
     197             :                         const char *restore_path=get_string(
     198           0 :                                 cconfs[OPT_RESTORE_PATH]);
     199             :                         // Client will not accept the restore.
     200           0 :                         unlink(restore_path);
     201           0 :                         if(set_string(cconfs[OPT_RESTORE_PATH], NULL))
     202             :                                 goto end;
     203           0 :                         logp("Client not accepting server initiated restore.\n");
     204             :                 }
     205           0 :                 else if(!strcmp(rbuf->buf, "sincexc ok"))
     206             :                 {
     207             :                         // Client can accept incexc conf from the
     208             :                         // server.
     209           0 :                         iobuf_free_content(rbuf);
     210           0 :                         if(incexc_send_server(asfd, cconfs)) goto end;
     211             :                 }
     212           0 :                 else if(!strcmp(rbuf->buf, "incexc"))
     213             :                 {
     214             :                         // Client is telling server its incexc
     215             :                         // configuration so that it can better decide
     216             :                         // what to do on resume.
     217           0 :                         iobuf_free_content(rbuf);
     218           0 :                         if(incexc_recv_server(asfd, incexc, globalcs)) goto end;
     219           0 :                         if(*incexc)
     220             :                         {
     221           0 :                                 char *tmp=NULL;
     222           0 :                                 char comp[32]="";
     223             :                                 snprintf(comp, sizeof(comp),
     224             :                                         "compression = %d\n",
     225           0 :                                         get_int(cconfs[OPT_COMPRESSION]));
     226           0 :                                 if(!(tmp=prepend(*incexc, comp)))
     227             :                                         goto end;
     228           0 :                                 free_w(incexc);
     229           0 :                                 *incexc=tmp;
     230             :                         }
     231             :                 }
     232           0 :                 else if(!strcmp(rbuf->buf, "countersok"))
     233             :                 {
     234             :                         // Client can accept counters on
     235             :                         // resume/verify/restore.
     236           0 :                         logp("Client supports being sent counters.\n");
     237           0 :                         set_int(cconfs[OPT_SEND_CLIENT_CNTR], 1);
     238             :                 }
     239           0 :                 else if(!strncmp_w(rbuf->buf, "uname=")
     240           0 :                   && strlen(rbuf->buf)>strlen("uname="))
     241             :                 {
     242           0 :                         char *uname=rbuf->buf+strlen("uname=");
     243           0 :                         if(!strncasecmp("Windows", uname, strlen("Windows")))
     244           0 :                                 set_int(cconfs[OPT_CLIENT_IS_WINDOWS], 1);
     245             :                 }
     246           0 :                 else if(!strncmp_w(rbuf->buf, "orig_client=")
     247           0 :                   && strlen(rbuf->buf)>strlen("orig_client="))
     248             :                 {
     249           0 :                         if(conf_switch_to_orig_client(globalcs, cconfs,
     250           0 :                                 rbuf->buf+strlen("orig_client=")))
     251             :                                         goto end;
     252             :                         // If this started out as a server-initiated
     253             :                         // restore, need to load the restore file
     254             :                         // again.
     255           0 :                         if(*srestore)
     256             :                         {
     257           0 :                                 if(conf_parse_incexcs_path(cconfs,
     258           0 :                                         get_string(cconfs[OPT_RESTORE_PATH])))
     259             :                                                 goto end;
     260             :                         }
     261           0 :                         if(asfd->write_str(asfd, CMD_GEN, "orig_client ok"))
     262             :                                 goto end;
     263             :                 }
     264           0 :                 else if(!strncmp_w(rbuf->buf, "restore_spool="))
     265             :                 {
     266             :                         // Client supports temporary spool directory
     267             :                         // for restores.
     268           0 :                         if(set_string(cconfs[OPT_RESTORE_SPOOL],
     269           0 :                                 rbuf->buf+strlen("restore_spool=")))
     270             :                                         goto end;
     271             :                 }
     272           0 :                 else if(!strncmp_w(rbuf->buf, "protocol="))
     273             :                 {
     274           0 :                         char msg[128]="";
     275             :                         // Client wants to set protocol.
     276           0 :                         enum protocol protocol=get_protocol(cconfs);
     277           0 :                         if(protocol!=PROTO_AUTO)
     278             :                         {
     279           0 :                                 snprintf(msg, sizeof(msg), "Client is trying to use protocol=%s but server is set to protocol=%d\n", rbuf->buf, protocol);
     280           0 :                                 log_and_send_oom(asfd, __func__);
     281           0 :                                 goto end;
     282             :                         }
     283           0 :                         else if(!strcmp(rbuf->buf+strlen("protocol="), "1"))
     284             :                         {
     285           0 :                                 set_protocol(cconfs, PROTO_1);
     286           0 :                                 set_protocol(globalcs, PROTO_1);
     287             :                         }
     288           0 :                         else if(!strcmp(rbuf->buf+strlen("protocol="), "2"))
     289             :                         {
     290           0 :                                 set_protocol(cconfs, PROTO_2);
     291           0 :                                 set_protocol(globalcs, PROTO_2);
     292             :                         }
     293             :                         else
     294             :                         {
     295           0 :                                 snprintf(msg, sizeof(msg), "Client is trying to use protocol=%s, which is unknown\n", rbuf->buf);
     296           0 :                                 log_and_send_oom(asfd, __func__);
     297             :                                 goto end;
     298             :                         }
     299             :                         logp("Client has set protocol=%d\n",
     300           0 :                                 (int)get_protocol(cconfs));
     301             :                 }
     302           0 :                 else if(!strncmp_w(rbuf->buf, "rshash=blake2"))
     303             :                 {
     304             : #ifdef RS_DEFAULT_STRONG_LEN
     305             :                         logp("Client is trying to use librsync hash blake2, but server does not support it.\n");
     306             :                         goto end;
     307             : #else
     308           0 :                         set_e_rshash(cconfs[OPT_RSHASH], RSHASH_BLAKE2);
     309           0 :                         set_e_rshash(globalcs[OPT_RSHASH], RSHASH_BLAKE2);
     310             : #endif
     311             :                 }
     312           0 :                 else if(!strncmp_w(rbuf->buf, "msg"))
     313             :                 {
     314           0 :                         set_int(cconfs[OPT_MESSAGE], 1);
     315           0 :                         set_int(globalcs[OPT_MESSAGE], 1);
     316             :                 }
     317             :                 else
     318             :                 {
     319           0 :                         iobuf_log_unexpected(rbuf, __func__);
     320             :                         goto end;
     321             :                 }
     322             :         }
     323             : 
     324           0 :         ret=0;
     325             : end:
     326           0 :         iobuf_free_content(rbuf);
     327           0 :         return ret;
     328             : }
     329             : 
     330           0 : static int vers_init(struct vers *vers, struct conf **cconfs)
     331             : {
     332             :         memset(vers, 0, sizeof(struct vers));
     333           0 :         return ((vers->min=version_to_long("1.2.7"))<0
     334           0 :           || (vers->cli=version_to_long(get_string(cconfs[OPT_PEER_VERSION])))<0
     335           0 :           || (vers->ser=version_to_long(VERSION))<0
     336           0 :           || (vers->feat_list=version_to_long("1.3.0"))<0
     337           0 :           || (vers->directory_tree=version_to_long("1.3.6"))<0
     338           0 :           || (vers->burp2=version_to_long("2.0.0"))<0);
     339             : }
     340             : 
     341           0 : int extra_comms(struct async *as,
     342             :         char **incexc, int *srestore, struct conf **confs, struct conf **cconfs)
     343             : {
     344             :         struct vers vers;
     345             :         struct asfd *asfd;
     346           0 :         asfd=as->asfd;
     347             :         //char *restorepath=NULL;
     348           0 :         const char *peer_version=NULL;
     349             : 
     350           0 :         if(vers_init(&vers, cconfs)) goto error;
     351             : 
     352           0 :         if(vers.cli<vers.directory_tree)
     353             :         {
     354           0 :                 set_int(confs[OPT_DIRECTORY_TREE], 0);
     355           0 :                 set_int(cconfs[OPT_DIRECTORY_TREE], 0);
     356             :         }
     357             : 
     358             :         // Clients before 1.2.7 did not know how to do extra comms, so skip
     359             :         // this section for them.
     360           0 :         if(vers.cli<vers.min) return 0;
     361             : 
     362           0 :         if(asfd_read_expect(asfd, CMD_GEN, "extra_comms_begin"))
     363             :         {
     364           0 :                 logp("problem reading in extra_comms\n");
     365           0 :                 goto error;
     366             :         }
     367             :         // Want to tell the clients the extra comms features that are
     368             :         // supported, so that new clients are more likely to work with old
     369             :         // servers.
     370           0 :         if(vers.cli==vers.feat_list)
     371             :         {
     372             :                 // 1.3.0 did not support the feature list.
     373           0 :                 if(asfd->write_str(asfd, CMD_GEN, "extra_comms_begin ok"))
     374             :                 {
     375           0 :                         logp("problem writing in extra_comms\n");
     376           0 :                         goto error;
     377             :                 }
     378             :         }
     379             :         else
     380             :         {
     381           0 :                 if(send_features(asfd, cconfs)) goto error;
     382             :         }
     383             : 
     384           0 :         if(extra_comms_read(as, &vers, srestore, incexc, confs, cconfs))
     385             :                 goto error;
     386             : 
     387           0 :         peer_version=get_string(cconfs[OPT_PEER_VERSION]);
     388             : 
     389             :         // This needs to come after extra_comms_read, as the client might
     390             :         // have set PROTO_1 or PROTO_2.
     391           0 :         switch(get_protocol(cconfs))
     392             :         {
     393             :                 case PROTO_AUTO:
     394             :                         // The protocol has not been specified. Make a choice.
     395           0 :                         if(vers.cli<vers.burp2)
     396             :                         {
     397             :                                 // Client is burp-1.x.x, use protocol1.
     398           0 :                                 set_protocol(confs, PROTO_1);
     399           0 :                                 set_protocol(cconfs, PROTO_1);
     400             :                                 logp("Client is burp-%s - using protocol=%d\n",
     401           0 :                                         peer_version, PROTO_1);
     402             :                         }
     403             :                         else
     404             :                         {
     405             :                                 // Client is burp-2.x.x, use protocol2.
     406             :                                 // This will probably never be reached because
     407             :                                 // the negotiation will take care of it.
     408           0 :                                 set_protocol(confs, PROTO_2);
     409           0 :                                 set_protocol(cconfs, PROTO_2);
     410             :                                 logp("Client is burp-%s - using protocol=%d\n",
     411           0 :                                         peer_version, PROTO_2);
     412             :                         }
     413             :                         break;
     414             :                 case PROTO_1:
     415             :                         // It is OK for the client to be burp1 and for the
     416             :                         // server to be forced to protocol1.
     417             :                         break;
     418             :                 case PROTO_2:
     419           0 :                         if(vers.cli>=vers.burp2) break;
     420             :                         logp("protocol=%d is set server side, "
     421             :                           "but client is burp version %s\n",
     422           0 :                           PROTO_2, peer_version);
     423           0 :                         goto error;
     424             :         }
     425             : 
     426           0 :         if(get_protocol(cconfs)==PROTO_1)
     427             :         {
     428           0 :                 if(get_e_rshash(cconfs[OPT_RSHASH])==RSHASH_UNSET)
     429             :                 {
     430           0 :                         set_e_rshash(confs[OPT_RSHASH], RSHASH_MD4);
     431           0 :                         set_e_rshash(cconfs[OPT_RSHASH], RSHASH_MD4);
     432             :                 }
     433             :         }
     434             : 
     435             :         return 0;
     436             : error:
     437             :         return -1;
     438             : }

Generated by: LCOV version 1.10