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, struct cntr *cntr)
147 : {
148 354856 : switch(rbuf->cmd)
149 : {
150 : case CMD_ATTRIBS:
151 60754 : if(sb->protocol2)
152 47097 : sbuf_free_content(sb);
153 : else
154 : {
155 13657 : if(sb->protocol1->datapth.buf)
156 : // protocol 1 phase 2+ file data
157 : // starts with datapth.
158 8303 : iobuf_free_content(&sb->attr);
159 : else
160 : // protocol 1 phase 1 or non file data
161 : // starts with attribs
162 5354 : sbuf_free_content(sb);
163 : }
164 60754 : iobuf_move(&sb->attr, rbuf);
165 60754 : attribs_decode(sb);
166 60754 : return PARSE_RET_NEED_MORE;
167 :
168 : case CMD_FILE:
169 : case CMD_DIRECTORY:
170 : case CMD_SOFT_LINK:
171 : case CMD_HARD_LINK:
172 : case CMD_SPECIAL:
173 : // Stuff not currently supported in burp-2, but OK
174 : // to find in burp-1.
175 : case CMD_ENC_FILE:
176 : case CMD_METADATA:
177 : case CMD_ENC_METADATA:
178 : case CMD_EFS_FILE:
179 : case CMD_VSS:
180 : case CMD_ENC_VSS:
181 : case CMD_VSS_T:
182 : case CMD_ENC_VSS_T:
183 69859 : if(!sb->attr.buf)
184 : {
185 1 : log_and_send(asfd, "read cmd with no attribs");
186 1 : return PARSE_RET_ERROR;
187 : }
188 69858 : if(sb->flags & SBUF_NEED_LINK)
189 : {
190 9124 : if(cmd_is_link(rbuf->cmd))
191 : {
192 9124 : iobuf_free_content(&sb->link);
193 9124 : iobuf_move(&sb->link, rbuf);
194 9124 : sb->flags &= ~SBUF_NEED_LINK;
195 9124 : return PARSE_RET_COMPLETE;
196 : }
197 : else
198 : {
199 0 : log_and_send(asfd, "got non-link after link in manifest");
200 0 : return PARSE_RET_NEED_MORE;
201 : }
202 : }
203 : else
204 : {
205 60734 : iobuf_free_content(&sb->path);
206 60734 : iobuf_move(&sb->path, rbuf);
207 60734 : if(cmd_is_link(rbuf->cmd))
208 : {
209 9124 : sb->flags |= SBUF_NEED_LINK;
210 9124 : return PARSE_RET_NEED_MORE;
211 : }
212 51610 : else if(sb->protocol1
213 12254 : && sb->protocol1->datapth.buf)
214 : {
215 : // Protocol1 client restore reads
216 : // CMD_APPEND and CMD_END_FILE in the
217 : // calling function, so pretend it is
218 : // complete if we have the hack flag.
219 8303 : if(sb->flags & SBUF_CLIENT_RESTORE_HACK)
220 : return PARSE_RET_COMPLETE;
221 8299 : return PARSE_RET_NEED_MORE;
222 : }
223 : return PARSE_RET_COMPLETE;
224 : }
225 : #ifndef HAVE_WIN32
226 : case CMD_SIG:
227 : // Fill in the sig/block, if the caller provided
228 : // a pointer for one. Server only.
229 198651 : if(!blk) return PARSE_RET_NEED_MORE;
230 :
231 : // Just fill in the sig details.
232 46462 : if(blk_set_from_iobuf_sig_and_savepath(blk, rbuf))
233 : return PARSE_RET_ERROR;
234 46462 : blk->got_save_path=1;
235 46462 : iobuf_free_content(rbuf);
236 46462 : return PARSE_RET_COMPLETE;
237 : #endif
238 : case CMD_DATA:
239 : // Need to write the block to disk.
240 : // Client only.
241 14 : if(!blk) return PARSE_RET_NEED_MORE;
242 14 : blk->data=rbuf->buf;
243 14 : blk->length=rbuf->len;
244 14 : rbuf->buf=NULL;
245 14 : return PARSE_RET_COMPLETE;
246 : case CMD_MESSAGE:
247 : case CMD_WARNING:
248 0 : log_recvd(rbuf, cntr, 1);
249 0 : return PARSE_RET_NEED_MORE;
250 : case CMD_GEN:
251 43 : if(!strcmp(rbuf->buf, "restoreend")
252 39 : || !strcmp(rbuf->buf, "phase1end")
253 1 : || !strcmp(rbuf->buf, "backupphase2")
254 : // Think these are protocol1 things.
255 1 : || !strcmp(rbuf->buf, "backupend")
256 1 : || !strcmp(rbuf->buf, "estimateend"))
257 : return PARSE_RET_FINISHED;
258 1 : iobuf_log_unexpected(rbuf, __func__);
259 1 : return PARSE_RET_ERROR;
260 : case CMD_FINGERPRINT:
261 698 : if(blk && blk_set_from_iobuf_fingerprint(blk, rbuf))
262 : return PARSE_RET_ERROR;
263 : // Fall through.
264 : case CMD_MANIFEST:
265 778 : iobuf_free_content(&sb->path);
266 778 : iobuf_move(&sb->path, rbuf);
267 778 : return PARSE_RET_COMPLETE;
268 : case CMD_ERROR:
269 0 : logp("got error: %s\n", rbuf->buf);
270 0 : return PARSE_RET_ERROR;
271 : case CMD_DATAPTH:
272 8304 : if(!sb->protocol1)
273 : {
274 0 : iobuf_log_unexpected(rbuf, __func__);
275 0 : return PARSE_RET_ERROR;
276 : }
277 8304 : if(sb->flags & SBUF_CLIENT_RESTORE_HACK)
278 : {
279 5 : sbuf_free_content(sb);
280 5 : sb->flags |= SBUF_CLIENT_RESTORE_HACK;
281 : }
282 : else
283 8299 : sbuf_free_content(sb);
284 :
285 8304 : iobuf_move(&sb->protocol1->datapth, rbuf);
286 8304 : return PARSE_RET_NEED_MORE;
287 : case CMD_END_FILE:
288 16453 : iobuf_free_content(&sb->endfile);
289 16453 : iobuf_move(&sb->endfile, rbuf);
290 16453 : if(sb->protocol1)
291 : {
292 8269 : if(!sb->attr.buf
293 8269 : || !sb->protocol1->datapth.buf
294 8269 : || (!sbuf_is_filedata(sb)
295 98 : && !sbuf_is_vssdata(sb)))
296 : {
297 0 : logp("got unexpected cmd_endfile");
298 0 : return PARSE_RET_ERROR;
299 : }
300 : }
301 : return PARSE_RET_COMPLETE;
302 : default:
303 0 : iobuf_log_unexpected(rbuf, __func__);
304 0 : return PARSE_RET_ERROR;
305 : }
306 : logp("Fell out of switch unexpectedly in %s()\n", __func__);
307 : return PARSE_RET_ERROR;
308 : }
309 :
310 116571 : static int sbuf_fill(struct sbuf *sb, struct asfd *asfd, struct fzp *fzp,
311 : struct blk *blk, struct cntr *cntr)
312 : {
313 : static struct iobuf *rbuf;
314 : static struct iobuf localrbuf;
315 116571 : int ret=-1;
316 :
317 116571 : if(asfd) rbuf=asfd->rbuf;
318 : else
319 : {
320 : // If not given asfd, use our own iobuf.
321 : memset(&localrbuf, 0, sizeof(struct iobuf));
322 116518 : rbuf=&localrbuf;
323 : }
324 : while(1)
325 : {
326 355241 : iobuf_free_content(rbuf);
327 355241 : if(fzp)
328 : {
329 355145 : if((ret=iobuf_fill_from_fzp(rbuf, fzp)))
330 : goto end;
331 : }
332 : else
333 : {
334 96 : if(asfd->read(asfd))
335 : {
336 1 : logp("error in async_read\n");
337 1 : break;
338 : }
339 : }
340 354856 : switch(parse_cmd(sb, asfd, rbuf, blk, cntr))
341 : {
342 : case PARSE_RET_NEED_MORE:
343 238670 : continue;
344 : case PARSE_RET_COMPLETE:
345 : return 0;
346 : case PARSE_RET_FINISHED:
347 : ret=1;
348 : goto end;
349 : case PARSE_RET_ERROR:
350 : default:
351 2 : ret=-1;
352 2 : goto end;
353 : }
354 238670 : }
355 : end:
356 429 : iobuf_free_content(rbuf);
357 429 : return ret;
358 : }
359 :
360 53 : int sbuf_fill_from_net(struct sbuf *sb, struct asfd *asfd,
361 : struct blk *blk, struct cntr *cntr)
362 : {
363 53 : return sbuf_fill(sb, asfd, NULL, blk, cntr);
364 : }
365 :
366 116518 : int sbuf_fill_from_file(struct sbuf *sb, struct fzp *fzp,
367 : struct blk *blk)
368 : {
369 116518 : return sbuf_fill(sb, NULL, fzp, blk, NULL);
370 : }
|