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 :
13 32346 : struct sbuf *sbuf_alloc()
14 : {
15 : struct sbuf *sb;
16 32346 : if(!(sb=(struct sbuf *)calloc_w(1, sizeof(struct sbuf), __func__)))
17 : return NULL;
18 32346 : iobuf_init(&sb->path);
19 32346 : iobuf_init(&sb->attr);
20 32346 : sb->attr.cmd=CMD_ATTRIBS;
21 32346 : iobuf_init(&sb->link);
22 32346 : iobuf_init(&sb->endfile);
23 32346 : sb->compression=-1;
24 32346 : sb->use_winapi=1;
25 32346 : sb->datapth.cmd=CMD_DATAPTH;
26 :
27 32346 : return sb;
28 : }
29 :
30 59651 : void sbuf_free_content(struct sbuf *sb)
31 : {
32 59651 : iobuf_free_content(&sb->path);
33 59651 : iobuf_free_content(&sb->attr);
34 59651 : iobuf_free_content(&sb->link);
35 59651 : iobuf_free_content(&sb->endfile);
36 59651 : memset(&(sb->statp), 0, sizeof(sb->statp));
37 59651 : sb->compression=-1;
38 59651 : sb->winattr=0;
39 59651 : sb->use_winapi=1;
40 59651 : sb->flags=0;
41 :
42 59651 : memset(&sb->rsbuf, 0, sizeof(sb->rsbuf));
43 59651 : if(sb->sigjob) { rs_job_free(sb->sigjob); sb->sigjob=NULL; }
44 59651 : rs_filebuf_free(&sb->infb);
45 59651 : rs_filebuf_free(&sb->outfb);
46 59651 : fzp_close(&sb->sigfzp);
47 59651 : fzp_close(&sb->fzp);
48 59651 : sb->salt=0;
49 59651 : iobuf_free_content(&sb->datapth);
50 59651 : sb->datapth.cmd=CMD_DATAPTH;
51 59651 : }
52 :
53 32367 : void sbuf_free(struct sbuf **sb)
54 : {
55 32367 : if(!sb || !*sb) return;
56 32346 : sbuf_free_content(*sb);
57 32346 : free_v((void **)sb);
58 : }
59 :
60 26 : int sbuf_is_link(struct sbuf *sb)
61 : {
62 26 : return iobuf_is_link(&sb->path);
63 : }
64 :
65 24462 : int sbuf_is_filedata(struct sbuf *sb)
66 : {
67 32744 : return iobuf_is_filedata(&sb->path);
68 : }
69 :
70 5060 : int sbuf_is_vssdata(struct sbuf *sb)
71 : {
72 5158 : return iobuf_is_vssdata(&sb->path);
73 : }
74 :
75 38 : int sbuf_is_encrypted(struct sbuf *sb)
76 : {
77 38 : return iobuf_is_encrypted(&sb->path);
78 : }
79 :
80 0 : int sbuf_is_metadata(struct sbuf *sb)
81 : {
82 0 : return iobuf_is_metadata(&sb->path);
83 : }
84 :
85 0 : int sbuf_is_estimatable(struct sbuf *sb)
86 : {
87 0 : return iobuf_is_estimatable(&sb->path);
88 : }
89 :
90 11932 : int sbuf_to_manifest(struct sbuf *sb, struct fzp *fzp)
91 : {
92 11932 : if(!sb->path.buf) return 0;
93 :
94 11932 : if(sb->datapth.buf
95 6324 : && iobuf_send_msg_fzp(&(sb->datapth), fzp))
96 : return -1;
97 :
98 11932 : if(iobuf_send_msg_fzp(&sb->attr, fzp))
99 : return -1;
100 11932 : if(iobuf_send_msg_fzp(&sb->path, fzp))
101 : return -1;
102 11932 : if(sb->link.buf
103 1426 : && iobuf_send_msg_fzp(&sb->link, fzp))
104 : return -1;
105 11932 : if(sb->endfile.buf
106 6324 : && iobuf_send_msg_fzp(&sb->endfile, fzp))
107 : return -1;
108 :
109 : return 0;
110 : }
111 :
112 84 : int sbuf_to_manifest_cntr(struct sbuf *sb, struct fzp *fzp,
113 : enum cntr_manio what)
114 : {
115 84 : if(!sb->path.buf) return 0;
116 84 : fzp_printf(fzp, "%c", (char)what);
117 84 : return iobuf_send_msg_fzp(&sb->path, fzp);
118 : }
119 :
120 : // Like pathcmp, but sort entries that have the same paths so that metadata
121 : // comes later, and vss comes earlier, and trailing vss comes later.
122 17 : int sbuf_pathcmp(struct sbuf *a, struct sbuf *b)
123 : {
124 17 : return iobuf_pathcmp(&a->path, &b->path);
125 : }
126 :
127 : enum parse_ret
128 : {
129 : PARSE_RET_ERROR=-1,
130 : PARSE_RET_NEED_MORE=0,
131 : PARSE_RET_COMPLETE=1,
132 : PARSE_RET_FINISHED=2,
133 : };
134 :
135 45359 : static enum parse_ret parse_cmd(struct sbuf *sb, struct asfd *asfd,
136 : struct iobuf *rbuf, struct cntr *cntr)
137 : {
138 45359 : switch(rbuf->cmd)
139 : {
140 : case CMD_ATTRIBS:
141 13677 : if(sb->datapth.buf)
142 8316 : iobuf_free_content(&sb->attr);
143 : else
144 5361 : sbuf_free_content(sb);
145 13677 : iobuf_move(&sb->attr, rbuf);
146 13677 : attribs_decode(sb);
147 13677 : return PARSE_RET_NEED_MORE;
148 :
149 : case CMD_FILE:
150 : case CMD_DIRECTORY:
151 : case CMD_SOFT_LINK:
152 : case CMD_HARD_LINK:
153 : case CMD_SPECIAL:
154 : // Stuff not currently supported in burp-2, but OK
155 : // to find in burp-1.
156 : case CMD_ENC_FILE:
157 : case CMD_METADATA:
158 : case CMD_ENC_METADATA:
159 : case CMD_EFS_FILE:
160 : case CMD_VSS:
161 : case CMD_ENC_VSS:
162 : case CMD_VSS_T:
163 : case CMD_ENC_VSS_T:
164 15064 : if(!sb->attr.buf)
165 : {
166 1 : log_and_send(asfd, "read cmd with no attribs");
167 1 : return PARSE_RET_ERROR;
168 : }
169 15063 : if(sb->flags & SBUF_NEED_LINK)
170 : {
171 1396 : if(cmd_is_link(rbuf->cmd))
172 : {
173 1396 : iobuf_free_content(&sb->link);
174 1396 : iobuf_move(&sb->link, rbuf);
175 1396 : sb->flags &= ~SBUF_NEED_LINK;
176 1396 : return PARSE_RET_COMPLETE;
177 : }
178 : else
179 : {
180 0 : log_and_send(asfd, "got non-link after link in manifest");
181 0 : return PARSE_RET_NEED_MORE;
182 : }
183 : }
184 : else
185 : {
186 13667 : if(iobuf_relative_path_attack(rbuf))
187 : return PARSE_RET_ERROR;
188 :
189 13667 : iobuf_free_content(&sb->path);
190 13667 : iobuf_move(&sb->path, rbuf);
191 13667 : if(cmd_is_link(rbuf->cmd))
192 : {
193 1396 : sb->flags |= SBUF_NEED_LINK;
194 1396 : return PARSE_RET_NEED_MORE;
195 : }
196 12271 : else if(sb->datapth.buf)
197 : {
198 : // Restore reads CMD_APPEND and
199 : // CMD_END_FILE in the calling
200 : // function, so pretend it is
201 : // complete if we have the hack flag.
202 8316 : if(sb->flags & SBUF_CLIENT_RESTORE_HACK)
203 : return PARSE_RET_COMPLETE;
204 8312 : return PARSE_RET_NEED_MORE;
205 : }
206 : return PARSE_RET_COMPLETE;
207 : }
208 : case CMD_MESSAGE:
209 : case CMD_WARNING:
210 0 : log_recvd(rbuf, cntr, 1);
211 0 : return PARSE_RET_NEED_MORE;
212 : case CMD_GEN:
213 19 : if(!strcmp(rbuf->buf, "restoreend")
214 17 : || !strcmp(rbuf->buf, "phase1end")
215 1 : || !strcmp(rbuf->buf, "backupphase2")
216 1 : || !strcmp(rbuf->buf, "backupend")
217 1 : || !strcmp(rbuf->buf, "estimateend"))
218 : return PARSE_RET_FINISHED;
219 1 : iobuf_log_unexpected(rbuf, __func__);
220 1 : return PARSE_RET_ERROR;
221 : case CMD_MANIFEST:
222 0 : if(iobuf_relative_path_attack(rbuf))
223 : return PARSE_RET_ERROR;
224 0 : iobuf_free_content(&sb->path);
225 0 : iobuf_move(&sb->path, rbuf);
226 0 : return PARSE_RET_COMPLETE;
227 : case CMD_ERROR:
228 0 : logp("got error: %s\n", rbuf->buf);
229 0 : return PARSE_RET_ERROR;
230 : case CMD_DATAPTH:
231 8317 : if(iobuf_relative_path_attack(rbuf))
232 : return PARSE_RET_ERROR;
233 :
234 8317 : if(sb->flags & SBUF_CLIENT_RESTORE_HACK)
235 : {
236 5 : sbuf_free_content(sb);
237 5 : sb->flags |= SBUF_CLIENT_RESTORE_HACK;
238 : }
239 : else
240 8312 : sbuf_free_content(sb);
241 :
242 8317 : iobuf_move(&sb->datapth, rbuf);
243 8317 : return PARSE_RET_NEED_MORE;
244 : case CMD_END_FILE:
245 8282 : iobuf_free_content(&sb->endfile);
246 8282 : iobuf_move(&sb->endfile, rbuf);
247 8282 : if(!sb->attr.buf
248 8282 : || !sb->datapth.buf
249 8282 : || (!sbuf_is_filedata(sb)
250 98 : && !sbuf_is_vssdata(sb)))
251 : {
252 0 : logp("got unexpected cmd_endfile");
253 0 : return PARSE_RET_ERROR;
254 : }
255 : return PARSE_RET_COMPLETE;
256 : default:
257 0 : iobuf_log_unexpected(rbuf, __func__);
258 0 : return PARSE_RET_ERROR;
259 : }
260 : logp("Fell out of switch unexpectedly in %s()\n", __func__);
261 : return PARSE_RET_ERROR;
262 : }
263 :
264 13791 : static int sbuf_fill(struct sbuf *sb, struct asfd *asfd, struct fzp *fzp,
265 : struct cntr *cntr)
266 : {
267 : static struct iobuf *rbuf;
268 : static struct iobuf localrbuf;
269 13791 : int ret=-1;
270 :
271 13791 : if(asfd) rbuf=asfd->rbuf;
272 : else
273 : {
274 : // If not given asfd, use our own iobuf.
275 13777 : memset(&localrbuf, 0, sizeof(struct iobuf));
276 13777 : rbuf=&localrbuf;
277 : }
278 : while(1)
279 : {
280 77195 : iobuf_free_content(rbuf);
281 45493 : if(fzp)
282 : {
283 45461 : if((ret=iobuf_fill_from_fzp(rbuf, fzp)))
284 : goto end;
285 : }
286 : else
287 : {
288 32 : if(asfd->read(asfd))
289 : {
290 1 : logp("error in async_read\n");
291 1 : break;
292 : }
293 : }
294 45359 : switch(parse_cmd(sb, asfd, rbuf, cntr))
295 : {
296 : case PARSE_RET_NEED_MORE:
297 31702 : continue;
298 : case PARSE_RET_COMPLETE:
299 : return 0;
300 : case PARSE_RET_FINISHED:
301 : ret=1;
302 : goto end;
303 : case PARSE_RET_ERROR:
304 : default:
305 2 : ret=-1;
306 2 : goto end;
307 : }
308 : }
309 : end:
310 154 : iobuf_free_content(rbuf);
311 154 : return ret;
312 : }
313 :
314 14 : int sbuf_fill_from_net(struct sbuf *sb, struct asfd *asfd,
315 : struct cntr *cntr)
316 : {
317 14 : return sbuf_fill(sb, asfd, NULL, cntr);
318 : }
319 :
320 13777 : int sbuf_fill_from_file(struct sbuf *sb, struct fzp *fzp)
321 : {
322 13777 : return sbuf_fill(sb, NULL, fzp, NULL);
323 : }
|