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