Line | Source | Count |
1 | | - |
2 | #include <stdio.h> | - |
3 | #include <stdlib.h> | - |
4 | #include <string.h> | - |
5 | #include <openssl/objects.h> | - |
6 | #include <openssl/comp.h> | - |
7 | #include <openssl/err.h> | - |
8 | | - |
9 | COMP_METHOD *COMP_zlib(void ); | - |
10 | | - |
11 | static COMP_METHOD zlib_method_nozlib = { | - |
12 | .type = NID_undef, | - |
13 | .name = "(undef)" | - |
14 | }; | - |
15 | | - |
16 | #ifdef ZLIB | - |
17 | | - |
18 | #include <zlib.h> | - |
19 | | - |
20 | static int zlib_stateful_init(COMP_CTX *ctx); | - |
21 | static void zlib_stateful_finish(COMP_CTX *ctx); | - |
22 | static int zlib_stateful_compress_block(COMP_CTX *ctx, unsigned char *out, | - |
23 | unsigned int olen, unsigned char *in, unsigned int ilen); | - |
24 | static int zlib_stateful_expand_block(COMP_CTX *ctx, unsigned char *out, | - |
25 | unsigned int olen, unsigned char *in, unsigned int ilen); | - |
26 | | - |
27 | | - |
28 | | - |
29 | static void* | - |
30 | zlib_zalloc(void* opaque, unsigned int no, unsigned int size) | - |
31 | { | - |
32 | return calloc(no, size); | - |
33 | } | - |
34 | | - |
35 | static void | - |
36 | zlib_zfree(void* opaque, void* address) | - |
37 | { | - |
38 | free(address); | - |
39 | } | - |
40 | | - |
41 | static COMP_METHOD zlib_stateful_method = { | - |
42 | .type = NID_zlib_compression, | - |
43 | .name = LN_zlib_compression, | - |
44 | .init = zlib_stateful_init, | - |
45 | .finish = zlib_stateful_finish, | - |
46 | .compress = zlib_stateful_compress_block, | - |
47 | .expand = zlib_stateful_expand_block | - |
48 | }; | - |
49 | | - |
50 | struct zlib_state { | - |
51 | z_stream istream; | - |
52 | z_stream ostream; | - |
53 | }; | - |
54 | | - |
55 | static int zlib_stateful_ex_idx = -1; | - |
56 | | - |
57 | static int | - |
58 | zlib_stateful_init(COMP_CTX *ctx) | - |
59 | { | - |
60 | int err; | - |
61 | struct zlib_state *state = malloc(sizeof(struct zlib_state)); | - |
62 | | - |
63 | if (state == NULL) | - |
64 | goto err; | - |
65 | | - |
66 | state->istream.zalloc = zlib_zalloc; | - |
67 | state->istream.zfree = zlib_zfree; | - |
68 | state->istream.opaque = Z_NULL; | - |
69 | state->istream.next_in = Z_NULL; | - |
70 | state->istream.next_out = Z_NULL; | - |
71 | state->istream.avail_in = 0; | - |
72 | state->istream.avail_out = 0; | - |
73 | err = inflateInit_(&state->istream, ZLIB_VERSION, sizeof(z_stream)); | - |
74 | if (err != Z_OK) | - |
75 | goto err; | - |
76 | | - |
77 | state->ostream.zalloc = zlib_zalloc; | - |
78 | state->ostream.zfree = zlib_zfree; | - |
79 | state->ostream.opaque = Z_NULL; | - |
80 | state->ostream.next_in = Z_NULL; | - |
81 | state->ostream.next_out = Z_NULL; | - |
82 | state->ostream.avail_in = 0; | - |
83 | state->ostream.avail_out = 0; | - |
84 | err = deflateInit_(&state->ostream, Z_DEFAULT_COMPRESSION, | - |
85 | ZLIB_VERSION, sizeof(z_stream)); | - |
86 | if (err != Z_OK) | - |
87 | goto err; | - |
88 | | - |
89 | CRYPTO_new_ex_data(CRYPTO_EX_INDEX_COMP, ctx, &ctx->ex_data); | - |
90 | CRYPTO_set_ex_data(&ctx->ex_data, zlib_stateful_ex_idx, state); | - |
91 | return 1; | - |
92 | | - |
93 | err: | - |
94 | free(state); | - |
95 | return 0; | - |
96 | } | - |
97 | | - |
98 | static void | - |
99 | zlib_stateful_finish(COMP_CTX *ctx) | - |
100 | { | - |
101 | struct zlib_state *state = | - |
102 | (struct zlib_state *)CRYPTO_get_ex_data(&ctx->ex_data, | - |
103 | zlib_stateful_ex_idx); | - |
104 | | - |
105 | inflateEnd(&state->istream); | - |
106 | deflateEnd(&state->ostream); | - |
107 | free(state); | - |
108 | CRYPTO_free_ex_data(CRYPTO_EX_INDEX_COMP, ctx, &ctx->ex_data); | - |
109 | } | - |
110 | | - |
111 | static int | - |
112 | zlib_stateful_compress_block(COMP_CTX *ctx, unsigned char *out, | - |
113 | unsigned int olen, unsigned char *in, unsigned int ilen) | - |
114 | { | - |
115 | int err = Z_OK; | - |
116 | struct zlib_state *state = | - |
117 | (struct zlib_state *)CRYPTO_get_ex_data(&ctx->ex_data, | - |
118 | zlib_stateful_ex_idx); | - |
119 | | - |
120 | if (state == NULL) | - |
121 | return -1; | - |
122 | | - |
123 | state->ostream.next_in = in; | - |
124 | state->ostream.avail_in = ilen; | - |
125 | state->ostream.next_out = out; | - |
126 | state->ostream.avail_out = olen; | - |
127 | if (ilen > 0) | - |
128 | err = deflate(&state->ostream, Z_SYNC_FLUSH); | - |
129 | if (err != Z_OK) | - |
130 | return -1; | - |
131 | | - |
132 | #ifdef DEBUG_ZLIB | - |
133 | fprintf(stderr, "compress(%4d)->%4d %s\n", | - |
134 | ilen, olen - state->ostream.avail_out, | - |
135 | (ilen != olen - state->ostream.avail_out)?"zlib":"clear"); | - |
136 | #endif | - |
137 | | - |
138 | return olen - state->ostream.avail_out; | - |
139 | } | - |
140 | | - |
141 | static int | - |
142 | zlib_stateful_expand_block(COMP_CTX *ctx, unsigned char *out, | - |
143 | unsigned int olen, unsigned char *in, unsigned int ilen) | - |
144 | { | - |
145 | int err = Z_OK; | - |
146 | | - |
147 | struct zlib_state *state = | - |
148 | (struct zlib_state *)CRYPTO_get_ex_data(&ctx->ex_data, | - |
149 | zlib_stateful_ex_idx); | - |
150 | | - |
151 | if (state == NULL) | - |
152 | return 0; | - |
153 | | - |
154 | state->istream.next_in = in; | - |
155 | state->istream.avail_in = ilen; | - |
156 | state->istream.next_out = out; | - |
157 | state->istream.avail_out = olen; | - |
158 | if (ilen > 0) | - |
159 | err = inflate(&state->istream, Z_SYNC_FLUSH); | - |
160 | if (err != Z_OK) | - |
161 | return -1; | - |
162 | | - |
163 | #ifdef DEBUG_ZLIB | - |
164 | fprintf(stderr, "expand(%4d)->%4d %s\n", | - |
165 | ilen, olen - state->istream.avail_out, | - |
166 | (ilen != olen - state->istream.avail_out)?"zlib":"clear"); | - |
167 | #endif | - |
168 | | - |
169 | return olen - state->istream.avail_out; | - |
170 | } | - |
171 | | - |
172 | #endif | - |
173 | | - |
174 | COMP_METHOD * | - |
175 | COMP_zlib(void) | - |
176 | { | - |
177 | COMP_METHOD *meth = &zlib_method_nozlib; | - |
178 | | - |
179 | #ifdef ZLIB | - |
180 | { | - |
181 | | - |
182 | | - |
183 | | - |
184 | if (zlib_stateful_ex_idx == -1) { | - |
185 | CRYPTO_w_lock(CRYPTO_LOCK_COMP); | - |
186 | if (zlib_stateful_ex_idx == -1) | - |
187 | zlib_stateful_ex_idx = | - |
188 | CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_COMP, | - |
189 | 0, NULL, NULL, NULL, NULL); | - |
190 | CRYPTO_w_unlock(CRYPTO_LOCK_COMP); | - |
191 | if (zlib_stateful_ex_idx == -1) | - |
192 | goto err; | - |
193 | } | - |
194 | if (!OPENSSL_init_crypto(0, NULL)) | - |
195 | goto err; | - |
196 | | - |
197 | meth = &zlib_stateful_method; | - |
198 | } | - |
199 | | - |
200 | err: | - |
201 | #endif | - |
202 | | - |
203 | return (meth); never executed: return (meth); | 0 |
204 | } | - |
205 | | - |
206 | void | - |
207 | COMP_zlib_cleanup(void) | - |
208 | { | - |
209 | } | - |
210 | | - |
211 | #ifdef ZLIB | - |
212 | | - |
213 | | - |
214 | | - |
215 | typedef struct { | - |
216 | unsigned char *ibuf; | - |
217 | int ibufsize; | - |
218 | z_stream zin; | - |
219 | unsigned char *obuf; | - |
220 | int obufsize; | - |
221 | unsigned char *optr; | - |
222 | int ocount; | - |
223 | int odone; | - |
224 | int comp_level; | - |
225 | z_stream zout; | - |
226 | } BIO_ZLIB_CTX; | - |
227 | | - |
228 | #define ZLIB_DEFAULT_BUFSIZE 1024 | - |
229 | | - |
230 | static int bio_zlib_new(BIO *bi); | - |
231 | static int bio_zlib_free(BIO *bi); | - |
232 | static int bio_zlib_read(BIO *b, char *out, int outl); | - |
233 | static int bio_zlib_write(BIO *b, const char *in, int inl); | - |
234 | static long bio_zlib_ctrl(BIO *b, int cmd, long num, void *ptr); | - |
235 | static long bio_zlib_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp); | - |
236 | | - |
237 | static BIO_METHOD bio_meth_zlib = { | - |
238 | .type = BIO_TYPE_COMP, | - |
239 | .name = "zlib", | - |
240 | .bwrite = bio_zlib_write, | - |
241 | .bread = bio_zlib_read, | - |
242 | .ctrl = bio_zlib_ctrl, | - |
243 | .create = bio_zlib_new, | - |
244 | .destroy = bio_zlib_free, | - |
245 | .callback_ctrl = bio_zlib_callback_ctrl | - |
246 | }; | - |
247 | | - |
248 | BIO_METHOD * | - |
249 | BIO_f_zlib(void) | - |
250 | { | - |
251 | return &bio_meth_zlib; | - |
252 | } | - |
253 | | - |
254 | | - |
255 | static int | - |
256 | bio_zlib_new(BIO *bi) | - |
257 | { | - |
258 | BIO_ZLIB_CTX *ctx; | - |
259 | | - |
260 | ctx = malloc(sizeof(BIO_ZLIB_CTX)); | - |
261 | if (!ctx) { | - |
262 | COMPerror(ERR_R_MALLOC_FAILURE); | - |
263 | return 0; | - |
264 | } | - |
265 | ctx->ibuf = NULL; | - |
266 | ctx->obuf = NULL; | - |
267 | ctx->ibufsize = ZLIB_DEFAULT_BUFSIZE; | - |
268 | ctx->obufsize = ZLIB_DEFAULT_BUFSIZE; | - |
269 | ctx->zin.zalloc = Z_NULL; | - |
270 | ctx->zin.zfree = Z_NULL; | - |
271 | ctx->zin.next_in = NULL; | - |
272 | ctx->zin.avail_in = 0; | - |
273 | ctx->zin.next_out = NULL; | - |
274 | ctx->zin.avail_out = 0; | - |
275 | ctx->zout.zalloc = Z_NULL; | - |
276 | ctx->zout.zfree = Z_NULL; | - |
277 | ctx->zout.next_in = NULL; | - |
278 | ctx->zout.avail_in = 0; | - |
279 | ctx->zout.next_out = NULL; | - |
280 | ctx->zout.avail_out = 0; | - |
281 | ctx->odone = 0; | - |
282 | ctx->comp_level = Z_DEFAULT_COMPRESSION; | - |
283 | bi->init = 1; | - |
284 | bi->ptr = (char *)ctx; | - |
285 | bi->flags = 0; | - |
286 | return 1; | - |
287 | } | - |
288 | | - |
289 | static int | - |
290 | bio_zlib_free(BIO *bi) | - |
291 | { | - |
292 | BIO_ZLIB_CTX *ctx; | - |
293 | | - |
294 | if (!bi) | - |
295 | return 0; | - |
296 | ctx = (BIO_ZLIB_CTX *)bi->ptr; | - |
297 | if (ctx->ibuf) { | - |
298 | | - |
299 | inflateEnd(&ctx->zin); | - |
300 | free(ctx->ibuf); | - |
301 | } | - |
302 | if (ctx->obuf) { | - |
303 | | - |
304 | deflateEnd(&ctx->zout); | - |
305 | free(ctx->obuf); | - |
306 | } | - |
307 | free(ctx); | - |
308 | bi->ptr = NULL; | - |
309 | bi->init = 0; | - |
310 | bi->flags = 0; | - |
311 | return 1; | - |
312 | } | - |
313 | | - |
314 | static int | - |
315 | bio_zlib_read(BIO *b, char *out, int outl) | - |
316 | { | - |
317 | BIO_ZLIB_CTX *ctx; | - |
318 | int ret; | - |
319 | z_stream *zin; | - |
320 | | - |
321 | if (!out || !outl) | - |
322 | return 0; | - |
323 | ctx = (BIO_ZLIB_CTX *)b->ptr; | - |
324 | zin = &ctx->zin; | - |
325 | BIO_clear_retry_flags(b); | - |
326 | if (!ctx->ibuf) { | - |
327 | ctx->ibuf = malloc(ctx->ibufsize); | - |
328 | if (!ctx->ibuf) { | - |
329 | COMPerror(ERR_R_MALLOC_FAILURE); | - |
330 | return 0; | - |
331 | } | - |
332 | inflateInit(zin); | - |
333 | zin->next_in = ctx->ibuf; | - |
334 | zin->avail_in = 0; | - |
335 | } | - |
336 | | - |
337 | | - |
338 | zin->next_out = (unsigned char *)out; | - |
339 | zin->avail_out = (unsigned int)outl; | - |
340 | for (;;) { | - |
341 | | - |
342 | while (zin->avail_in) { | - |
343 | ret = inflate(zin, 0); | - |
344 | if ((ret != Z_OK) && (ret != Z_STREAM_END)) { | - |
345 | COMPerror(COMP_R_ZLIB_INFLATE_ERROR); | - |
346 | ERR_asprintf_error_data("zlib error:%s", | - |
347 | zError(ret)); | - |
348 | return 0; | - |
349 | } | - |
350 | | - |
351 | if ((ret == Z_STREAM_END) || !zin->avail_out) | - |
352 | return outl - zin->avail_out; | - |
353 | } | - |
354 | | - |
355 | | - |
356 | | - |
357 | | - |
358 | ret = BIO_read(b->next_bio, ctx->ibuf, ctx->ibufsize); | - |
359 | if (ret <= 0) { | - |
360 | | - |
361 | int tot = outl - zin->avail_out; | - |
362 | BIO_copy_next_retry(b); | - |
363 | if (ret < 0) | - |
364 | return (tot > 0) ? tot : ret; | - |
365 | return tot; | - |
366 | } | - |
367 | zin->avail_in = ret; | - |
368 | zin->next_in = ctx->ibuf; | - |
369 | } | - |
370 | } | - |
371 | | - |
372 | static int | - |
373 | bio_zlib_write(BIO *b, const char *in, int inl) | - |
374 | { | - |
375 | BIO_ZLIB_CTX *ctx; | - |
376 | int ret; | - |
377 | z_stream *zout; | - |
378 | | - |
379 | if (!in || !inl) | - |
380 | return 0; | - |
381 | ctx = (BIO_ZLIB_CTX *)b->ptr; | - |
382 | if (ctx->odone) | - |
383 | return 0; | - |
384 | zout = &ctx->zout; | - |
385 | BIO_clear_retry_flags(b); | - |
386 | if (!ctx->obuf) { | - |
387 | ctx->obuf = malloc(ctx->obufsize); | - |
388 | | - |
389 | if (!ctx->obuf) { | - |
390 | COMPerror(ERR_R_MALLOC_FAILURE); | - |
391 | return 0; | - |
392 | } | - |
393 | ctx->optr = ctx->obuf; | - |
394 | ctx->ocount = 0; | - |
395 | deflateInit(zout, ctx->comp_level); | - |
396 | zout->next_out = ctx->obuf; | - |
397 | zout->avail_out = ctx->obufsize; | - |
398 | } | - |
399 | | - |
400 | zout->next_in = (void *)in; | - |
401 | zout->avail_in = inl; | - |
402 | for (;;) { | - |
403 | | - |
404 | while (ctx->ocount) { | - |
405 | ret = BIO_write(b->next_bio, ctx->optr, ctx->ocount); | - |
406 | if (ret <= 0) { | - |
407 | | - |
408 | int tot = inl - zout->avail_in; | - |
409 | BIO_copy_next_retry(b); | - |
410 | if (ret < 0) | - |
411 | return (tot > 0) ? tot : ret; | - |
412 | return tot; | - |
413 | } | - |
414 | ctx->optr += ret; | - |
415 | ctx->ocount -= ret; | - |
416 | } | - |
417 | | - |
418 | | - |
419 | if (!zout->avail_in) | - |
420 | return inl; | - |
421 | | - |
422 | | - |
423 | | - |
424 | | - |
425 | ctx->optr = ctx->obuf; | - |
426 | zout->next_out = ctx->obuf; | - |
427 | zout->avail_out = ctx->obufsize; | - |
428 | | - |
429 | ret = deflate(zout, 0); | - |
430 | if (ret != Z_OK) { | - |
431 | COMPerror(COMP_R_ZLIB_DEFLATE_ERROR); | - |
432 | ERR_asprintf_error_data("zlib error:%s", zError(ret)); | - |
433 | return 0; | - |
434 | } | - |
435 | ctx->ocount = ctx->obufsize - zout->avail_out; | - |
436 | } | - |
437 | } | - |
438 | | - |
439 | static int | - |
440 | bio_zlib_flush(BIO *b) | - |
441 | { | - |
442 | BIO_ZLIB_CTX *ctx; | - |
443 | int ret; | - |
444 | z_stream *zout; | - |
445 | | - |
446 | ctx = (BIO_ZLIB_CTX *)b->ptr; | - |
447 | | - |
448 | if (!ctx->obuf || (ctx->odone && !ctx->ocount)) | - |
449 | return 1; | - |
450 | zout = &ctx->zout; | - |
451 | BIO_clear_retry_flags(b); | - |
452 | | - |
453 | zout->next_in = NULL; | - |
454 | zout->avail_in = 0; | - |
455 | for (;;) { | - |
456 | | - |
457 | while (ctx->ocount) { | - |
458 | ret = BIO_write(b->next_bio, ctx->optr, ctx->ocount); | - |
459 | if (ret <= 0) { | - |
460 | BIO_copy_next_retry(b); | - |
461 | return ret; | - |
462 | } | - |
463 | ctx->optr += ret; | - |
464 | ctx->ocount -= ret; | - |
465 | } | - |
466 | if (ctx->odone) | - |
467 | return 1; | - |
468 | | - |
469 | | - |
470 | | - |
471 | | - |
472 | ctx->optr = ctx->obuf; | - |
473 | zout->next_out = ctx->obuf; | - |
474 | zout->avail_out = ctx->obufsize; | - |
475 | | - |
476 | ret = deflate(zout, Z_FINISH); | - |
477 | if (ret == Z_STREAM_END) | - |
478 | ctx->odone = 1; | - |
479 | else if (ret != Z_OK) { | - |
480 | COMPerror(COMP_R_ZLIB_DEFLATE_ERROR); | - |
481 | ERR_asprintf_error_data("zlib error:%s", zError(ret)); | - |
482 | return 0; | - |
483 | } | - |
484 | ctx->ocount = ctx->obufsize - zout->avail_out; | - |
485 | } | - |
486 | } | - |
487 | | - |
488 | static long | - |
489 | bio_zlib_ctrl(BIO *b, int cmd, long num, void *ptr) | - |
490 | { | - |
491 | BIO_ZLIB_CTX *ctx; | - |
492 | int ret, *ip; | - |
493 | int ibs, obs; | - |
494 | if (!b->next_bio) | - |
495 | return 0; | - |
496 | ctx = (BIO_ZLIB_CTX *)b->ptr; | - |
497 | switch (cmd) { | - |
498 | | - |
499 | case BIO_CTRL_RESET: | - |
500 | ctx->ocount = 0; | - |
501 | ctx->odone = 0; | - |
502 | ret = 1; | - |
503 | break; | - |
504 | | - |
505 | case BIO_CTRL_FLUSH: | - |
506 | ret = bio_zlib_flush(b); | - |
507 | if (ret > 0) | - |
508 | ret = BIO_flush(b->next_bio); | - |
509 | break; | - |
510 | | - |
511 | case BIO_C_SET_BUFF_SIZE: | - |
512 | ibs = -1; | - |
513 | obs = -1; | - |
514 | if (ptr != NULL) { | - |
515 | ip = ptr; | - |
516 | if (*ip == 0) | - |
517 | ibs = (int) num; | - |
518 | else | - |
519 | obs = (int) num; | - |
520 | } else { | - |
521 | ibs = (int)num; | - |
522 | obs = ibs; | - |
523 | } | - |
524 | | - |
525 | if (ibs != -1) { | - |
526 | free(ctx->ibuf); | - |
527 | ctx->ibuf = NULL; | - |
528 | ctx->ibufsize = ibs; | - |
529 | } | - |
530 | | - |
531 | if (obs != -1) { | - |
532 | free(ctx->obuf); | - |
533 | ctx->obuf = NULL; | - |
534 | ctx->obufsize = obs; | - |
535 | } | - |
536 | ret = 1; | - |
537 | break; | - |
538 | | - |
539 | case BIO_C_DO_STATE_MACHINE: | - |
540 | BIO_clear_retry_flags(b); | - |
541 | ret = BIO_ctrl(b->next_bio, cmd, num, ptr); | - |
542 | BIO_copy_next_retry(b); | - |
543 | break; | - |
544 | | - |
545 | default: | - |
546 | ret = BIO_ctrl(b->next_bio, cmd, num, ptr); | - |
547 | break; | - |
548 | | - |
549 | } | - |
550 | | - |
551 | return ret; | - |
552 | } | - |
553 | | - |
554 | | - |
555 | static long | - |
556 | bio_zlib_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp) | - |
557 | { | - |
558 | if (!b->next_bio) | - |
559 | return 0; | - |
560 | return BIO_callback_ctrl(b->next_bio, cmd, fp); | - |
561 | } | - |
562 | | - |
563 | #endif | - |
| | |