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 196 : return strstr(feat, wanted);
22 : }
23 :
24 23 : 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 23 : if(!strcmp(feat, "extra_comms_begin ok")) return "ok";
29 23 : return server_supports(feat, ":autoupgrade:");
30 : }
31 :
32 : #include <librsync.h>
33 :
34 26 : int extra_comms_client(struct async *as, struct conf **confs,
35 : enum action *action, char **incexc)
36 : {
37 26 : int ret=-1;
38 26 : char *feat=NULL;
39 : struct asfd *asfd;
40 : struct iobuf *rbuf;
41 26 : const char *orig_client=NULL;
42 26 : asfd=as->asfd;
43 26 : rbuf=asfd->rbuf;
44 :
45 26 : 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 25 : if(asfd->read(asfd))
53 : {
54 1 : logp("Problem reading response to extra_comms_begin\n");
55 1 : goto end;
56 : }
57 24 : if(rbuf->cmd!=CMD_GEN
58 24 : || strncmp_w(rbuf->buf, "extra_comms_begin ok"))
59 : {
60 1 : iobuf_log_unexpected(rbuf, __func__);
61 1 : goto end;
62 : }
63 23 : feat=rbuf->buf;
64 23 : rbuf->buf=NULL;
65 23 : logp("%s\n", feat);
66 23 : iobuf_init(rbuf);
67 :
68 : // Can add extra bits here. The first extra bit is the
69 : // autoupgrade stuff.
70 23 : 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 44 : if(server_supports(feat, ":srestore:"))
79 : {
80 4 : logp("Server wants to initiate a restore\n");
81 4 : if(*action==ACTION_MONITOR)
82 : {
83 1 : logp("Client is in monitor mode, so ignoring\n");
84 : }
85 3 : else if(get_int(confs[OPT_SERVER_CAN_RESTORE]))
86 : {
87 2 : logp("Client accepts.\n");
88 2 : if(incexc_recv_client_restore(asfd, incexc, confs))
89 : goto end;
90 2 : if(*incexc)
91 : {
92 2 : if(conf_parse_incexcs_buf(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 : 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[128]="";
181 : snprintf(msg, sizeof(msg),
182 : "uname=%s", clientos);
183 1 : if(asfd->write_str(asfd, CMD_GEN, msg))
184 : goto end;
185 : }
186 : }
187 :
188 40 : if(server_supports(feat, ":csetproto:"))
189 : {
190 3 : char msg[128]="";
191 : // Use protocol1 if no choice has been made on client side.
192 3 : if(get_protocol(confs)==PROTO_AUTO)
193 : {
194 1 : logp("Server has protocol=0 (auto)\n");
195 1 : set_protocol(confs, PROTO_1);
196 : }
197 : // Send choice to server.
198 : snprintf(msg, sizeof(msg), "protocol=%d",
199 3 : get_protocol(confs));
200 3 : if(asfd->write_str(asfd, CMD_GEN, msg))
201 : goto end;
202 3 : logp("Using protocol=%d\n",
203 3 : get_protocol(confs));
204 : }
205 34 : else if(server_supports(feat, ":forceproto=1:"))
206 : {
207 2 : logp("Server is forcing protocol 1\n");
208 2 : if(get_protocol(confs)!=PROTO_AUTO
209 2 : && get_protocol(confs)!=PROTO_1)
210 : {
211 1 : logp("But client has set protocol=%d!\n",
212 1 : get_protocol(confs));
213 1 : goto end;
214 : }
215 1 : set_protocol(confs, PROTO_1);
216 : }
217 30 : else if(server_supports(feat, ":forceproto=2:"))
218 : {
219 2 : logp("Server is forcing protocol 2\n");
220 2 : if(get_protocol(confs)!=PROTO_AUTO
221 2 : && get_protocol(confs)!=PROTO_2)
222 : {
223 1 : logp("But client has set protocol=%d!\n",
224 1 : get_protocol(confs));
225 1 : goto end;
226 : }
227 1 : set_protocol(confs, PROTO_2);
228 : }
229 :
230 36 : if(server_supports(feat, ":msg:"))
231 : {
232 1 : set_int(confs[OPT_MESSAGE], 1);
233 1 : if(asfd->write_str(asfd, CMD_GEN, "msg"))
234 : goto end;
235 : }
236 :
237 : #ifndef RS_DEFAULT_STRONG_LEN
238 : if(server_supports(feat, ":rshash=blake2:"))
239 : {
240 : set_e_rshash(confs[OPT_RSHASH], RSHASH_BLAKE2);
241 : // Send choice to server.
242 : if(asfd->write_str(asfd, CMD_GEN, "rshash=blake2"))
243 : goto end;
244 : }
245 : else
246 : #endif
247 18 : set_e_rshash(confs[OPT_RSHASH], RSHASH_MD4);
248 :
249 18 : if(asfd->write_str(asfd, CMD_GEN, "extra_comms_end")
250 18 : || asfd_read_expect(asfd, CMD_GEN, "extra_comms_end ok"))
251 : {
252 1 : logp("Problem requesting extra_comms_end\n");
253 1 : goto end;
254 : }
255 :
256 : ret=0;
257 : end:
258 26 : free_w(&feat);
259 26 : return ret;
260 : }
|