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 "protocol2/blk.h"
12 : #include "server/protocol2/rblk.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 132952 : 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 767424 : 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 115 : int sbuf_is_metadata(struct sbuf *sb)
80 : {
81 115 : 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", sb->attr.buf);
112 0 : return -1;
113 : }
114 79962 : if(send_msg_fzp(fzp, CMD_ATTRIBS,
115 79962 : cp, sb->attr.len-(cp-sb->attr.buf)))
116 : return -1;
117 : }
118 91874 : if(iobuf_send_msg_fzp(&sb->path, fzp))
119 : return -1;
120 91874 : if(sb->link.buf
121 15876 : && iobuf_send_msg_fzp(&sb->link, fzp))
122 : return -1;
123 91874 : if(sb->endfile.buf
124 6315 : && iobuf_send_msg_fzp(&sb->endfile, fzp))
125 : return -1;
126 :
127 : return 0;
128 : }
129 :
130 : // Like pathcmp, but sort entries that have the same paths so that metadata
131 : // comes later, and vss comes earlier, and trailing vss comes later.
132 23 : int sbuf_pathcmp(struct sbuf *a, struct sbuf *b)
133 : {
134 23 : return iobuf_pathcmp(&a->path, &b->path);
135 : }
136 :
137 : enum parse_ret
138 : {
139 : PARSE_RET_ERROR=-1,
140 : PARSE_RET_NEED_MORE=0,
141 : PARSE_RET_COMPLETE=1,
142 : PARSE_RET_FINISHED=2,
143 : };
144 :
145 354856 : static enum parse_ret parse_cmd(struct sbuf *sb, struct asfd *asfd,
146 : struct iobuf *rbuf, struct blk *blk,
147 : const char *datpath, 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 : iobuf_free_content(&sb->path);
207 60734 : iobuf_move(&sb->path, rbuf);
208 60734 : if(cmd_is_link(rbuf->cmd))
209 : {
210 9124 : sb->flags |= SBUF_NEED_LINK;
211 9124 : return PARSE_RET_NEED_MORE;
212 : }
213 51610 : else if(sb->protocol1
214 12254 : && sb->protocol1->datapth.buf)
215 : {
216 : // Protocol1 client restore reads
217 : // CMD_APPEND and CMD_END_FILE in the
218 : // calling function, so pretend it is
219 : // complete if we have the hack flag.
220 8303 : if(sb->flags & SBUF_CLIENT_RESTORE_HACK)
221 : return PARSE_RET_COMPLETE;
222 8299 : return PARSE_RET_NEED_MORE;
223 : }
224 : return PARSE_RET_COMPLETE;
225 : }
226 : #ifndef HAVE_WIN32
227 : case CMD_SIG:
228 : // Fill in the sig/block, if the caller provided
229 : // a pointer for one. Server only.
230 198651 : if(!blk) return PARSE_RET_NEED_MORE;
231 :
232 : // Just fill in the sig details.
233 46462 : if(blk_set_from_iobuf_sig_and_savepath(blk, rbuf))
234 : return PARSE_RET_ERROR;
235 46462 : blk->got_save_path=1;
236 46462 : iobuf_free_content(rbuf);
237 46462 : if(datpath && rblk_retrieve_data(datpath, blk))
238 : {
239 0 : logp("Could not retrieve blk data.\n");
240 0 : return PARSE_RET_ERROR;
241 : }
242 : return PARSE_RET_COMPLETE;
243 : #endif
244 : case CMD_DATA:
245 : // Need to write the block to disk.
246 : // Client only.
247 14 : if(!blk) return PARSE_RET_NEED_MORE;
248 14 : blk->data=rbuf->buf;
249 14 : blk->length=rbuf->len;
250 14 : rbuf->buf=NULL;
251 14 : return PARSE_RET_COMPLETE;
252 : case CMD_MESSAGE:
253 : case CMD_WARNING:
254 0 : log_recvd(rbuf, cntr, 1);
255 0 : return PARSE_RET_NEED_MORE;
256 : case CMD_GEN:
257 43 : if(!strcmp(rbuf->buf, "restoreend")
258 39 : || !strcmp(rbuf->buf, "phase1end")
259 1 : || !strcmp(rbuf->buf, "backupphase2")
260 : // Think these are protocol1 things.
261 1 : || !strcmp(rbuf->buf, "backupend")
262 1 : || !strcmp(rbuf->buf, "estimateend"))
263 : return PARSE_RET_FINISHED;
264 1 : iobuf_log_unexpected(rbuf, __func__);
265 1 : return PARSE_RET_ERROR;
266 : case CMD_FINGERPRINT:
267 698 : if(blk && blk_set_from_iobuf_fingerprint(blk, rbuf))
268 : return PARSE_RET_ERROR;
269 : // Fall through.
270 : case CMD_MANIFEST:
271 778 : iobuf_free_content(&sb->path);
272 778 : iobuf_move(&sb->path, rbuf);
273 778 : return PARSE_RET_COMPLETE;
274 : case CMD_ERROR:
275 0 : logp("got error: %s\n", rbuf->buf);
276 0 : return PARSE_RET_ERROR;
277 : case CMD_DATAPTH:
278 8304 : if(!sb->protocol1)
279 : {
280 0 : iobuf_log_unexpected(rbuf, __func__);
281 0 : return PARSE_RET_ERROR;
282 : }
283 8304 : if(sb->flags & SBUF_CLIENT_RESTORE_HACK)
284 : {
285 5 : sbuf_free_content(sb);
286 5 : sb->flags |= SBUF_CLIENT_RESTORE_HACK;
287 : }
288 : else
289 8299 : sbuf_free_content(sb);
290 :
291 8304 : iobuf_move(&sb->protocol1->datapth, rbuf);
292 8304 : return PARSE_RET_NEED_MORE;
293 : case CMD_END_FILE:
294 16453 : iobuf_free_content(&sb->endfile);
295 16453 : iobuf_move(&sb->endfile, rbuf);
296 16453 : if(sb->protocol1)
297 : {
298 8269 : if(!sb->attr.buf
299 8269 : || !sb->protocol1->datapth.buf
300 8269 : || (!sbuf_is_filedata(sb)
301 98 : && !sbuf_is_vssdata(sb)))
302 : {
303 0 : logp("got unexpected cmd_endfile");
304 0 : return PARSE_RET_ERROR;
305 : }
306 : }
307 : return PARSE_RET_COMPLETE;
308 : default:
309 0 : iobuf_log_unexpected(rbuf, __func__);
310 0 : return PARSE_RET_ERROR;
311 : }
312 : logp("Fell out of switch unexpectedly in %s()\n", __func__);
313 : return PARSE_RET_ERROR;
314 : }
315 :
316 116571 : static int sbuf_fill(struct sbuf *sb, struct asfd *asfd, struct fzp *fzp,
317 : struct blk *blk, const char *datpath, struct cntr *cntr)
318 : {
319 : static struct iobuf *rbuf;
320 : static struct iobuf localrbuf;
321 116571 : int ret=-1;
322 :
323 116571 : if(asfd) rbuf=asfd->rbuf;
324 : else
325 : {
326 : // If not given asfd, use our own iobuf.
327 : memset(&localrbuf, 0, sizeof(struct iobuf));
328 116518 : rbuf=&localrbuf;
329 : }
330 : while(1)
331 : {
332 355241 : iobuf_free_content(rbuf);
333 355241 : if(fzp)
334 : {
335 355145 : if((ret=iobuf_fill_from_fzp(rbuf, fzp)))
336 : goto end;
337 : }
338 : else
339 : {
340 96 : if(asfd->read(asfd))
341 : {
342 1 : logp("error in async_read\n");
343 1 : break;
344 : }
345 : }
346 354856 : switch(parse_cmd(sb, asfd, rbuf, blk, datpath, cntr))
347 : {
348 : case PARSE_RET_NEED_MORE:
349 238670 : continue;
350 : case PARSE_RET_COMPLETE:
351 : return 0;
352 : case PARSE_RET_FINISHED:
353 : ret=1;
354 : goto end;
355 : case PARSE_RET_ERROR:
356 : default:
357 2 : ret=-1;
358 2 : goto end;
359 : }
360 238670 : }
361 : end:
362 429 : iobuf_free_content(rbuf);
363 429 : return ret;
364 : }
365 :
366 53 : int sbuf_fill_from_net(struct sbuf *sb, struct asfd *asfd,
367 : struct blk *blk, struct cntr *cntr)
368 : {
369 53 : return sbuf_fill(sb, asfd, NULL, blk, NULL, cntr);
370 : }
371 :
372 116518 : int sbuf_fill_from_file(struct sbuf *sb, struct fzp *fzp,
373 : struct blk *blk, const char *datpath)
374 : {
375 116518 : return sbuf_fill(sb, NULL, fzp, blk, datpath, NULL);
376 : }
|