LCOV - code coverage report
Current view: top level - src/client - extra_comms.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 112 115 97.4 %
Date: 2019-03-02 00:16:58 Functions: 2 2 100.0 %

          Line data    Source code
       1             : #include "../burp.h"
       2             : #include "../asfd.h"
       3             : #include "../async.h"
       4             : #include "../cmd.h"
       5             : #include "../conf.h"
       6             : #include "../conffile.h"
       7             : #include "../handy.h"
       8             : #include "../incexc_recv.h"
       9             : #include "../incexc_send.h"
      10             : #include "../iobuf.h"
      11             : #include "../log.h"
      12             : #include "autoupgrade.h"
      13             : #include "extra_comms.h"
      14             : 
      15             : #ifndef HAVE_WIN32
      16             : #include <sys/utsname.h>
      17             : #endif
      18             : 
      19             : static const char *server_supports(const char *feat, const char *wanted)
      20             : {
      21         200 :         return strstr(feat, wanted);
      22             : }
      23             : 
      24          25 : static const char *server_supports_autoupgrade(const char *feat)
      25             : {
      26             :         // 1.3.0 servers did not list the features, but the only feature
      27             :         // that was supported was autoupgrade.
      28          25 :         if(!strcmp(feat, "extra_comms_begin ok")) return "ok";
      29          25 :         return server_supports(feat, ":autoupgrade:");
      30             : }
      31             : 
      32             : #include <librsync.h>
      33             : 
      34          28 : int extra_comms_client(struct async *as, struct conf **confs,
      35             :         enum action *action, char **incexc)
      36             : {
      37          28 :         int ret=-1;
      38          28 :         char *feat=NULL;
      39             :         struct asfd *asfd;
      40             :         struct iobuf *rbuf;
      41          28 :         const char *orig_client=NULL;
      42          28 :         asfd=as->asfd;
      43          28 :         rbuf=asfd->rbuf;
      44             : 
      45          28 :         if(asfd->write_str(asfd, CMD_GEN, "extra_comms_begin"))
      46             :         {
      47           1 :                 logp("Problem requesting extra_comms_begin\n");
      48           1 :                 goto end;
      49             :         }
      50             :         // Servers greater than 1.3.0 will list the extra_comms
      51             :         // features they support.
      52          27 :         if(asfd->read(asfd))
      53             :         {
      54           1 :                 logp("Problem reading response to extra_comms_begin\n");
      55           1 :                 goto end;
      56             :         }
      57          26 :         if(rbuf->cmd!=CMD_GEN
      58          26 :           || strncmp_w(rbuf->buf, "extra_comms_begin ok"))
      59             :         {
      60           1 :                 iobuf_log_unexpected(rbuf, __func__);
      61           1 :                 goto end;
      62             :         }
      63          25 :         feat=rbuf->buf;
      64          25 :         rbuf->buf=NULL;
      65          25 :         logp("%s\n", feat);
      66          25 :         iobuf_init(rbuf);
      67             : 
      68             :         // Can add extra bits here. The first extra bit is the
      69             :         // autoupgrade stuff.
      70          25 :         if(server_supports_autoupgrade(feat)
      71           1 :           && get_string(confs[OPT_AUTOUPGRADE_DIR])
      72           1 :           && get_string(confs[OPT_AUTOUPGRADE_OS])
      73           1 :           && autoupgrade_client(as, confs))
      74             :                 goto end;
      75             : 
      76             : 
      77             :         // :srestore: means that the server wants to do a restore.
      78          48 :         if(server_supports(feat, ":srestore:"))
      79             :         {
      80           6 :                 logp("Server wants to initiate a restore\n");
      81           6 :                 if(*action==ACTION_MONITOR)
      82             :                 {
      83           1 :                         logp("Client is in monitor mode, so ignoring\n");
      84             :                 }
      85           5 :                 else if(get_int(confs[OPT_SERVER_CAN_RESTORE]))
      86             :                 {
      87           4 :                         logp("Client accepts.\n");
      88           4 :                         if(incexc_recv_client_restore(asfd, incexc, confs))
      89             :                                 goto end;
      90           4 :                         if(*incexc)
      91             :                         {
      92           4 :                                 if(conf_parse_incexcs_srestore(confs, *incexc))
      93             :                                         goto end;
      94           2 :                                 *action=ACTION_RESTORE;
      95           2 :                                 log_restore_settings(confs, 1);
      96             :                         }
      97             :                 }
      98             :                 else
      99             :                 {
     100           1 :                         logp("Client configuration says no\n");
     101           1 :                         if(asfd->write_str(asfd, CMD_GEN, "srestore not ok"))
     102             :                                 goto end;
     103             :                 }
     104             :         }
     105             : 
     106             :         // Needs to be after the srestore stuff, as the server may set
     107             :         // orig_client in the server-initiated restore file.
     108          22 :         if((orig_client=get_string(confs[OPT_ORIG_CLIENT])))
     109             :         {
     110           4 :                 char str[512]="";
     111           4 :                 snprintf(str, sizeof(str), "orig_client=%s", orig_client);
     112           8 :                 if(!server_supports(feat, ":orig_client:"))
     113             :                 {
     114           1 :                         logp("Server does not support switching client.\n");
     115           1 :                         goto end;
     116             :                 }
     117           3 :                 if(asfd->write_str(asfd, CMD_GEN, str)
     118           3 :                   || asfd_read_expect(asfd, CMD_GEN, "orig_client ok"))
     119             :                 {
     120           1 :                         logp("Problem requesting %s\n", str);
     121           1 :                         goto end;
     122             :                 }
     123           2 :                 logp("Switched to client %s\n", orig_client);
     124             :         }
     125             : 
     126             :         // :sincexc: is for the server giving the client the
     127             :         // incexc config.
     128          40 :         if(*action==ACTION_BACKUP
     129          20 :           || *action==ACTION_BACKUP_TIMED
     130           3 :           || *action==ACTION_TIMER_CHECK)
     131             :         {
     132          34 :                 if(!*incexc && server_supports(feat, ":sincexc:"))
     133             :                 {
     134           2 :                         logp("Server is setting includes/excludes.\n");
     135           2 :                         if(get_int(confs[OPT_SERVER_CAN_OVERRIDE_INCLUDES]))
     136             :                         {
     137           1 :                                 logp("Client accepts.\n");
     138           1 :                                 if(incexc_recv_client(asfd, incexc, confs))
     139             :                                         goto end;
     140           1 :                                 if(*incexc && conf_parse_incexcs_buf(confs,
     141             :                                         *incexc)) goto end;
     142             :                         }
     143             :                         else
     144             :                         {
     145           1 :                                 logp("Client configuration says no\n");
     146             :                         }
     147             :                 }
     148             :         }
     149             : 
     150          40 :         if(server_supports(feat, ":counters_json:"))
     151             :         {
     152           1 :                 if(asfd->write_str(asfd, CMD_GEN, "counters_json ok"))
     153             :                         goto end;
     154           1 :                 set_int(confs[OPT_SEND_CLIENT_CNTR], 1);
     155             :         }
     156             : 
     157             :         // :incexc: is for the client sending the server the
     158             :         // incexc conf so that it better knows what to do on
     159             :         // resume.
     160          40 :         if(server_supports(feat, ":incexc:")
     161           0 :           && incexc_send_client(asfd, confs))
     162             :                 goto end;
     163             : 
     164          40 :         if(server_supports(feat, ":uname:"))
     165             :         {
     166           1 :                 const char *clientos=NULL;
     167             : #ifdef HAVE_WIN32
     168             : #ifdef _WIN64
     169             :                 clientos="Windows 64bit";
     170             : #else
     171             :                 clientos="Windows 32bit";
     172             : #endif
     173             : #else
     174             :                 struct utsname utsname;
     175           1 :                 if(!uname(&utsname))
     176           1 :                         clientos=(const char *)utsname.sysname;
     177             : #endif
     178           1 :                 if(clientos)
     179             :                 {
     180           1 :                         char *msg=NULL;
     181           1 :                         if(astrcat(&msg, "uname=", __func__)
     182           1 :                           || astrcat(&msg, clientos, __func__))
     183             :                                 goto end;
     184           1 :                         if(asfd->write_str(asfd, CMD_GEN, msg))
     185             :                         {
     186           0 :                                 free_w(&msg);
     187           0 :                                 goto end;
     188             :                         }
     189           1 :                         free_w(&msg);
     190             :                 }
     191             :         }
     192             : 
     193          40 :         if(server_supports(feat, ":csetproto:"))
     194             :         {
     195           3 :                 char msg[128]="";
     196             :                 // Use protocol1 if no choice has been made on client side.
     197           3 :                 if(get_protocol(confs)==PROTO_AUTO)
     198             :                 {
     199           1 :                         logp("Server has protocol=0 (auto)\n");
     200           1 :                         set_protocol(confs, PROTO_1);
     201             :                 }
     202             :                 // Send choice to server.
     203           3 :                 snprintf(msg, sizeof(msg), "protocol=%d",
     204           3 :                         get_protocol(confs));
     205           3 :                 if(asfd->write_str(asfd, CMD_GEN, msg))
     206             :                         goto end;
     207           3 :                 logp("Using protocol=%d\n",
     208           3 :                         get_protocol(confs));
     209             :         }
     210          34 :         else if(server_supports(feat, ":forceproto=1:"))
     211             :         {
     212           2 :                 logp("Server is forcing protocol 1\n");
     213           2 :                 if(get_protocol(confs)!=PROTO_AUTO
     214           2 :                   && get_protocol(confs)!=PROTO_1)
     215             :                 {
     216           1 :                         logp("But client has set protocol=%d!\n",
     217           1 :                                 get_protocol(confs));
     218           1 :                         goto end;
     219             :                 }
     220           1 :                 set_protocol(confs, PROTO_1);
     221             :         }
     222          30 :         else if(server_supports(feat, ":forceproto=2:"))
     223             :         {
     224           2 :                 logp("Server is forcing protocol 2\n");
     225           2 :                 if(get_protocol(confs)!=PROTO_AUTO
     226           2 :                   && get_protocol(confs)!=PROTO_2)
     227             :                 {
     228           1 :                         logp("But client has set protocol=%d!\n",
     229           1 :                                 get_protocol(confs));
     230           1 :                         goto end;
     231             :                 }
     232           1 :                 set_protocol(confs, PROTO_2);
     233             :         }
     234             : 
     235          36 :         if(server_supports(feat, ":msg:"))
     236             :         {
     237           1 :                 set_int(confs[OPT_MESSAGE], 1);
     238           1 :                 if(asfd->write_str(asfd, CMD_GEN, "msg"))
     239             :                         goto end;
     240             :         }
     241             : 
     242             : #ifdef HAVE_BLAKE2
     243             :         if(server_supports(feat, ":rshash=blake2:"))
     244             :         {
     245             :                 set_e_rshash(confs[OPT_RSHASH], RSHASH_BLAKE2);
     246             :                 // Send choice to server.
     247             :                 if(asfd->write_str(asfd, CMD_GEN, "rshash=blake2"))
     248             :                         goto end;
     249             :         }
     250             :         else
     251             : #endif
     252          18 :                 set_e_rshash(confs[OPT_RSHASH], RSHASH_MD4);
     253             : 
     254          18 :         if(asfd->write_str(asfd, CMD_GEN, "extra_comms_end")
     255          18 :           || asfd_read_expect(asfd, CMD_GEN, "extra_comms_end ok"))
     256             :         {
     257           1 :                 logp("Problem requesting extra_comms_end\n");
     258           1 :                 goto end;
     259             :         }
     260             : 
     261             :         ret=0;
     262             : end:
     263          28 :         free_w(&feat);
     264          28 :         return ret;
     265             : }

Generated by: LCOV version 1.13