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