LCOV - code coverage report
Current view: top level - src/client - extra_comms.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 94 131 71.8 %
Date: 2022-12-03 01:09:05 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         140 :         return strstr(feat, wanted);
      22             : }
      23             : 
      24          18 : 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          18 :         if(!strcmp(feat, "extra_comms_begin ok")) return "ok";
      29          18 :         return server_supports(feat, ":autoupgrade:");
      30             : }
      31             : 
      32             : #include <librsync.h>
      33             : 
      34          21 : int extra_comms_client(struct async *as, struct conf **confs,
      35             :         enum action *action, struct strlist *failover, char **incexc)
      36             : {
      37          21 :         int ret=-1;
      38          21 :         char *feat=NULL;
      39          21 :         char *seed_src=NULL;
      40          21 :         char *seed_dst=NULL;
      41             :         struct asfd *asfd;
      42             :         struct iobuf *rbuf;
      43          21 :         const char *orig_client=NULL;
      44          21 :         asfd=as->asfd;
      45          21 :         rbuf=asfd->rbuf;
      46             : 
      47          21 :         if(asfd->write_str(asfd, CMD_GEN, "extra_comms_begin"))
      48             :         {
      49           1 :                 logp("Problem requesting extra_comms_begin\n");
      50           1 :                 goto end;
      51             :         }
      52             :         // Servers greater than 1.3.0 will list the extra_comms
      53             :         // features they support.
      54          20 :         if(asfd->read(asfd))
      55             :         {
      56           1 :                 logp("Problem reading response to extra_comms_begin\n");
      57           1 :                 goto end;
      58             :         }
      59          19 :         if(rbuf->cmd!=CMD_GEN
      60          19 :           || strncmp_w(rbuf->buf, "extra_comms_begin ok"))
      61             :         {
      62           1 :                 iobuf_log_unexpected(rbuf, __func__);
      63           1 :                 goto end;
      64             :         }
      65          18 :         feat=rbuf->buf;
      66          18 :         rbuf->buf=NULL;
      67          18 :         logp("%s\n", feat);
      68          18 :         iobuf_init(rbuf);
      69             : 
      70             :         // Can add extra bits here. The first extra bit is the
      71             :         // autoupgrade stuff.
      72          18 :         if(server_supports_autoupgrade(feat)
      73           1 :           && get_string(confs[OPT_AUTOUPGRADE_DIR])
      74           1 :           && get_string(confs[OPT_AUTOUPGRADE_OS])
      75           1 :           && autoupgrade_client(as, confs))
      76             :                 goto end;
      77             : 
      78             : 
      79             :         // :srestore: means that the server wants to do a restore.
      80          34 :         if(server_supports(feat, ":srestore:"))
      81             :         {
      82           6 :                 logp("Server wants to initiate a restore\n");
      83           6 :                 if(*action==ACTION_MONITOR)
      84             :                 {
      85           1 :                         logp("Client is in monitor mode, so ignoring\n");
      86             :                 }
      87           5 :                 else if(get_int(confs[OPT_SERVER_CAN_RESTORE]))
      88             :                 {
      89           4 :                         logp("Client accepts.\n");
      90           4 :                         if(incexc_recv_client_restore(asfd, incexc, confs))
      91             :                                 goto end;
      92           4 :                         if(*incexc)
      93             :                         {
      94           4 :                                 if(conf_parse_incexcs_srestore(confs, *incexc))
      95             :                                         goto end;
      96           2 :                                 *action=ACTION_RESTORE;
      97           2 :                                 log_restore_settings(confs, 1);
      98             :                         }
      99             :                 }
     100             :                 else
     101             :                 {
     102           1 :                         logp("Client configuration says no\n");
     103           1 :                         if(asfd->write_str(asfd, CMD_GEN, "srestore not ok"))
     104             :                                 goto end;
     105             :                 }
     106             :         }
     107             : 
     108             :         // Needs to be after the srestore stuff, as the server may set
     109             :         // orig_client in the server-initiated restore file.
     110          15 :         if((orig_client=get_string(confs[OPT_ORIG_CLIENT])))
     111             :         {
     112           4 :                 char str[512]="";
     113           4 :                 snprintf(str, sizeof(str), "orig_client=%s", orig_client);
     114           8 :                 if(!server_supports(feat, ":orig_client:"))
     115             :                 {
     116           1 :                         logp("Server does not support switching client.\n");
     117           1 :                         goto end;
     118             :                 }
     119           3 :                 if(asfd->write_str(asfd, CMD_GEN, str)
     120           3 :                   || asfd_read_expect(asfd, CMD_GEN, "orig_client ok"))
     121             :                 {
     122           1 :                         logp("Problem requesting %s\n", str);
     123           1 :                         goto end;
     124             :                 }
     125           2 :                 logp("Switched to client %s\n", orig_client);
     126             :         }
     127             : 
     128             :         // :sincexc: is for the server giving the client the
     129             :         // incexc config.
     130          26 :         if(*action==ACTION_BACKUP
     131          13 :           || *action==ACTION_BACKUP_TIMED
     132           3 :           || *action==ACTION_TIMER_CHECK)
     133             :         {
     134          20 :                 if(!*incexc && server_supports(feat, ":sincexc:"))
     135             :                 {
     136           2 :                         logp("Server is setting includes/excludes.\n");
     137           2 :                         if(get_int(confs[OPT_SERVER_CAN_OVERRIDE_INCLUDES]))
     138             :                         {
     139           1 :                                 logp("Client accepts.\n");
     140           1 :                                 if(incexc_recv_client(asfd, incexc, confs))
     141             :                                         goto end;
     142           1 :                                 if(*incexc && conf_parse_incexcs_buf(confs,
     143             :                                         *incexc)) goto end;
     144             :                         }
     145             :                         else
     146             :                         {
     147           1 :                                 logp("Client configuration says no\n");
     148             :                         }
     149             :                 }
     150             :         }
     151             : 
     152          26 :         if(server_supports(feat, ":counters_json:"))
     153             :         {
     154           1 :                 if(asfd->write_str(asfd, CMD_GEN, "counters_json ok"))
     155             :                         goto end;
     156           1 :                 set_int(confs[OPT_SEND_CLIENT_CNTR], 1);
     157             :         }
     158             : 
     159             :         // :incexc: is for the client sending the server the
     160             :         // incexc conf so that it better knows what to do on
     161             :         // resume.
     162          26 :         if(server_supports(feat, ":incexc:")
     163           0 :           && incexc_send_client(asfd, confs))
     164             :                 goto end;
     165             : 
     166          26 :         if(server_supports(feat, ":uname:"))
     167             :         {
     168           1 :                 const char *clientos=NULL;
     169             : #ifdef HAVE_WIN32
     170             : #ifdef _WIN64
     171             :                 clientos="Windows 64bit";
     172             : #else
     173             :                 clientos="Windows 32bit";
     174             : #endif
     175             : #else
     176             :                 struct utsname utsname;
     177           1 :                 if(!uname(&utsname))
     178           1 :                         clientos=(const char *)utsname.sysname;
     179             : #endif
     180           1 :                 if(clientos)
     181             :                 {
     182           1 :                         char *msg=NULL;
     183           1 :                         if(astrcat(&msg, "uname=", __func__)
     184           1 :                           || astrcat(&msg, clientos, __func__))
     185             :                                 goto end;
     186           1 :                         if(asfd->write_str(asfd, CMD_GEN, msg))
     187             :                         {
     188           0 :                                 free_w(&msg);
     189           0 :                                 goto end;
     190             :                         }
     191           1 :                         free_w(&msg);
     192             :                 }
     193             :         }
     194             : 
     195          26 :         if(server_supports(feat, ":msg:"))
     196             :         {
     197           1 :                 set_int(confs[OPT_MESSAGE], 1);
     198           1 :                 if(asfd->write_str(asfd, CMD_GEN, "msg"))
     199             :                         goto end;
     200             :         }
     201             : 
     202             : #ifdef HAVE_BLAKE2
     203             :         if(server_supports(feat, ":rshash=blake2:"))
     204             :         {
     205             :                 set_e_rshash(confs[OPT_RSHASH], RSHASH_BLAKE2);
     206             :                 // Send choice to server.
     207             :                 if(asfd->write_str(asfd, CMD_GEN, "rshash=blake2"))
     208             :                         goto end;
     209             :         }
     210             :         else
     211             : #endif
     212          13 :                 set_e_rshash(confs[OPT_RSHASH], RSHASH_MD4);
     213             : 
     214          26 :         if(server_supports(feat, ":failover:"))
     215             :         {
     216           0 :                 if(*action==ACTION_BACKUP
     217           0 :                   || *action==ACTION_BACKUP_TIMED)
     218             :                 {
     219           0 :                         char msg[64]="";
     220           0 :                         int left=0;
     221           0 :                         struct strlist *f=NULL;
     222           0 :                         for(f=failover; f; f=f->next)
     223           0 :                                 left++;
     224           0 :                         snprintf(msg, sizeof(msg),
     225             :                                 "backup_failovers_left=%d", left);
     226           0 :                         if(asfd->write_str(asfd, CMD_GEN, msg))
     227             :                                 goto end;
     228             :                 }
     229             :         }
     230             : 
     231          13 :         seed_src=get_string(confs[OPT_SEED_SRC]);
     232          13 :         seed_dst=get_string(confs[OPT_SEED_DST]);
     233          13 :         if(seed_src && *seed_src
     234           0 :           && seed_dst && *seed_dst
     235           0 :           && server_supports(feat, ":seed:"))
     236             :         {
     237           0 :                 char *msg=NULL;
     238           0 :                 logp("Seeding from %s\n", seed_src);
     239           0 :                 if(astrcat(&msg, "seed_src=", __func__)
     240           0 :                   || astrcat(&msg, seed_src, __func__)
     241           0 :                   || asfd->write_str(asfd, CMD_GEN, msg))
     242             :                 {
     243           0 :                         free_w(&msg);
     244           0 :                         goto end;
     245             :                 }
     246           0 :                 free_w(&msg);
     247           0 :                 logp("Seeding to %s\n", seed_dst);
     248           0 :                 if(astrcat(&msg, "seed_dst=", __func__)
     249           0 :                   || astrcat(&msg, seed_dst, __func__)
     250           0 :                   || asfd->write_str(asfd, CMD_GEN, msg))
     251             :                 {
     252           0 :                         free_w(&msg);
     253           0 :                         goto end;
     254             :                 }
     255           0 :                 free_w(&msg);
     256             :         }
     257             : 
     258          26 :         if(server_supports(feat, ":vss_restore:"))
     259             :         {
     260           0 :                 enum vss_restore vss_restore=(enum vss_restore)
     261           0 :                         get_int(confs[OPT_VSS_RESTORE]);
     262           0 :                 if(vss_restore==VSS_RESTORE_OFF
     263           0 :                   && asfd->write_str(asfd, CMD_GEN, "vss_restore=off"))
     264             :                         goto end;
     265           0 :                 if(vss_restore==VSS_RESTORE_OFF_STRIP
     266           0 :                   && asfd->write_str(asfd, CMD_GEN, "vss_restore=strip"))
     267             :                         goto end;
     268             :         }
     269             : 
     270          26 :         if(server_supports(feat, ":regex_icase:"))
     271             :         {
     272           0 :                 if(get_int(confs[OPT_REGEX_CASE_INSENSITIVE]))
     273             :                 {
     274           0 :                           if(asfd->write_str(asfd, CMD_GEN,
     275             :                                 "regex_icase=1"))
     276             :                                         goto end;
     277             :                 }
     278             :         }
     279             : 
     280          13 :         if(asfd->write_str(asfd, CMD_GEN, "extra_comms_end")
     281          13 :           || asfd_read_expect(asfd, CMD_GEN, "extra_comms_end ok"))
     282             :         {
     283           1 :                 logp("Problem requesting extra_comms_end\n");
     284           1 :                 goto end;
     285             :         }
     286             : 
     287             :         ret=0;
     288             : end:
     289          21 :         free_w(&feat);
     290          21 :         return ret;
     291             : }

Generated by: LCOV version 1.13