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