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