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 "handy_extra.h"
8 : #include "iobuf.h"
9 : #include "log.h"
10 : #include "prepend.h"
11 : #include "sbuf.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 4 : } while(!zstrm->avail_out);
86 : return 0;
87 : }
88 :
89 : #ifdef HAVE_WIN32
90 :
91 : struct winbuf
92 : {
93 : uint64_t *rcvd;
94 : uint64_t *sent;
95 : struct cntr *cntr;
96 : struct asfd *asfd;
97 : };
98 :
99 : static DWORD WINAPI read_efs(PBYTE pbData, PVOID pvCallbackContext, PULONG ulLength)
100 : {
101 : struct iobuf *rbuf;
102 : struct winbuf *mybuf=(struct winbuf *)pvCallbackContext;
103 : rbuf=mybuf->asfd->rbuf;
104 :
105 : while(1)
106 : {
107 : if(mybuf->asfd->read(mybuf->asfd))
108 : return ERROR_FUNCTION_FAILED;
109 : (*(mybuf->rcvd))+=rbuf->len;
110 :
111 : switch(rbuf->cmd)
112 : {
113 : case CMD_APPEND:
114 : memcpy(pbData, rbuf->buf, rbuf->len);
115 : *ulLength=(ULONG)rbuf->len;
116 : (*(mybuf->sent))+=rbuf->len;
117 : iobuf_free_content(rbuf);
118 : return ERROR_SUCCESS;
119 : case CMD_END_FILE:
120 : *ulLength=0;
121 : iobuf_free_content(rbuf);
122 : return ERROR_SUCCESS;
123 : case CMD_MESSAGE:
124 : logp("MESSAGE: %s\n", rbuf->buf);
125 : cntr_add(mybuf->cntr, rbuf->cmd, 0);
126 : iobuf_free_content(rbuf);
127 : continue;
128 : case CMD_WARNING:
129 : logp("WARNING: %s\n", rbuf->buf);
130 : cntr_add(mybuf->cntr, rbuf->cmd, 0);
131 : iobuf_free_content(rbuf);
132 : continue;
133 : default:
134 : iobuf_log_unexpected(rbuf, __func__);
135 : iobuf_free_content(rbuf);
136 : break;
137 : }
138 : }
139 : return ERROR_FUNCTION_FAILED;
140 : }
141 :
142 : static int transfer_efs_in(struct asfd *asfd,
143 : struct BFILE *bfd, uint64_t *rcvd,
144 : uint64_t *sent, struct cntr *cntr)
145 : {
146 : int ret=0;
147 : struct winbuf mybuf;
148 : mybuf.rcvd=rcvd;
149 : mybuf.sent=sent;
150 : mybuf.cntr=cntr;
151 : mybuf.asfd=asfd;
152 : if((ret=WriteEncryptedFileRaw((PFE_IMPORT_FUNC)read_efs,
153 : &mybuf, bfd->pvContext)))
154 : logp("WriteEncryptedFileRaw returned %d\n", ret);
155 : return ret;
156 : }
157 :
158 : #endif
159 :
160 4 : int transfer_gzfile_inl(struct asfd *asfd,
161 : #ifdef HAVE_WIN32
162 : struct sbuf *sb,
163 : #endif
164 : struct BFILE *bfd,
165 : uint64_t *rcvd, uint64_t *sent,
166 : const char *encpassword, int enccompressed,
167 : struct cntr *cntr, char **metadata,
168 : int key_deriv, uint64_t salt)
169 : {
170 4 : int quit=0;
171 4 : int ret=-1;
172 : uint8_t out[ZCHUNK];
173 4 : int doutlen=0;
174 : uint8_t doutbuf[ZCHUNK-EVP_MAX_BLOCK_LENGTH];
175 4 : struct iobuf *rbuf=asfd->rbuf;
176 :
177 : z_stream zstrm;
178 :
179 4 : EVP_CIPHER_CTX *enc_ctx=NULL;
180 :
181 : #ifdef HAVE_WIN32
182 : if(sb && sb->path.cmd==CMD_EFS_FILE)
183 : return transfer_efs_in(asfd, bfd, rcvd, sent, cntr);
184 : #endif
185 :
186 4 : zstrm.zalloc=Z_NULL;
187 4 : zstrm.zfree=Z_NULL;
188 4 : zstrm.opaque=Z_NULL;
189 4 : zstrm.avail_in=0;
190 4 : zstrm.next_in=Z_NULL;
191 :
192 4 : if(inflateInit2(&zstrm, (15+16)))
193 : {
194 0 : logp("unable to init inflate\n");
195 0 : return -1;
196 : }
197 :
198 4 : if(encpassword
199 0 : && !(enc_ctx=enc_setup(0, encpassword, key_deriv, salt)))
200 : {
201 0 : inflateEnd(&zstrm);
202 0 : return -1;
203 : }
204 :
205 12 : while(!quit)
206 : {
207 8 : iobuf_free_content(rbuf);
208 8 : if(asfd->read(asfd))
209 : {
210 0 : if(enc_ctx)
211 : {
212 0 : EVP_CIPHER_CTX_cleanup(enc_ctx);
213 0 : EVP_CIPHER_CTX_free(enc_ctx);
214 0 : enc_ctx=NULL;
215 : }
216 0 : inflateEnd(&zstrm);
217 0 : return -1;
218 : }
219 8 : (*rcvd)+=rbuf->len;
220 :
221 8 : switch(rbuf->cmd)
222 : {
223 : case CMD_APPEND: // append
224 4 : if(!bfd && !metadata)
225 : {
226 0 : logp("given append, but no file or metadata to write to\n");
227 0 : asfd->write_str(asfd, CMD_ERROR,
228 : "append with no file or metadata");
229 0 : quit++; ret=-1;
230 : }
231 : else
232 : {
233 : size_t lentouse;
234 4 : uint8_t *buftouse=NULL;
235 : // If doing decryption, it needs
236 : // to be done before uncompressing.
237 4 : if(enc_ctx)
238 : {
239 : // updating our checksum needs to
240 : // be done first
241 0 : if(!EVP_CipherUpdate(enc_ctx,
242 : doutbuf, &doutlen,
243 0 : (uint8_t *)rbuf->buf,
244 0 : rbuf->len))
245 : {
246 0 : logp("Decryption error\n");
247 0 : quit++; ret=-1;
248 0 : break;
249 : }
250 0 : if(!doutlen) break;
251 0 : lentouse=(size_t)doutlen;
252 0 : buftouse=doutbuf;
253 : }
254 : else
255 : {
256 4 : lentouse=rbuf->len;
257 4 : buftouse=(uint8_t *)rbuf->buf;
258 : }
259 : //logp("want to write: %d\n", zstrm.avail_in);
260 :
261 4 : if(do_inflate(asfd, &zstrm, bfd, out,
262 : buftouse, lentouse, metadata,
263 : encpassword,
264 : enccompressed,
265 : sent))
266 : {
267 0 : ret=-1; quit++;
268 0 : break;
269 : }
270 : }
271 : break;
272 : case CMD_END_FILE: // finish up
273 4 : if(enc_ctx)
274 : {
275 0 : if(!EVP_CipherFinal_ex(enc_ctx,
276 : doutbuf, &doutlen))
277 : {
278 0 : logp("Decryption failure at the end.\n");
279 0 : ret=-1; quit++;
280 0 : break;
281 : }
282 0 : if(doutlen && do_inflate(asfd,
283 : &zstrm, bfd,
284 : out, doutbuf, (size_t)doutlen,
285 : metadata, encpassword,
286 : enccompressed, sent))
287 : {
288 0 : ret=-1; quit++;
289 0 : break;
290 : }
291 : }
292 4 : quit++;
293 4 : ret=0;
294 4 : break;
295 : case CMD_MESSAGE:
296 : case CMD_WARNING:
297 0 : log_recvd(rbuf, cntr, 0);
298 0 : break;
299 : default:
300 0 : iobuf_log_unexpected(rbuf, __func__);
301 0 : quit++;
302 0 : ret=-1;
303 0 : break;
304 : }
305 : }
306 4 : inflateEnd(&zstrm);
307 4 : if(enc_ctx)
308 : {
309 0 : EVP_CIPHER_CTX_cleanup(enc_ctx);
310 0 : EVP_CIPHER_CTX_free(enc_ctx);
311 0 : enc_ctx=NULL;
312 : }
313 :
314 4 : iobuf_free_content(rbuf);
315 4 : if(ret) logp("transfer file returning: %d\n", ret);
316 : return ret;
317 : }
|