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(incexc_recv_client(asfd, incexc, confs))
129 : goto end;
130 0 : if(*incexc && conf_parse_incexcs_buf(confs,
131 0 : *incexc)) goto end;
132 : }
133 : }
134 :
135 0 : if(server_supports(feat, ":counters:"))
136 : {
137 0 : if(asfd->write_str(asfd, CMD_GEN, "countersok"))
138 : goto end;
139 0 : set_int(confs[OPT_SEND_CLIENT_CNTR], 1);
140 : }
141 :
142 : // :incexc: is for the client sending the server the
143 : // incexc conf so that it better knows what to do on
144 : // resume.
145 0 : if(server_supports(feat, ":incexc:")
146 0 : && incexc_send_client(asfd, confs))
147 : goto end;
148 :
149 0 : if(server_supports(feat, ":uname:"))
150 : {
151 0 : const char *clientos=NULL;
152 : #ifdef HAVE_WIN32
153 : #ifdef _WIN64
154 : clientos="Windows 64bit";
155 : #else
156 : clientos="Windows 32bit";
157 : #endif
158 : #else
159 : struct utsname utsname;
160 0 : if(!uname(&utsname))
161 0 : clientos=(const char *)utsname.sysname;
162 : #endif
163 0 : if(clientos)
164 : {
165 0 : char msg[128]="";
166 : snprintf(msg, sizeof(msg),
167 : "uname=%s", clientos);
168 0 : if(asfd->write_str(asfd, CMD_GEN, msg))
169 : goto end;
170 : }
171 : }
172 :
173 0 : if(server_supports(feat, ":csetproto:"))
174 : {
175 0 : char msg[128]="";
176 : // Use protocol2 if no choice has been made on client side.
177 0 : if(get_protocol(confs)==PROTO_AUTO)
178 : {
179 0 : logp("Server has protocol=0 (auto)\n");
180 0 : set_protocol(confs, PROTO_2);
181 : }
182 : // Send choice to server.
183 : snprintf(msg, sizeof(msg), "protocol=%d",
184 0 : get_protocol(confs));
185 0 : if(asfd->write_str(asfd, CMD_GEN, msg))
186 : goto end;
187 : logp("Using protocol=%d\n",
188 0 : get_protocol(confs));
189 : }
190 0 : else if(server_supports(feat, ":forceproto=1:"))
191 : {
192 0 : logp("Server is forcing protocol 1\n");
193 0 : if(get_protocol(confs)!=PROTO_AUTO
194 0 : && get_protocol(confs)!=PROTO_1)
195 : {
196 : logp("But client has set protocol=%d!\n",
197 0 : get_protocol(confs));
198 0 : goto end;
199 : }
200 0 : set_protocol(confs, PROTO_1);
201 : }
202 0 : else if(server_supports(feat, ":forceproto=2:"))
203 : {
204 0 : logp("Server is forcing protocol 2\n");
205 0 : if(get_protocol(confs)!=PROTO_AUTO
206 0 : && get_protocol(confs)!=PROTO_2)
207 : {
208 : logp("But client has set protocol=%d!\n",
209 0 : get_protocol(confs));
210 0 : goto end;
211 : }
212 0 : set_protocol(confs, PROTO_2);
213 : }
214 :
215 0 : if(server_supports(feat, ":msg:"))
216 : {
217 0 : set_int(confs[OPT_MESSAGE], 1);
218 0 : if(asfd->write_str(asfd, CMD_GEN, "msg"))
219 : goto end;
220 : }
221 :
222 : #ifndef RS_DEFAULT_STRONG_LEN
223 0 : if(server_supports(feat, ":rshash=blake2:"))
224 : {
225 0 : set_e_rshash(confs[OPT_RSHASH], RSHASH_BLAKE2);
226 : // Send choice to server.
227 0 : if(asfd->write_str(asfd, CMD_GEN, "rshash=blake2"))
228 : goto end;
229 : }
230 : else
231 : #endif
232 0 : set_e_rshash(confs[OPT_RSHASH], RSHASH_MD4);
233 :
234 0 : if(asfd->write_str(asfd, CMD_GEN, "extra_comms_end")
235 0 : || asfd_read_expect(asfd, CMD_GEN, "extra_comms_end ok"))
236 : {
237 0 : logp("Problem requesting extra_comms_end\n");
238 0 : goto end;
239 : }
240 :
241 : ret=0;
242 : end:
243 0 : return ret;
244 : }
|