Line data Source code
1 : #include "burp.h"
2 : #include "sbuf.h"
3 : #include "alloc.h"
4 : #include "asfd.h"
5 : #include "attribs.h"
6 : #include "cmd.h"
7 : #include "conf.h"
8 : #include "handy.h"
9 : #include "log.h"
10 : #include "msg.h"
11 : #include "pathcmp.h"
12 : #include "protocol2/blk.h"
13 :
14 132952 : struct sbuf *sbuf_alloc(enum protocol protocol)
15 : {
16 : struct sbuf *sb;
17 132952 : if(!(sb=(struct sbuf *)calloc_w(1, sizeof(struct sbuf), __func__)))
18 : return NULL;
19 132952 : iobuf_init(&sb->path);
20 132952 : iobuf_init(&sb->attr);
21 132952 : sb->attr.cmd=CMD_ATTRIBS;
22 132952 : iobuf_init(&sb->link);
23 132952 : iobuf_init(&sb->endfile);
24 132952 : sb->compression=-1;
25 132952 : if(protocol==PROTO_1)
26 : {
27 32297 : if(!(sb->protocol1=sbuf_protocol1_alloc())) return NULL;
28 : }
29 : else
30 : {
31 100655 : if(!(sb->protocol2=sbuf_protocol2_alloc())) return NULL;
32 : }
33 : return sb;
34 : }
35 :
36 229752 : void sbuf_free_content(struct sbuf *sb)
37 : {
38 229752 : iobuf_free_content(&sb->path);
39 229752 : iobuf_free_content(&sb->attr);
40 229752 : iobuf_free_content(&sb->link);
41 229752 : iobuf_free_content(&sb->endfile);
42 229752 : memset(&(sb->statp), 0, sizeof(sb->statp));
43 229752 : sb->compression=-1;
44 229752 : sb->winattr=0;
45 229752 : sb->flags=0;
46 229752 : sbuf_protocol1_free_content(sb->protocol1);
47 229752 : sbuf_protocol2_free_content();
48 229752 : }
49 :
50 383712 : void sbuf_free(struct sbuf **sb)
51 : {
52 383712 : if(!sb || !*sb) return;
53 132952 : sbuf_free_content(*sb);
54 132952 : free_v((void **)&((*sb)->protocol1));
55 132952 : free_v((void **)&((*sb)->protocol2));
56 132952 : free_v((void **)sb);
57 : }
58 :
59 110 : int sbuf_is_link(struct sbuf *sb)
60 : {
61 110 : return iobuf_is_link(&sb->path);
62 : }
63 :
64 219249 : int sbuf_is_filedata(struct sbuf *sb)
65 : {
66 227518 : return iobuf_is_filedata(&sb->path);
67 : }
68 :
69 10733 : int sbuf_is_vssdata(struct sbuf *sb)
70 : {
71 10831 : return iobuf_is_vssdata(&sb->path);
72 : }
73 :
74 85249 : int sbuf_is_encrypted(struct sbuf *sb)
75 : {
76 85249 : return iobuf_is_encrypted(&sb->path);
77 : }
78 :
79 117 : int sbuf_is_metadata(struct sbuf *sb)
80 : {
81 117 : return iobuf_is_metadata(&sb->path);
82 : }
83 :
84 0 : int sbuf_is_estimatable(struct sbuf *sb)
85 : {
86 0 : return iobuf_is_estimatable(&sb->path);
87 : }
88 :
89 91874 : int sbuf_to_manifest(struct sbuf *sb, struct fzp *fzp)
90 : {
91 91874 : if(!sb->path.buf) return 0;
92 :
93 91874 : if(sb->protocol1)
94 : {
95 11912 : if(sb->protocol1->datapth.buf
96 6311 : && iobuf_send_msg_fzp(&(sb->protocol1->datapth), fzp))
97 : return -1;
98 :
99 11912 : if(iobuf_send_msg_fzp(&sb->attr, fzp))
100 : return -1;
101 : }
102 : else
103 : {
104 : // Hackity hack: Strip the file index from the beginning of
105 : // the attribs so that manifests where nothing changed are
106 : // identical to each other. Better would be to preserve the
107 : // index.
108 : char *cp;
109 79962 : if(!(cp=strchr(sb->attr.buf, ' ')))
110 : {
111 0 : logp("Strange attributes: %s\n",
112 : iobuf_to_printable(&sb->attr));
113 0 : return -1;
114 : }
115 79962 : if(send_msg_fzp(fzp, CMD_ATTRIBS,
116 79962 : cp, sb->attr.len-(cp-sb->attr.buf)))
117 : return -1;
118 : }
119 91874 : if(iobuf_send_msg_fzp(&sb->path, fzp))
120 : return -1;
121 91874 : if(sb->link.buf
122 15876 : && iobuf_send_msg_fzp(&sb->link, fzp))
123 : return -1;
124 91874 : if(sb->endfile.buf
125 6315 : && iobuf_send_msg_fzp(&sb->endfile, fzp))
126 : return -1;
127 :
128 : return 0;
129 : }
130 :
131 : // Like pathcmp, but sort entries that have the same paths so that metadata
132 : // comes later, and vss comes earlier, and trailing vss comes later.
133 23 : int sbuf_pathcmp(struct sbuf *a, struct sbuf *b)
134 : {
135 23 : return iobuf_pathcmp(&a->path, &b->path);
136 : }
137 :
138 : enum parse_ret
139 : {
140 : PARSE_RET_ERROR=-1,
141 : PARSE_RET_NEED_MORE=0,
142 : PARSE_RET_COMPLETE=1,
143 : PARSE_RET_FINISHED=2,
144 : };
145 :
146 354856 : static enum parse_ret parse_cmd(struct sbuf *sb, struct asfd *asfd,
147 : struct iobuf *rbuf, struct blk *blk, struct cntr *cntr)
148 : {
149 354856 : switch(rbuf->cmd)
150 : {
151 : case CMD_ATTRIBS:
152 60754 : if(sb->protocol2)
153 47097 : sbuf_free_content(sb);
154 : else
155 : {
156 13657 : if(sb->protocol1->datapth.buf)
157 : // protocol 1 phase 2+ file data
158 : // starts with datapth.
159 8303 : iobuf_free_content(&sb->attr);
160 : else
161 : // protocol 1 phase 1 or non file data
162 : // starts with attribs
163 5354 : sbuf_free_content(sb);
164 : }
165 60754 : iobuf_move(&sb->attr, rbuf);
166 60754 : attribs_decode(sb);
167 60754 : return PARSE_RET_NEED_MORE;
168 :
169 : case CMD_FILE:
170 : case CMD_DIRECTORY:
171 : case CMD_SOFT_LINK:
172 : case CMD_HARD_LINK:
173 : case CMD_SPECIAL:
174 : // Stuff not currently supported in burp-2, but OK
175 : // to find in burp-1.
176 : case CMD_ENC_FILE:
177 : case CMD_METADATA:
178 : case CMD_ENC_METADATA:
179 : case CMD_EFS_FILE:
180 : case CMD_VSS:
181 : case CMD_ENC_VSS:
182 : case CMD_VSS_T:
183 : case CMD_ENC_VSS_T:
184 69859 : if(!sb->attr.buf)
185 : {
186 1 : log_and_send(asfd, "read cmd with no attribs");
187 1 : return PARSE_RET_ERROR;
188 : }
189 69858 : if(sb->flags & SBUF_NEED_LINK)
190 : {
191 9124 : if(cmd_is_link(rbuf->cmd))
192 : {
193 9124 : iobuf_free_content(&sb->link);
194 9124 : iobuf_move(&sb->link, rbuf);
195 9124 : sb->flags &= ~SBUF_NEED_LINK;
196 9124 : return PARSE_RET_COMPLETE;
197 : }
198 : else
199 : {
200 0 : log_and_send(asfd, "got non-link after link in manifest");
201 0 : return PARSE_RET_NEED_MORE;
202 : }
203 : }
204 : else
205 : {
206 60734 : if(iobuf_relative_path_attack(rbuf))
207 : return PARSE_RET_ERROR;
208 :
209 60734 : iobuf_free_content(&sb->path);
210 60734 : iobuf_move(&sb->path, rbuf);
211 60734 : if(cmd_is_link(rbuf->cmd))
212 : {
213 9124 : sb->flags |= SBUF_NEED_LINK;
214 9124 : return PARSE_RET_NEED_MORE;
215 : }
216 51610 : else if(sb->protocol1
217 12254 : && sb->protocol1->datapth.buf)
218 : {
219 : // Protocol1 client restore reads
220 : // CMD_APPEND and CMD_END_FILE in the
221 : // calling function, so pretend it is
222 : // complete if we have the hack flag.
223 8303 : if(sb->flags & SBUF_CLIENT_RESTORE_HACK)
224 : return PARSE_RET_COMPLETE;
225 8299 : return PARSE_RET_NEED_MORE;
226 : }
227 : return PARSE_RET_COMPLETE;
228 : }
229 : #ifndef HAVE_WIN32
230 : case CMD_SIG:
231 : // Fill in the sig/block, if the caller provided
232 : // a pointer for one. Server only.
233 198651 : if(!blk) return PARSE_RET_NEED_MORE;
234 :
235 : // Just fill in the sig details.
236 46462 : if(blk_set_from_iobuf_sig_and_savepath(blk, rbuf))
237 : return PARSE_RET_ERROR;
238 46462 : blk->got_save_path=1;
239 46462 : iobuf_free_content(rbuf);
240 46462 : return PARSE_RET_COMPLETE;
241 : #endif
242 : case CMD_DATA:
243 : // Need to write the block to disk.
244 : // Client only.
245 14 : if(!blk) return PARSE_RET_NEED_MORE;
246 14 : blk->data=rbuf->buf;
247 14 : blk->length=rbuf->len;
248 14 : rbuf->buf=NULL;
249 14 : return PARSE_RET_COMPLETE;
250 : case CMD_MESSAGE:
251 : case CMD_WARNING:
252 0 : log_recvd(rbuf, cntr, 1);
253 0 : return PARSE_RET_NEED_MORE;
254 : case CMD_GEN:
255 43 : if(!strcmp(rbuf->buf, "restoreend")
256 39 : || !strcmp(rbuf->buf, "phase1end")
257 1 : || !strcmp(rbuf->buf, "backupphase2")
258 : // Think these are protocol1 things.
259 1 : || !strcmp(rbuf->buf, "backupend")
260 1 : || !strcmp(rbuf->buf, "estimateend"))
261 : return PARSE_RET_FINISHED;
262 1 : iobuf_log_unexpected(rbuf, __func__);
263 1 : return PARSE_RET_ERROR;
264 : case CMD_FINGERPRINT:
265 698 : if(blk && blk_set_from_iobuf_fingerprint(blk, rbuf))
266 : return PARSE_RET_ERROR;
267 698 : iobuf_free_content(&sb->path);
268 698 : iobuf_move(&sb->path, rbuf);
269 698 : return PARSE_RET_COMPLETE;
270 : case CMD_MANIFEST:
271 80 : if(iobuf_relative_path_attack(rbuf))
272 : return PARSE_RET_ERROR;
273 80 : iobuf_free_content(&sb->path);
274 80 : iobuf_move(&sb->path, rbuf);
275 80 : return PARSE_RET_COMPLETE;
276 : case CMD_ERROR:
277 0 : logp("got error: %s\n", rbuf->buf);
278 0 : return PARSE_RET_ERROR;
279 : case CMD_DATAPTH:
280 8304 : if(iobuf_relative_path_attack(rbuf))
281 : return PARSE_RET_ERROR;
282 :
283 8304 : if(!sb->protocol1)
284 : {
285 0 : iobuf_log_unexpected(rbuf, __func__);
286 0 : return PARSE_RET_ERROR;
287 : }
288 8304 : if(sb->flags & SBUF_CLIENT_RESTORE_HACK)
289 : {
290 5 : sbuf_free_content(sb);
291 5 : sb->flags |= SBUF_CLIENT_RESTORE_HACK;
292 : }
293 : else
294 8299 : sbuf_free_content(sb);
295 :
296 8304 : iobuf_move(&sb->protocol1->datapth, rbuf);
297 8304 : return PARSE_RET_NEED_MORE;
298 : case CMD_END_FILE:
299 16453 : iobuf_free_content(&sb->endfile);
300 16453 : iobuf_move(&sb->endfile, rbuf);
301 16453 : if(sb->protocol1)
302 : {
303 8269 : if(!sb->attr.buf
304 8269 : || !sb->protocol1->datapth.buf
305 8269 : || (!sbuf_is_filedata(sb)
306 98 : && !sbuf_is_vssdata(sb)))
307 : {
308 0 : logp("got unexpected cmd_endfile");
309 0 : return PARSE_RET_ERROR;
310 : }
311 : }
312 : return PARSE_RET_COMPLETE;
313 : default:
314 0 : iobuf_log_unexpected(rbuf, __func__);
315 0 : return PARSE_RET_ERROR;
316 : }
317 : logp("Fell out of switch unexpectedly in %s()\n", __func__);
318 : return PARSE_RET_ERROR;
319 : }
320 :
321 116571 : static int sbuf_fill(struct sbuf *sb, struct asfd *asfd, struct fzp *fzp,
322 : struct blk *blk, struct cntr *cntr)
323 : {
324 : static struct iobuf *rbuf;
325 : static struct iobuf localrbuf;
326 116571 : int ret=-1;
327 :
328 116571 : if(asfd) rbuf=asfd->rbuf;
329 : else
330 : {
331 : // If not given asfd, use our own iobuf.
332 116518 : memset(&localrbuf, 0, sizeof(struct iobuf));
333 116518 : rbuf=&localrbuf;
334 : }
335 : while(1)
336 : {
337 593911 : iobuf_free_content(rbuf);
338 355241 : if(fzp)
339 : {
340 355145 : if((ret=iobuf_fill_from_fzp(rbuf, fzp)))
341 : goto end;
342 : }
343 : else
344 : {
345 96 : if(asfd->read(asfd))
346 : {
347 1 : logp("error in async_read\n");
348 1 : break;
349 : }
350 : }
351 354856 : switch(parse_cmd(sb, asfd, rbuf, blk, cntr))
352 : {
353 : case PARSE_RET_NEED_MORE:
354 238670 : continue;
355 : case PARSE_RET_COMPLETE:
356 : return 0;
357 : case PARSE_RET_FINISHED:
358 : ret=1;
359 : goto end;
360 : case PARSE_RET_ERROR:
361 : default:
362 2 : ret=-1;
363 2 : goto end;
364 : }
365 : }
366 : end:
367 429 : iobuf_free_content(rbuf);
368 429 : return ret;
369 : }
370 :
371 53 : int sbuf_fill_from_net(struct sbuf *sb, struct asfd *asfd,
372 : struct blk *blk, struct cntr *cntr)
373 : {
374 53 : return sbuf_fill(sb, asfd, NULL, blk, cntr);
375 : }
376 :
377 116518 : int sbuf_fill_from_file(struct sbuf *sb, struct fzp *fzp,
378 : struct blk *blk)
379 : {
380 116518 : return sbuf_fill(sb, NULL, fzp, blk, NULL);
381 : }
|