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