LCOV - code coverage report
Current view: top level - src/server - extra_comms.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 231 273 84.6 %
Date: 2020-11-06 04:06:22 Functions: 10 11 90.9 %

          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 "../fsops.h"
       9             : #include "../handy.h"
      10             : #include "../incexc_recv.h"
      11             : #include "../incexc_send.h"
      12             : #include "../iobuf.h"
      13             : #include "../log.h"
      14             : #include "../pathcmp.h"
      15             : #include "../prepend.h"
      16             : #include "autoupgrade.h"
      17             : #include "extra_comms.h"
      18             : 
      19             : #include <librsync.h>
      20             : 
      21         419 : static int append_to_feat(char **feat, const char *str)
      22             : {
      23         419 :         char *tmp=NULL;
      24         419 :         if(!*feat)
      25             :         {
      26          35 :                 if(!(*feat=strdup_w(str, __func__)))
      27             :                         return -1;
      28          35 :                 return 0;
      29             :         }
      30         384 :         if(!(tmp=prepend(*feat, str)))
      31             :                 return -1;
      32         384 :         free_w(feat);
      33         384 :         *feat=tmp;
      34         384 :         return 0;
      35             : }
      36             : 
      37             : // It is unfortunate that we are having to figure out the server-initiated
      38             : // restore paths here instead of setting it in a struct sdirs.
      39             : // But doing the extra_comms needs to come before setting the sdirs, because
      40             : // extra_comms sets up a bunch of settings that sdirs need to know.
      41          35 : static char *get_restorepath_proto1(struct conf **cconfs)
      42             : {
      43          35 :         char *tmp=NULL;
      44          35 :         char *restorepath=NULL;
      45          35 :         if((tmp=prepend_s(get_string(cconfs[OPT_DIRECTORY]),
      46          35 :                 get_string(cconfs[OPT_CNAME]))))
      47          35 :                         restorepath=prepend_s(tmp, "restore");
      48          35 :         free_w(&tmp);
      49          35 :         return restorepath;
      50             : }
      51             : 
      52          35 : static char *get_restorepath_proto2(struct conf **cconfs)
      53             : {
      54          35 :         char *tmp1=NULL;
      55          35 :         char *tmp2=NULL;
      56          35 :         char *restorepath=NULL;
      57          35 :         if(!(tmp1=prepend_s(get_string(cconfs[OPT_DIRECTORY]),
      58          35 :                 get_string(cconfs[OPT_DEDUP_GROUP]))))
      59             :                         goto error;
      60          35 :         if(!(tmp2=prepend_s(tmp1, "clients")))
      61             :                 goto error;
      62          35 :         free_w(&tmp1);
      63          35 :         if(!(tmp1=prepend_s(tmp2, get_string(cconfs[OPT_CNAME]))))
      64             :                 goto error;
      65          35 :         if(!(restorepath=prepend_s(tmp1, "restore")))
      66             :                 goto error;
      67             :         goto end;
      68             : error:
      69           0 :         free_w(&restorepath);
      70             : end:
      71          35 :         free_w(&tmp1);
      72          35 :         free_w(&tmp2);
      73          35 :         return restorepath;
      74             : }
      75             : 
      76          35 : static int set_restore_path(struct conf **cconfs, char **feat)
      77             : {
      78          35 :         int ret=-1;
      79          35 :         char *restorepath1=NULL;
      80          35 :         char *restorepath2=NULL;
      81          35 :         if(!(restorepath1=get_restorepath_proto1(cconfs))
      82          35 :           || !(restorepath2=get_restorepath_proto2(cconfs)))
      83             :                 goto end;
      84          35 :         if(is_reg_lstat(restorepath1)==1
      85           4 :           && set_string(cconfs[OPT_RESTORE_PATH], restorepath1))
      86             :                 goto end;
      87          35 :         else if(is_reg_lstat(restorepath2)==1
      88           0 :           && set_string(cconfs[OPT_RESTORE_PATH], restorepath2))
      89             :                 goto end;
      90          35 :         if(get_string(cconfs[OPT_RESTORE_PATH])
      91           4 :           && append_to_feat(feat, "srestore:"))
      92             :                 goto end;
      93             :         ret=0;
      94             : end:
      95          35 :         free_w(&restorepath1);
      96          35 :         free_w(&restorepath2);
      97          35 :         return ret;
      98             : }
      99             : 
     100             : struct vers
     101             : {
     102             :         long min;
     103             :         long cli;
     104             :         long ser;
     105             :         long feat_list;
     106             :         long directory_tree;
     107             :         long burp2;
     108             :         long counters_json;
     109             : };
     110             : 
     111          35 : static int send_features(struct asfd *asfd, struct conf **cconfs,
     112             :         struct vers *vers)
     113             : {
     114          35 :         int ret=-1;
     115          35 :         char *feat=NULL;
     116          35 :         enum protocol protocol=get_protocol(cconfs);
     117          35 :         struct strlist *startdir=get_strlist(cconfs[OPT_STARTDIR]);
     118          35 :         struct strlist *incglob=get_strlist(cconfs[OPT_INCGLOB]);
     119             : 
     120          35 :         if(append_to_feat(&feat, "extra_comms_begin ok:")
     121             :                 /* clients can autoupgrade */
     122          35 :           || append_to_feat(&feat, "autoupgrade:")
     123             :                 /* clients can give server incexc conf so that the
     124             :                    server knows better what to do on resume */
     125          35 :           || append_to_feat(&feat, "incexc:")
     126             :                 /* clients can give the server an alternative client
     127             :                    to restore from */
     128          35 :           || append_to_feat(&feat, "orig_client:")
     129             :                 /* clients can tell the server what kind of system they are. */
     130          35 :           || append_to_feat(&feat, "uname:")
     131          35 :           || append_to_feat(&feat, "failover:")
     132          35 :           || append_to_feat(&feat, "vss_restore:")
     133          35 :           || append_to_feat(&feat, "regex_icase:"))
     134             :                 goto end;
     135             : 
     136             :         /* Clients can receive restore initiated from the server. */
     137          35 :         if(set_restore_path(cconfs, &feat))
     138             :                 goto end;
     139             : 
     140             :         /* Clients can receive incexc conf from the server.
     141             :            Only give it as an option if the server has some starting
     142             :            directory configured in the clientconfdir. */
     143          35 :         if((startdir || incglob)
     144           0 :           && append_to_feat(&feat, "sincexc:"))
     145             :                 goto end;
     146             : 
     147          35 :         if(vers->cli>=vers->counters_json)
     148             :         {
     149             :                 /* Clients can be sent cntrs on resume/verify/restore. */
     150          30 :                 if(append_to_feat(&feat, "counters_json:"))
     151             :                         goto end;
     152             :         }
     153             : 
     154             :         // We support CMD_MESSAGE.
     155          35 :         if(append_to_feat(&feat, "msg:"))
     156             :                 goto end;
     157             : 
     158          35 :         if(protocol==PROTO_AUTO)
     159             :         {
     160             :                 /* If the server is configured to use either protocol, let the
     161             :                    client know that it can choose. */
     162          25 :                 logp("Server is using protocol=0 (auto)\n");
     163          25 :                 if(append_to_feat(&feat, "csetproto:"))
     164             :                         goto end;
     165             :         }
     166             :         else
     167             :         {
     168          10 :                 char p[32]="";
     169             :                 /* Tell the client what we are going to use. */
     170          10 :                 logp("Server is using protocol=%d\n", (int)protocol);
     171          10 :                 snprintf(p, sizeof(p), "forceproto=%d:", (int)protocol);
     172          10 :                 if(append_to_feat(&feat, p))
     173             :                         goto end;
     174             :         }
     175             : 
     176             : #ifdef HAVE_BLAKE2
     177             :         if(append_to_feat(&feat, "rshash=blake2:"))
     178             :                 goto end;
     179             : #endif
     180             : 
     181          35 :         if(append_to_feat(&feat, "seed:"))
     182             :                 goto end;
     183             : 
     184             :         //printf("feat: %s\n", feat);
     185             : 
     186          35 :         if(asfd->write_str(asfd, CMD_GEN, feat))
     187             :         {
     188           1 :                 logp("problem in extra_comms\n");
     189             :                 goto end;
     190             :         }
     191             : 
     192             :         ret=0;
     193             : end:
     194          35 :         free_w(&feat);
     195          35 :         return ret;
     196             : }
     197             : 
     198           2 : static int do_autoupgrade(struct asfd *asfd, struct vers *vers,
     199             :         struct conf **globalcs)
     200             : {
     201           2 :         int ret=-1;
     202           2 :         char *os=NULL;
     203           2 :         struct iobuf *rbuf=asfd->rbuf;
     204           2 :         const char *autoupgrade_dir=get_string(globalcs[OPT_AUTOUPGRADE_DIR]);
     205             : 
     206           2 :         if(!(os=strdup_w(rbuf->buf+strlen("autoupgrade:"), __func__)))
     207             :                 goto end;
     208           2 :         iobuf_free_content(rbuf);
     209           2 :         ret=0;
     210           2 :         if(os && *os)
     211             :         {
     212             :                 // Sanitise path separators
     213           7 :                 for(char *i=os; *i; ++i)
     214           7 :                         if(*i == '/' || *i == '\\' || *i == ':')
     215           0 :                                 *i='-';
     216             : 
     217           1 :                 ret=autoupgrade_server(asfd, vers->ser,
     218             :                         vers->cli, os, get_cntr(globalcs),
     219             :                         autoupgrade_dir);
     220             :         }
     221             : end:
     222           2 :         free_w(&os);
     223           2 :         return ret;
     224             : }
     225             : 
     226           0 : static int setup_seed(
     227             :         struct asfd *asfd,
     228             :         struct conf **cconfs,
     229             :         struct iobuf *rbuf,
     230             :         const char *what,
     231             :         enum conf_opt opt
     232             : ) {
     233           0 :         int ret=-1;
     234           0 :         char *tmp=NULL;
     235           0 :         char *str=NULL;
     236             : 
     237           0 :         str=rbuf->buf+strlen(what)+1;
     238           0 :         strip_trailing_slashes(&str);
     239             : 
     240           0 :         if(!is_absolute(str))
     241             :         {
     242             :                 char msg[128];
     243           0 :                 snprintf(msg, sizeof(msg), "A %s needs to be absolute!", what);
     244           0 :                 log_and_send(asfd, msg);
     245             :                 goto end;
     246             :         }
     247           0 :         if(opt==OPT_SEED_SRC && *str!='/')
     248             :         {
     249           0 : printf("here: %s\n", str);
     250             :                 // More windows hacks - add a slash to the beginning of things
     251             :                 // like 'C:'.
     252           0 :                 if(astrcat(&tmp, "/", __func__)
     253           0 :                   || astrcat(&tmp, str, __func__))
     254             :                         goto end;
     255           0 :                 str=tmp;
     256             :         }
     257           0 :         if(set_string(cconfs[opt], str))
     258             :                 goto end;
     259           0 :         ret=0;
     260             : end:
     261           0 :         free_w(&tmp);
     262           0 :         return ret;
     263             : }
     264             : 
     265          34 : static int extra_comms_read(struct async *as,
     266             :         struct vers *vers, int *srestore,
     267             :         char **incexc, struct conf **globalcs, struct conf **cconfs)
     268             : {
     269          34 :         int ret=-1;
     270             :         struct asfd *asfd;
     271             :         struct iobuf *rbuf;
     272          34 :         asfd=as->asfd;
     273          34 :         rbuf=asfd->rbuf;
     274             : 
     275             :         while(1)
     276             :         {
     277          54 :                 iobuf_free_content(rbuf);
     278          54 :                 if(asfd->read(asfd)) goto end;
     279             : 
     280          54 :                 if(rbuf->cmd!=CMD_GEN)
     281             :                 {
     282           1 :                         iobuf_log_unexpected(rbuf, __func__);
     283             :                         goto end;
     284             :                 }
     285             : 
     286          53 :                 if(!strcmp(rbuf->buf, "extra_comms_end"))
     287             :                 {
     288          24 :                         if(asfd->write_str(asfd, CMD_GEN, "extra_comms_end ok"))
     289             :                                 goto end;
     290             :                         break;
     291             :                 }
     292          29 :                 else if(!strncmp_w(rbuf->buf, "autoupgrade:"))
     293             :                 {
     294           2 :                         if(do_autoupgrade(asfd, vers, globalcs))
     295             :                                 goto end;
     296             :                 }
     297          27 :                 else if(!strcmp(rbuf->buf, "srestore ok"))
     298             :                 {
     299           4 :                         char *restore_path=get_string(cconfs[OPT_RESTORE_PATH]);
     300           4 :                         if(!restore_path)
     301             :                         {
     302           0 :                                 logp("got srestore ok without a restore_path");
     303             :                                 goto end;
     304             :                         }
     305             :                         
     306           4 :                         iobuf_free_content(rbuf);
     307             :                         // Client can accept the restore.
     308             :                         // Load the restore config, then send it.
     309           4 :                         *srestore=1;
     310             :                         // Need to wipe out OPT_INCEXDIR, as it is needed for
     311             :                         // srestore includes. If it is not wiped out, it can
     312             :                         // interfere if cconfs[OPT_RESTORE_PATH] contained no
     313             :                         // includes.
     314           4 :                         set_strlist(cconfs[OPT_INCEXCDIR], NULL);
     315           4 :                         if(conf_parse_incexcs_path(cconfs, restore_path)
     316           4 :                           || incexc_send_server_restore(asfd, cconfs))
     317             :                                 goto end;
     318             :                         // Do not unlink it here - wait until
     319             :                         // the client says that it wants to do the
     320             :                         // restore.
     321             :                         // Also need to leave it around if the
     322             :                         // restore is to an alternative client, so
     323             :                         // that the code below that reloads the config
     324             :                         // can read it again.
     325             :                         // NOTE: that appears to be in
     326             :                         // src/server/run_action.c::client_can_restore()
     327             :                         //unlink(get_string(cconfs[OPT_RESTORE_PATH]));
     328             :                 }
     329          23 :                 else if(!strcmp(rbuf->buf, "srestore not ok"))
     330             :                 {
     331           1 :                         const char *restore_path=get_string(
     332             :                                 cconfs[OPT_RESTORE_PATH]);
     333             :                         // Client will not accept the restore.
     334           1 :                         if (restore_path)
     335           1 :                                 unlink(restore_path);
     336           1 :                         if(set_string(cconfs[OPT_RESTORE_PATH], NULL))
     337             :                                 goto end;
     338           1 :                         logp("Client not accepting server initiated restore.\n");
     339             :                 }
     340          22 :                 else if(!strcmp(rbuf->buf, "sincexc ok"))
     341             :                 {
     342             :                         // Client can accept incexc conf from the
     343             :                         // server.
     344           1 :                         iobuf_free_content(rbuf);
     345           1 :                         if(incexc_send_server(asfd, cconfs))
     346             :                                 goto end;
     347             :                 }
     348          21 :                 else if(!strcmp(rbuf->buf, "incexc"))
     349             :                 {
     350             :                         // Client is telling server its incexc
     351             :                         // configuration so that it can better decide
     352             :                         // what to do on resume.
     353           1 :                         iobuf_free_content(rbuf);
     354           1 :                         if(incexc_recv_server(asfd, incexc, globalcs))
     355             :                                 goto end;
     356           1 :                         if(*incexc)
     357             :                         {
     358           1 :                                 char *tmp=NULL;
     359           1 :                                 char comp[32]="";
     360           1 :                                 snprintf(comp, sizeof(comp),
     361             :                                         "compression = %d\n",
     362             :                                         get_int(cconfs[OPT_COMPRESSION]));
     363           1 :                                 if(!(tmp=prepend(*incexc, comp)))
     364             :                                         goto end;
     365           1 :                                 free_w(incexc);
     366           1 :                                 *incexc=tmp;
     367             :                         }
     368             :                 }
     369          20 :                 else if(!strcmp(rbuf->buf, "counters_json ok"))
     370             :                 {
     371             :                         // Client can accept counters on
     372             :                         // resume/verify/restore.
     373           1 :                         logp("Client supports being sent json counters.\n");
     374           1 :                         set_int(cconfs[OPT_SEND_CLIENT_CNTR], 1);
     375             :                 }
     376          19 :                 else if(!strncmp_w(rbuf->buf, "uname=")
     377           2 :                   && strlen(rbuf->buf)>strlen("uname="))
     378             :                 {
     379           2 :                         char *uname=rbuf->buf+strlen("uname=");
     380           2 :                         if(!strncasecmp("Windows", uname, strlen("Windows")))
     381           1 :                                 set_int(cconfs[OPT_CLIENT_IS_WINDOWS], 1);
     382             :                 }
     383          17 :                 else if(!strncmp_w(rbuf->buf, "orig_client=")
     384           3 :                   && strlen(rbuf->buf)>strlen("orig_client="))
     385             :                 {
     386           3 :                         if(conf_switch_to_orig_client(globalcs, cconfs,
     387           3 :                                 rbuf->buf+strlen("orig_client=")))
     388             :                                         goto end;
     389             :                         // If this started out as a server-initiated
     390             :                         // restore, need to load the restore file
     391             :                         // again.
     392           2 :                         if(*srestore)
     393             :                         {
     394           1 :                                 if(conf_parse_incexcs_path(cconfs,
     395           1 :                                         get_string(cconfs[OPT_RESTORE_PATH])))
     396             :                                                 goto end;
     397             :                         }
     398           2 :                         if(asfd->write_str(asfd, CMD_GEN, "orig_client ok"))
     399             :                                 goto end;
     400             :                 }
     401          14 :                 else if(!strncmp_w(rbuf->buf, "restore_spool="))
     402             :                 {
     403             :                         // Removed.
     404             :                 }
     405          14 :                 else if(!strncmp_w(rbuf->buf, "protocol="))
     406             :                 {
     407          11 :                         char msg[128]="";
     408             :                         // Client wants to set protocol.
     409             :                         enum protocol protocol;
     410             :                         enum protocol cprotocol;
     411          11 :                         const char *cliproto=NULL;
     412          11 :                         protocol=get_protocol(cconfs);
     413          11 :                         cliproto=rbuf->buf+strlen("protocol=");
     414          11 :                         cprotocol=atoi(cliproto);
     415             : 
     416          11 :                         if(protocol!=PROTO_AUTO)
     417             :                         {
     418           6 :                                 if(protocol==cprotocol)
     419             :                                 {
     420           2 :                                         logp("Client is forcing protocol=%d\n", (int)protocol);
     421           2 :                                         continue;
     422             :                                 }
     423           4 :                                 snprintf(msg, sizeof(msg), "Client is trying to use protocol=%d but server is set to protocol=%d\n", (int)cprotocol, (int)protocol);
     424           4 :                                 log_and_send(asfd, msg);
     425           5 :                                 goto end;
     426             :                         }
     427           5 :                         else if(cprotocol==PROTO_1)
     428             :                         {
     429           2 :                                 set_protocol(cconfs, cprotocol);
     430           2 :                                 set_protocol(globalcs, cprotocol);
     431             :                         }
     432           3 :                         else if(cprotocol==PROTO_2)
     433             :                         {
     434           2 :                                 set_protocol(cconfs, cprotocol);
     435           2 :                                 set_protocol(globalcs, cprotocol);
     436             :                         }
     437             :                         else
     438             :                         {
     439           1 :                                 snprintf(msg, sizeof(msg), "Client is trying to use protocol=%s, which is unknown\n", cliproto);
     440           1 :                                 log_and_send(asfd, msg);
     441             :                                 goto end;
     442             :                         }
     443           4 :                         logp("Client has set protocol=%d\n",
     444           4 :                                 (int)get_protocol(cconfs));
     445             :                 }
     446           3 :                 else if(!strncmp_w(rbuf->buf, "rshash=blake2"))
     447             :                 {
     448             : #ifdef HAVE_BLAKE2
     449             :                         set_e_rshash(cconfs[OPT_RSHASH], RSHASH_BLAKE2);
     450             :                         set_e_rshash(globalcs[OPT_RSHASH], RSHASH_BLAKE2);
     451             : #else
     452           1 :                         logp("Client is trying to use librsync hash blake2, but server does not support it.\n");
     453             :                         goto end;
     454             : #endif
     455             :                 }
     456           2 :                 else if(!strncmp_w(rbuf->buf, "msg"))
     457             :                 {
     458           1 :                         set_int(cconfs[OPT_MESSAGE], 1);
     459           1 :                         set_int(globalcs[OPT_MESSAGE], 1);
     460             :                 }
     461           1 :                 else if(!strncmp_w(rbuf->buf, "backup_failovers_left="))
     462             :                 {
     463             :                         int l;
     464           0 :                         l=atoi(rbuf->buf+strlen("backup_failovers_left="));
     465           0 :                         set_int(cconfs[OPT_BACKUP_FAILOVERS_LEFT], l);
     466           0 :                         set_int(globalcs[OPT_BACKUP_FAILOVERS_LEFT], l);
     467             :                 }
     468           1 :                 else if(!strncmp_w(rbuf->buf, "seed_src="))
     469             :                 {
     470           0 :                         if(setup_seed(asfd, cconfs,
     471             :                                 rbuf, "seed_src", OPT_SEED_SRC))
     472             :                                         goto end;
     473             :                 }
     474           1 :                 else if(!strncmp_w(rbuf->buf, "seed_dst="))
     475             :                 {
     476           0 :                         if(setup_seed(asfd, cconfs,
     477             :                                 rbuf, "seed_dst", OPT_SEED_DST))
     478             :                                         goto end;
     479             :                 }
     480           1 :                 else if(!strncmp_w(rbuf->buf, "vss_restore=off"))
     481             :                 {
     482           0 :                         set_int(cconfs[OPT_VSS_RESTORE], VSS_RESTORE_OFF);
     483           0 :                         set_int(globalcs[OPT_VSS_RESTORE], VSS_RESTORE_OFF);
     484             :                 }
     485           1 :                 else if(!strncmp_w(rbuf->buf, "vss_restore=strip"))
     486             :                 {
     487           0 :                         set_int(cconfs[OPT_VSS_RESTORE], VSS_RESTORE_OFF_STRIP);
     488           0 :                         set_int(globalcs[OPT_VSS_RESTORE], VSS_RESTORE_OFF_STRIP);
     489             :                 }
     490           1 :                 else if(!strncmp_w(rbuf->buf, "regex_icase=1"))
     491             :                 {
     492           0 :                         set_int(cconfs[OPT_REGEX_CASE_INSENSITIVE], 1);
     493           0 :                         set_int(globalcs[OPT_REGEX_CASE_INSENSITIVE], 1);
     494             :                 }
     495             :                 else
     496             :                 {
     497           1 :                         iobuf_log_unexpected(rbuf, __func__);
     498             :                         goto end;
     499             :                 }
     500             :         }
     501             : 
     502          24 :         ret=0;
     503             : end:
     504          34 :         iobuf_free_content(rbuf);
     505          34 :         return ret;
     506             : }
     507             : 
     508          39 : static int vers_init(struct vers *vers, struct conf **cconfs)
     509             : {
     510          39 :         memset(vers, 0, sizeof(struct vers));
     511          39 :         return ((vers->min=version_to_long("1.2.7"))<0
     512          39 :           || (vers->cli=version_to_long(get_string(cconfs[OPT_PEER_VERSION])))<0
     513          39 :           || (vers->ser=version_to_long(PACKAGE_VERSION))<0
     514          39 :           || (vers->feat_list=version_to_long("1.3.0"))<0
     515          39 :           || (vers->directory_tree=version_to_long("1.3.6"))<0
     516          39 :           || (vers->burp2=version_to_long("2.0.0"))<0
     517          78 :           || (vers->counters_json=version_to_long("2.0.46"))<0);
     518             : }
     519             : 
     520          22 : static int check_seed(struct asfd *asfd, struct conf **cconfs)
     521             : {
     522          22 :         char msg[128]="";
     523          22 :         const char *src=get_string(cconfs[OPT_SEED_SRC]);
     524          22 :         const char *dst=get_string(cconfs[OPT_SEED_DST]);
     525          22 :         if(!src && !dst)
     526             :                 return 0;
     527           0 :         if(src && dst)
     528             :         {
     529           0 :                 logp("Seeding '%s' -> '%s'\n", src, dst);
     530           0 :                 return 0;
     531             :         }
     532           0 :         snprintf(msg, sizeof(msg),
     533             :                 "You must specify %s and %s options together, or not at all.",
     534           0 :                         cconfs[OPT_SEED_SRC]->field,
     535           0 :                         cconfs[OPT_SEED_DST]->field);
     536           0 :         log_and_send(asfd, msg);
     537           0 :         return -1;
     538             : }
     539             : 
     540          39 : int extra_comms(struct async *as,
     541             :         char **incexc, int *srestore, struct conf **confs, struct conf **cconfs)
     542             : {
     543             :         struct vers vers;
     544             :         struct asfd *asfd;
     545          39 :         asfd=as->asfd;
     546             :         //char *restorepath=NULL;
     547          39 :         const char *peer_version=NULL;
     548             : 
     549          39 :         if(vers_init(&vers, cconfs))
     550             :                 goto error;
     551             : 
     552          39 :         if(vers.cli<vers.directory_tree)
     553             :         {
     554           3 :                 set_int(confs[OPT_DIRECTORY_TREE], 0);
     555           3 :                 set_int(cconfs[OPT_DIRECTORY_TREE], 0);
     556             :         }
     557             : 
     558             :         // Clients before 1.2.7 did not know how to do extra comms, so skip
     559             :         // this section for them.
     560          39 :         if(vers.cli<vers.min)
     561             :                 return 0;
     562             : 
     563          37 :         if(asfd_read_expect(asfd, CMD_GEN, "extra_comms_begin"))
     564             :         {
     565           1 :                 logp("problem reading in extra_comms\n");
     566           1 :                 goto error;
     567             :         }
     568             :         // Want to tell the clients the extra comms features that are
     569             :         // supported, so that new clients are more likely to work with old
     570             :         // servers.
     571          36 :         if(vers.cli==vers.feat_list)
     572             :         {
     573             :                 // 1.3.0 did not support the feature list.
     574           1 :                 if(asfd->write_str(asfd, CMD_GEN, "extra_comms_begin ok"))
     575             :                 {
     576           1 :                         logp("problem writing in extra_comms\n");
     577           1 :                         goto error;
     578             :                 }
     579             :         }
     580             :         else
     581             :         {
     582          35 :                 if(send_features(asfd, cconfs, &vers))
     583             :                         goto error;
     584             :         }
     585             : 
     586          34 :         if(extra_comms_read(as, &vers, srestore, incexc, confs, cconfs))
     587             :                 goto error;
     588             : 
     589          24 :         peer_version=get_string(cconfs[OPT_PEER_VERSION]);
     590             : 
     591             :         // This needs to come after extra_comms_read, as the client might
     592             :         // have set PROTO_1 or PROTO_2.
     593          24 :         switch(get_protocol(cconfs))
     594             :         {
     595             :                 case PROTO_AUTO:
     596             :                         // The protocol has not been specified. Make a choice.
     597          14 :                         if(vers.cli<vers.burp2)
     598             :                         {
     599             :                                 // Client is burp-1.x.x, use protocol1.
     600           1 :                                 set_protocol(confs, PROTO_1);
     601           1 :                                 set_protocol(cconfs, PROTO_1);
     602           1 :                                 logp("Client is %s-%s - using protocol=%d\n",
     603             :                                         PACKAGE_TARNAME,
     604             :                                         peer_version, PROTO_1);
     605             :                         }
     606             :                         else
     607             :                         {
     608             :                                 // Client is burp-2.x.x, use protocol2.
     609             :                                 // This will probably never be reached because
     610             :                                 // the negotiation will take care of it.
     611             :                                 /*
     612             :                                 set_protocol(confs, PROTO_2);
     613             :                                 set_protocol(cconfs, PROTO_2);
     614             :                                 logp("Client is %s-%s - using protocol=%d\n",
     615             :                                         PACKAGE_TARNAME,
     616             :                                         peer_version, PROTO_2);
     617             :                                 */
     618             :                                 // PROTO_1 is safer for now.
     619          13 :                                 set_protocol(confs, PROTO_1);
     620          13 :                                 set_protocol(cconfs, PROTO_1);
     621          13 :                                 logp("Client is %s-%s - using protocol=%d\n",
     622             :                                         PACKAGE_TARNAME,
     623             :                                         peer_version, PROTO_1);
     624             :                         }
     625             :                         break;
     626             :                 case PROTO_1:
     627             :                         // It is OK for the client to be burp1 and for the
     628             :                         // server to be forced to protocol1.
     629             :                         break;
     630             :                 case PROTO_2:
     631           5 :                         if(vers.cli>=vers.burp2)
     632             :                                 break;
     633           2 :                         logp("protocol=%d is set server side, "
     634             :                           "but client is %s version %s\n",
     635             :                           PROTO_2, PACKAGE_TARNAME, peer_version);
     636           2 :                         goto error;
     637             :         }
     638             : 
     639          22 :         if(get_protocol(cconfs)==PROTO_1)
     640             :         {
     641          19 :                 if(get_e_rshash(cconfs[OPT_RSHASH])==RSHASH_UNSET)
     642             :                 {
     643          19 :                         set_e_rshash(confs[OPT_RSHASH], RSHASH_MD4);
     644          19 :                         set_e_rshash(cconfs[OPT_RSHASH], RSHASH_MD4);
     645             :                 }
     646             :         }
     647             : 
     648          22 :         if(check_seed(asfd, cconfs))
     649             :                 goto error;
     650             : 
     651             :         return 0;
     652             : error:
     653             :         return -1;
     654             : }

Generated by: LCOV version 1.13