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