Line data Source code
1 : #include "../burp.h"
2 : #include "../alloc.h"
3 : #include "../asfd.h"
4 : #include "../async.h"
5 : #include "../cmd.h"
6 : #include "../cntr.h"
7 : #include "../iobuf.h"
8 : #include "../log.h"
9 : #include "../prepend.h"
10 : #include "../sbuf.h"
11 : #include "handy.h"
12 : #include "msg.h"
13 :
14 4 : static int do_write(struct asfd *asfd,
15 : BFILE *bfd, uint8_t *out, size_t outlen,
16 : char **metadata, uint64_t *sent)
17 : {
18 4 : int ret=0;
19 4 : if(metadata)
20 : {
21 : // Append it to our metadata.
22 0 : out[outlen]='\0';
23 : //printf("\nadd outlen: %lu\n", outlen);
24 0 : if(!(*metadata=prepend_len(*metadata, *sent,
25 : (const char *)out, outlen,
26 0 : "", 0, (size_t *)sent)))
27 : {
28 0 : logp("error when appending metadata\n");
29 : asfd->write_str(asfd, CMD_ERROR,
30 0 : "error when appending metadata");
31 0 : return -1;
32 : }
33 : }
34 : else
35 : {
36 4 : if((ret=bfd->write(bfd, out, outlen))<=0)
37 : {
38 0 : logp("error when appending %d: %d\n", outlen, ret);
39 0 : asfd->write_str(asfd, CMD_ERROR, "write failed");
40 0 : return -1;
41 : }
42 4 : *sent+=outlen;
43 : }
44 : return 0;
45 : }
46 :
47 4 : static int do_inflate(struct asfd *asfd,
48 : z_stream *zstrm, BFILE *bfd,
49 : uint8_t *out, uint8_t *buftouse, size_t lentouse,
50 : char **metadata, const char *encpassword, int enccompressed,
51 : uint64_t *sent)
52 : {
53 4 : int zret=Z_OK;
54 4 : unsigned have=0;
55 :
56 : // Do not want to inflate encrypted data that was not compressed.
57 : // Just write it straight out.
58 4 : if(encpassword && !enccompressed)
59 0 : return do_write(asfd, bfd, buftouse, lentouse, metadata, sent);
60 :
61 4 : zstrm->avail_in=lentouse;
62 4 : zstrm->next_in=buftouse;
63 :
64 4 : do
65 : {
66 4 : zstrm->avail_out=ZCHUNK;
67 4 : zstrm->next_out=out;
68 4 : zret=inflate(zstrm, Z_NO_FLUSH);
69 4 : switch(zret)
70 : {
71 : case Z_NEED_DICT:
72 0 : zret=Z_DATA_ERROR;
73 : case Z_DATA_ERROR:
74 : case Z_MEM_ERROR:
75 0 : logp("zstrm inflate error: %d\n", zret);
76 0 : return -1;
77 : break;
78 : }
79 4 : have=ZCHUNK-zstrm->avail_out;
80 4 : if(!have) continue;
81 :
82 4 : if(do_write(asfd, bfd, out, have, metadata, sent))
83 : return -1;
84 : /*
85 : if(md5)
86 : {
87 : if(!MD5_Update(md5, out, have))
88 : {
89 : logp("MD5 update error\n");
90 : return -1;
91 : }
92 : }
93 : */
94 4 : } while(!zstrm->avail_out);
95 : return 0;
96 : }
97 :
98 : #ifdef HAVE_WIN32
99 :
100 : struct winbuf
101 : {
102 : uint64_t *rcvd;
103 : uint64_t *sent;
104 : struct cntr *cntr;
105 : struct asfd *asfd;
106 : };
107 :
108 : static DWORD WINAPI read_efs(PBYTE pbData, PVOID pvCallbackContext, PULONG ulLength)
109 : {
110 : struct iobuf *rbuf;
111 : struct winbuf *mybuf=(struct winbuf *)pvCallbackContext;
112 : rbuf=mybuf->asfd->rbuf;
113 :
114 : while(1)
115 : {
116 : if(mybuf->asfd->read(mybuf->asfd))
117 : return ERROR_FUNCTION_FAILED;
118 : (*(mybuf->rcvd))+=rbuf->len;
119 :
120 : switch(rbuf->cmd)
121 : {
122 : case CMD_APPEND:
123 : memcpy(pbData, rbuf->buf, rbuf->len);
124 : *ulLength=(ULONG)rbuf->len;
125 : (*(mybuf->sent))+=rbuf->len;
126 : iobuf_free_content(rbuf);
127 : return ERROR_SUCCESS;
128 : case CMD_END_FILE:
129 : *ulLength=0;
130 : iobuf_free_content(rbuf);
131 : return ERROR_SUCCESS;
132 : case CMD_MESSAGE:
133 : logp("MESSAGE: %s\n", rbuf->buf);
134 : cntr_add(mybuf->cntr, rbuf->cmd, 0);
135 : iobuf_free_content(rbuf);
136 : continue;
137 : case CMD_WARNING:
138 : logp("WARNING: %s\n", rbuf->buf);
139 : cntr_add(mybuf->cntr, rbuf->cmd, 0);
140 : iobuf_free_content(rbuf);
141 : continue;
142 : default:
143 : iobuf_log_unexpected(rbuf, __func__);
144 : iobuf_free_content(rbuf);
145 : break;
146 : }
147 : }
148 : return ERROR_FUNCTION_FAILED;
149 : }
150 :
151 : static int transfer_efs_in(struct asfd *asfd,
152 : BFILE *bfd, uint64_t *rcvd,
153 : uint64_t *sent, struct cntr *cntr)
154 : {
155 : int ret=0;
156 : struct winbuf mybuf;
157 : mybuf.rcvd=rcvd;
158 : mybuf.sent=sent;
159 : mybuf.cntr=cntr;
160 : mybuf.asfd=asfd;
161 : if((ret=WriteEncryptedFileRaw((PFE_IMPORT_FUNC)read_efs,
162 : &mybuf, bfd->pvContext)))
163 : logp("WriteEncryptedFileRaw returned %d\n", ret);
164 : return ret;
165 : }
166 :
167 : #endif
168 :
169 4 : int transfer_gzfile_inl(struct asfd *asfd,
170 : struct sbuf *sb, const char *path, BFILE *bfd,
171 : uint64_t *rcvd, uint64_t *sent,
172 : const char *encpassword, int enccompressed,
173 : struct cntr *cntr, char **metadata)
174 : {
175 4 : int quit=0;
176 4 : int ret=-1;
177 : uint8_t out[ZCHUNK];
178 4 : int doutlen=0;
179 : //uint8_t doutbuf[1000+EVP_MAX_BLOCK_LENGTH];
180 : uint8_t doutbuf[ZCHUNK-EVP_MAX_BLOCK_LENGTH];
181 4 : struct iobuf *rbuf=asfd->rbuf;
182 :
183 : z_stream zstrm;
184 :
185 4 : EVP_CIPHER_CTX *enc_ctx=NULL;
186 :
187 : // Checksum stuff
188 : //MD5_CTX md5;
189 : //uint8_t checksum[MD5_DIGEST_LENGTH];
190 :
191 : #ifdef HAVE_WIN32
192 : if(sb && sb->path.cmd==CMD_EFS_FILE)
193 : return transfer_efs_in(asfd, bfd, rcvd, sent, cntr);
194 : #endif
195 :
196 : //if(!MD5_Init(&md5))
197 : //{
198 : // logp("MD5_Init() failed");
199 : // return -1;
200 : //}
201 :
202 4 : zstrm.zalloc=Z_NULL;
203 4 : zstrm.zfree=Z_NULL;
204 4 : zstrm.opaque=Z_NULL;
205 4 : zstrm.avail_in=0;
206 4 : zstrm.next_in=Z_NULL;
207 :
208 4 : if(inflateInit2(&zstrm, (15+16)))
209 : {
210 0 : logp("unable to init inflate\n");
211 0 : return -1;
212 : }
213 :
214 4 : if(encpassword && !(enc_ctx=enc_setup(0, encpassword)))
215 : {
216 0 : inflateEnd(&zstrm);
217 0 : return -1;
218 : }
219 :
220 12 : while(!quit)
221 : {
222 8 : iobuf_free_content(rbuf);
223 8 : if(asfd->read(asfd))
224 : {
225 0 : if(enc_ctx)
226 : {
227 0 : EVP_CIPHER_CTX_cleanup(enc_ctx);
228 0 : free_v((void **)&enc_ctx);
229 : }
230 0 : inflateEnd(&zstrm);
231 0 : return -1;
232 : }
233 8 : (*rcvd)+=rbuf->len;
234 :
235 : //logp("transfer in: %c:%s\n", rbuf->cmd, rbuf->buf);
236 8 : switch(rbuf->cmd)
237 : {
238 : case CMD_APPEND: // append
239 4 : if(!bfd && !metadata)
240 : {
241 0 : logp("given append, but no file or metadata to write to\n");
242 : asfd->write_str(asfd, CMD_ERROR,
243 0 : "append with no file or metadata");
244 0 : quit++; ret=-1;
245 : }
246 : else
247 : {
248 : size_t lentouse;
249 4 : uint8_t *buftouse=NULL;
250 : /*
251 : if(!MD5_Update(&md5, rbuf->buf, rbuf->len))
252 : {
253 : logp("MD5 update enc error\n");
254 : quit++; ret=-1;
255 : break;
256 : }
257 : */
258 : // If doing decryption, it needs
259 : // to be done before uncompressing.
260 4 : if(enc_ctx)
261 : {
262 : // updating our checksum needs to
263 : // be done first
264 : /*
265 : if(!MD5_Update(&md5, rbuf->buf, rbuf->len))
266 : {
267 : logp("MD5 update enc error\n");
268 : quit++; ret=-1;
269 : break;
270 : }
271 : else
272 : */
273 0 : if(!EVP_CipherUpdate(enc_ctx,
274 : doutbuf, &doutlen,
275 : (uint8_t *)rbuf->buf,
276 0 : rbuf->len))
277 : {
278 0 : logp("Decryption error\n");
279 0 : quit++; ret=-1;
280 0 : break;
281 : }
282 0 : if(!doutlen) break;
283 0 : lentouse=(size_t)doutlen;
284 0 : buftouse=doutbuf;
285 : }
286 : else
287 : {
288 4 : lentouse=rbuf->len;
289 4 : buftouse=(uint8_t *)rbuf->buf;
290 : }
291 : //logp("want to write: %d\n", zstrm.avail_in);
292 :
293 4 : if(do_inflate(asfd, &zstrm, bfd, out,
294 : buftouse, lentouse, metadata,
295 : encpassword,
296 : enccompressed,
297 4 : sent))
298 : {
299 0 : ret=-1; quit++;
300 0 : break;
301 : }
302 : }
303 : break;
304 : case CMD_END_FILE: // finish up
305 4 : if(enc_ctx)
306 : {
307 0 : if(!EVP_CipherFinal_ex(enc_ctx,
308 0 : doutbuf, &doutlen))
309 : {
310 0 : logp("Decryption failure at the end.\n");
311 0 : ret=-1; quit++;
312 0 : break;
313 : }
314 0 : if(doutlen && do_inflate(asfd,
315 : &zstrm, bfd,
316 : out, doutbuf, (size_t)doutlen,
317 : metadata, encpassword,
318 0 : enccompressed, sent))
319 : {
320 0 : ret=-1; quit++;
321 0 : break;
322 : }
323 : }
324 : /*
325 : if(MD5_Final(checksum, &md5))
326 : {
327 : char *oldsum=NULL;
328 : const char *newsum=NULL;
329 :
330 : if((oldsum=strchr(buf, ':')))
331 : {
332 : oldsum++;
333 : newsum=bytes_to_md5str(checksum);
334 : // log if the checksum differed
335 : if(strcmp(newsum, oldsum))
336 : logw(asfd, cntr, "md5sum for '%s' did not match! (%s!=%s)\n", path, newsum, oldsum);
337 : }
338 : }
339 : else
340 : {
341 : logp("MD5_Final() failed\n");
342 : }
343 : */
344 4 : quit++;
345 4 : ret=0;
346 4 : break;
347 : case CMD_MESSAGE:
348 : case CMD_WARNING:
349 0 : log_recvd(rbuf, cntr, 0);
350 0 : break;
351 : default:
352 0 : iobuf_log_unexpected(rbuf, __func__);
353 0 : quit++;
354 0 : ret=-1;
355 0 : break;
356 : }
357 : }
358 4 : inflateEnd(&zstrm);
359 4 : if(enc_ctx)
360 : {
361 0 : EVP_CIPHER_CTX_cleanup(enc_ctx);
362 0 : free_v((void **)&enc_ctx);
363 : }
364 :
365 4 : iobuf_free_content(rbuf);
366 4 : if(ret) logp("transfer file returning: %d\n", ret);
367 4 : return ret;
368 : }
|