c_zlib.c revision 291721
1#include <stdio.h> 2#include <stdlib.h> 3#include <string.h> 4#include <openssl/objects.h> 5#include <openssl/comp.h> 6#include <openssl/err.h> 7 8COMP_METHOD *COMP_zlib(void); 9 10static COMP_METHOD zlib_method_nozlib = { 11 NID_undef, 12 "(undef)", 13 NULL, 14 NULL, 15 NULL, 16 NULL, 17 NULL, 18 NULL, 19}; 20 21#ifndef ZLIB 22# undef ZLIB_SHARED 23#else 24 25# include <zlib.h> 26 27static int zlib_stateful_init(COMP_CTX *ctx); 28static void zlib_stateful_finish(COMP_CTX *ctx); 29static int zlib_stateful_compress_block(COMP_CTX *ctx, unsigned char *out, 30 unsigned int olen, unsigned char *in, 31 unsigned int ilen); 32static int zlib_stateful_expand_block(COMP_CTX *ctx, unsigned char *out, 33 unsigned int olen, unsigned char *in, 34 unsigned int ilen); 35 36/* memory allocations functions for zlib intialization */ 37static void *zlib_zalloc(void *opaque, unsigned int no, unsigned int size) 38{ 39 void *p; 40 41 p = OPENSSL_malloc(no * size); 42 if (p) 43 memset(p, 0, no * size); 44 return p; 45} 46 47static void zlib_zfree(void *opaque, void *address) 48{ 49 OPENSSL_free(address); 50} 51 52# if 0 53static int zlib_compress_block(COMP_CTX *ctx, unsigned char *out, 54 unsigned int olen, unsigned char *in, 55 unsigned int ilen); 56static int zlib_expand_block(COMP_CTX *ctx, unsigned char *out, 57 unsigned int olen, unsigned char *in, 58 unsigned int ilen); 59 60static int zz_uncompress(Bytef *dest, uLongf * destLen, const Bytef *source, 61 uLong sourceLen); 62 63static COMP_METHOD zlib_stateless_method = { 64 NID_zlib_compression, 65 LN_zlib_compression, 66 NULL, 67 NULL, 68 zlib_compress_block, 69 zlib_expand_block, 70 NULL, 71 NULL, 72}; 73# endif 74 75static COMP_METHOD zlib_stateful_method = { 76 NID_zlib_compression, 77 LN_zlib_compression, 78 zlib_stateful_init, 79 zlib_stateful_finish, 80 zlib_stateful_compress_block, 81 zlib_stateful_expand_block, 82 NULL, 83 NULL, 84}; 85 86/* 87 * When OpenSSL is built on Windows, we do not want to require that 88 * the ZLIB.DLL be available in order for the OpenSSL DLLs to 89 * work. Therefore, all ZLIB routines are loaded at run time 90 * and we do not link to a .LIB file when ZLIB_SHARED is set. 91 */ 92# if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32) 93# include <windows.h> 94# endif /* !(OPENSSL_SYS_WINDOWS || 95 * OPENSSL_SYS_WIN32) */ 96 97# ifdef ZLIB_SHARED 98# include <openssl/dso.h> 99 100/* Function pointers */ 101typedef int (*compress_ft) (Bytef *dest, uLongf * destLen, 102 const Bytef *source, uLong sourceLen); 103typedef int (*inflateEnd_ft) (z_streamp strm); 104typedef int (*inflate_ft) (z_streamp strm, int flush); 105typedef int (*inflateInit__ft) (z_streamp strm, 106 const char *version, int stream_size); 107typedef int (*deflateEnd_ft) (z_streamp strm); 108typedef int (*deflate_ft) (z_streamp strm, int flush); 109typedef int (*deflateInit__ft) (z_streamp strm, int level, 110 const char *version, int stream_size); 111typedef const char *(*zError__ft) (int err); 112static compress_ft p_compress = NULL; 113static inflateEnd_ft p_inflateEnd = NULL; 114static inflate_ft p_inflate = NULL; 115static inflateInit__ft p_inflateInit_ = NULL; 116static deflateEnd_ft p_deflateEnd = NULL; 117static deflate_ft p_deflate = NULL; 118static deflateInit__ft p_deflateInit_ = NULL; 119static zError__ft p_zError = NULL; 120 121static int zlib_loaded = 0; /* only attempt to init func pts once */ 122static DSO *zlib_dso = NULL; 123 124# define compress p_compress 125# define inflateEnd p_inflateEnd 126# define inflate p_inflate 127# define inflateInit_ p_inflateInit_ 128# define deflateEnd p_deflateEnd 129# define deflate p_deflate 130# define deflateInit_ p_deflateInit_ 131# define zError p_zError 132# endif /* ZLIB_SHARED */ 133 134struct zlib_state { 135 z_stream istream; 136 z_stream ostream; 137}; 138 139static int zlib_stateful_ex_idx = -1; 140 141static int zlib_stateful_init(COMP_CTX *ctx) 142{ 143 int err; 144 struct zlib_state *state = 145 (struct zlib_state *)OPENSSL_malloc(sizeof(struct zlib_state)); 146 147 if (state == NULL) 148 goto err; 149 150 state->istream.zalloc = zlib_zalloc; 151 state->istream.zfree = zlib_zfree; 152 state->istream.opaque = Z_NULL; 153 state->istream.next_in = Z_NULL; 154 state->istream.next_out = Z_NULL; 155 state->istream.avail_in = 0; 156 state->istream.avail_out = 0; 157 err = inflateInit_(&state->istream, ZLIB_VERSION, sizeof(z_stream)); 158 if (err != Z_OK) 159 goto err; 160 161 state->ostream.zalloc = zlib_zalloc; 162 state->ostream.zfree = zlib_zfree; 163 state->ostream.opaque = Z_NULL; 164 state->ostream.next_in = Z_NULL; 165 state->ostream.next_out = Z_NULL; 166 state->ostream.avail_in = 0; 167 state->ostream.avail_out = 0; 168 err = deflateInit_(&state->ostream, Z_DEFAULT_COMPRESSION, 169 ZLIB_VERSION, sizeof(z_stream)); 170 if (err != Z_OK) 171 goto err; 172 173 CRYPTO_new_ex_data(CRYPTO_EX_INDEX_COMP, ctx, &ctx->ex_data); 174 CRYPTO_set_ex_data(&ctx->ex_data, zlib_stateful_ex_idx, state); 175 return 1; 176 err: 177 if (state) 178 OPENSSL_free(state); 179 return 0; 180} 181 182static void zlib_stateful_finish(COMP_CTX *ctx) 183{ 184 struct zlib_state *state = 185 (struct zlib_state *)CRYPTO_get_ex_data(&ctx->ex_data, 186 zlib_stateful_ex_idx); 187 inflateEnd(&state->istream); 188 deflateEnd(&state->ostream); 189 OPENSSL_free(state); 190 CRYPTO_free_ex_data(CRYPTO_EX_INDEX_COMP, ctx, &ctx->ex_data); 191} 192 193static int zlib_stateful_compress_block(COMP_CTX *ctx, unsigned char *out, 194 unsigned int olen, unsigned char *in, 195 unsigned int ilen) 196{ 197 int err = Z_OK; 198 struct zlib_state *state = 199 (struct zlib_state *)CRYPTO_get_ex_data(&ctx->ex_data, 200 zlib_stateful_ex_idx); 201 202 if (state == NULL) 203 return -1; 204 205 state->ostream.next_in = in; 206 state->ostream.avail_in = ilen; 207 state->ostream.next_out = out; 208 state->ostream.avail_out = olen; 209 if (ilen > 0) 210 err = deflate(&state->ostream, Z_SYNC_FLUSH); 211 if (err != Z_OK) 212 return -1; 213# ifdef DEBUG_ZLIB 214 fprintf(stderr, "compress(%4d)->%4d %s\n", 215 ilen, olen - state->ostream.avail_out, 216 (ilen != olen - state->ostream.avail_out) ? "zlib" : "clear"); 217# endif 218 return olen - state->ostream.avail_out; 219} 220 221static int zlib_stateful_expand_block(COMP_CTX *ctx, unsigned char *out, 222 unsigned int olen, unsigned char *in, 223 unsigned int ilen) 224{ 225 int err = Z_OK; 226 227 struct zlib_state *state = 228 (struct zlib_state *)CRYPTO_get_ex_data(&ctx->ex_data, 229 zlib_stateful_ex_idx); 230 231 if (state == NULL) 232 return 0; 233 234 state->istream.next_in = in; 235 state->istream.avail_in = ilen; 236 state->istream.next_out = out; 237 state->istream.avail_out = olen; 238 if (ilen > 0) 239 err = inflate(&state->istream, Z_SYNC_FLUSH); 240 if (err != Z_OK) 241 return -1; 242# ifdef DEBUG_ZLIB 243 fprintf(stderr, "expand(%4d)->%4d %s\n", 244 ilen, olen - state->istream.avail_out, 245 (ilen != olen - state->istream.avail_out) ? "zlib" : "clear"); 246# endif 247 return olen - state->istream.avail_out; 248} 249 250# if 0 251static int zlib_compress_block(COMP_CTX *ctx, unsigned char *out, 252 unsigned int olen, unsigned char *in, 253 unsigned int ilen) 254{ 255 unsigned long l; 256 int i; 257 int clear = 1; 258 259 if (ilen > 128) { 260 out[0] = 1; 261 l = olen - 1; 262 i = compress(&(out[1]), &l, in, (unsigned long)ilen); 263 if (i != Z_OK) 264 return (-1); 265 if (ilen > l) { 266 clear = 0; 267 l++; 268 } 269 } 270 if (clear) { 271 out[0] = 0; 272 memcpy(&(out[1]), in, ilen); 273 l = ilen + 1; 274 } 275# ifdef DEBUG_ZLIB 276 fprintf(stderr, "compress(%4d)->%4d %s\n", 277 ilen, (int)l, (clear) ? "clear" : "zlib"); 278# endif 279 return ((int)l); 280} 281 282static int zlib_expand_block(COMP_CTX *ctx, unsigned char *out, 283 unsigned int olen, unsigned char *in, 284 unsigned int ilen) 285{ 286 unsigned long l; 287 int i; 288 289 if (in[0]) { 290 l = olen; 291 i = zz_uncompress(out, &l, &(in[1]), (unsigned long)ilen - 1); 292 if (i != Z_OK) 293 return (-1); 294 } else { 295 memcpy(out, &(in[1]), ilen - 1); 296 l = ilen - 1; 297 } 298# ifdef DEBUG_ZLIB 299 fprintf(stderr, "expand (%4d)->%4d %s\n", 300 ilen, (int)l, in[0] ? "zlib" : "clear"); 301# endif 302 return ((int)l); 303} 304 305static int zz_uncompress(Bytef *dest, uLongf * destLen, const Bytef *source, 306 uLong sourceLen) 307{ 308 z_stream stream; 309 int err; 310 311 stream.next_in = (Bytef *)source; 312 stream.avail_in = (uInt) sourceLen; 313 /* Check for source > 64K on 16-bit machine: */ 314 if ((uLong) stream.avail_in != sourceLen) 315 return Z_BUF_ERROR; 316 317 stream.next_out = dest; 318 stream.avail_out = (uInt) * destLen; 319 if ((uLong) stream.avail_out != *destLen) 320 return Z_BUF_ERROR; 321 322 stream.zalloc = (alloc_func) 0; 323 stream.zfree = (free_func) 0; 324 325 err = inflateInit_(&stream, ZLIB_VERSION, sizeof(z_stream)); 326 if (err != Z_OK) 327 return err; 328 329 err = inflate(&stream, Z_FINISH); 330 if (err != Z_STREAM_END) { 331 inflateEnd(&stream); 332 return err; 333 } 334 *destLen = stream.total_out; 335 336 err = inflateEnd(&stream); 337 return err; 338} 339# endif 340 341#endif 342 343COMP_METHOD *COMP_zlib(void) 344{ 345 COMP_METHOD *meth = &zlib_method_nozlib; 346 347#ifdef ZLIB_SHARED 348 if (!zlib_loaded) { 349# if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32) 350 zlib_dso = DSO_load(NULL, "ZLIB1", NULL, 0); 351# else 352 zlib_dso = DSO_load(NULL, "z", NULL, 0); 353# endif 354 if (zlib_dso != NULL) { 355 p_compress = (compress_ft) DSO_bind_func(zlib_dso, "compress"); 356 p_inflateEnd 357 = (inflateEnd_ft) DSO_bind_func(zlib_dso, "inflateEnd"); 358 p_inflate = (inflate_ft) DSO_bind_func(zlib_dso, "inflate"); 359 p_inflateInit_ 360 = (inflateInit__ft) DSO_bind_func(zlib_dso, "inflateInit_"); 361 p_deflateEnd 362 = (deflateEnd_ft) DSO_bind_func(zlib_dso, "deflateEnd"); 363 p_deflate = (deflate_ft) DSO_bind_func(zlib_dso, "deflate"); 364 p_deflateInit_ 365 = (deflateInit__ft) DSO_bind_func(zlib_dso, "deflateInit_"); 366 p_zError = (zError__ft) DSO_bind_func(zlib_dso, "zError"); 367 368 if (p_compress && p_inflateEnd && p_inflate 369 && p_inflateInit_ && p_deflateEnd 370 && p_deflate && p_deflateInit_ && p_zError) 371 zlib_loaded++; 372 } 373 } 374#endif 375#ifdef ZLIB_SHARED 376 if (zlib_loaded) 377#endif 378#if defined(ZLIB) || defined(ZLIB_SHARED) 379 { 380 /* 381 * init zlib_stateful_ex_idx here so that in a multi-process 382 * application it's enough to intialize openssl before forking (idx 383 * will be inherited in all the children) 384 */ 385 if (zlib_stateful_ex_idx == -1) { 386 CRYPTO_w_lock(CRYPTO_LOCK_COMP); 387 if (zlib_stateful_ex_idx == -1) 388 zlib_stateful_ex_idx = 389 CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_COMP, 390 0, NULL, NULL, NULL, NULL); 391 CRYPTO_w_unlock(CRYPTO_LOCK_COMP); 392 if (zlib_stateful_ex_idx == -1) 393 goto err; 394 } 395 396 meth = &zlib_stateful_method; 397 } 398 err: 399#endif 400 401 return (meth); 402} 403 404void COMP_zlib_cleanup(void) 405{ 406#ifdef ZLIB_SHARED 407 if (zlib_dso != NULL) 408 DSO_free(zlib_dso); 409 zlib_dso = NULL; 410#endif 411} 412 413#ifdef ZLIB 414 415/* Zlib based compression/decompression filter BIO */ 416 417typedef struct { 418 unsigned char *ibuf; /* Input buffer */ 419 int ibufsize; /* Buffer size */ 420 z_stream zin; /* Input decompress context */ 421 unsigned char *obuf; /* Output buffer */ 422 int obufsize; /* Output buffer size */ 423 unsigned char *optr; /* Position in output buffer */ 424 int ocount; /* Amount of data in output buffer */ 425 int odone; /* deflate EOF */ 426 int comp_level; /* Compression level to use */ 427 z_stream zout; /* Output compression context */ 428} BIO_ZLIB_CTX; 429 430# define ZLIB_DEFAULT_BUFSIZE 1024 431 432static int bio_zlib_new(BIO *bi); 433static int bio_zlib_free(BIO *bi); 434static int bio_zlib_read(BIO *b, char *out, int outl); 435static int bio_zlib_write(BIO *b, const char *in, int inl); 436static long bio_zlib_ctrl(BIO *b, int cmd, long num, void *ptr); 437static long bio_zlib_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp); 438 439static BIO_METHOD bio_meth_zlib = { 440 BIO_TYPE_COMP, 441 "zlib", 442 bio_zlib_write, 443 bio_zlib_read, 444 NULL, 445 NULL, 446 bio_zlib_ctrl, 447 bio_zlib_new, 448 bio_zlib_free, 449 bio_zlib_callback_ctrl 450}; 451 452BIO_METHOD *BIO_f_zlib(void) 453{ 454 return &bio_meth_zlib; 455} 456 457static int bio_zlib_new(BIO *bi) 458{ 459 BIO_ZLIB_CTX *ctx; 460# ifdef ZLIB_SHARED 461 (void)COMP_zlib(); 462 if (!zlib_loaded) { 463 COMPerr(COMP_F_BIO_ZLIB_NEW, COMP_R_ZLIB_NOT_SUPPORTED); 464 return 0; 465 } 466# endif 467 ctx = OPENSSL_malloc(sizeof(BIO_ZLIB_CTX)); 468 if (!ctx) { 469 COMPerr(COMP_F_BIO_ZLIB_NEW, ERR_R_MALLOC_FAILURE); 470 return 0; 471 } 472 ctx->ibuf = NULL; 473 ctx->obuf = NULL; 474 ctx->ibufsize = ZLIB_DEFAULT_BUFSIZE; 475 ctx->obufsize = ZLIB_DEFAULT_BUFSIZE; 476 ctx->zin.zalloc = Z_NULL; 477 ctx->zin.zfree = Z_NULL; 478 ctx->zin.next_in = NULL; 479 ctx->zin.avail_in = 0; 480 ctx->zin.next_out = NULL; 481 ctx->zin.avail_out = 0; 482 ctx->zout.zalloc = Z_NULL; 483 ctx->zout.zfree = Z_NULL; 484 ctx->zout.next_in = NULL; 485 ctx->zout.avail_in = 0; 486 ctx->zout.next_out = NULL; 487 ctx->zout.avail_out = 0; 488 ctx->odone = 0; 489 ctx->comp_level = Z_DEFAULT_COMPRESSION; 490 bi->init = 1; 491 bi->ptr = (char *)ctx; 492 bi->flags = 0; 493 return 1; 494} 495 496static int bio_zlib_free(BIO *bi) 497{ 498 BIO_ZLIB_CTX *ctx; 499 if (!bi) 500 return 0; 501 ctx = (BIO_ZLIB_CTX *) bi->ptr; 502 if (ctx->ibuf) { 503 /* Destroy decompress context */ 504 inflateEnd(&ctx->zin); 505 OPENSSL_free(ctx->ibuf); 506 } 507 if (ctx->obuf) { 508 /* Destroy compress context */ 509 deflateEnd(&ctx->zout); 510 OPENSSL_free(ctx->obuf); 511 } 512 OPENSSL_free(ctx); 513 bi->ptr = NULL; 514 bi->init = 0; 515 bi->flags = 0; 516 return 1; 517} 518 519static int bio_zlib_read(BIO *b, char *out, int outl) 520{ 521 BIO_ZLIB_CTX *ctx; 522 int ret; 523 z_stream *zin; 524 if (!out || !outl) 525 return 0; 526 ctx = (BIO_ZLIB_CTX *) b->ptr; 527 zin = &ctx->zin; 528 BIO_clear_retry_flags(b); 529 if (!ctx->ibuf) { 530 ctx->ibuf = OPENSSL_malloc(ctx->ibufsize); 531 if (!ctx->ibuf) { 532 COMPerr(COMP_F_BIO_ZLIB_READ, ERR_R_MALLOC_FAILURE); 533 return 0; 534 } 535 inflateInit(zin); 536 zin->next_in = ctx->ibuf; 537 zin->avail_in = 0; 538 } 539 540 /* Copy output data directly to supplied buffer */ 541 zin->next_out = (unsigned char *)out; 542 zin->avail_out = (unsigned int)outl; 543 for (;;) { 544 /* Decompress while data available */ 545 while (zin->avail_in) { 546 ret = inflate(zin, 0); 547 if ((ret != Z_OK) && (ret != Z_STREAM_END)) { 548 COMPerr(COMP_F_BIO_ZLIB_READ, COMP_R_ZLIB_INFLATE_ERROR); 549 ERR_add_error_data(2, "zlib error:", zError(ret)); 550 return 0; 551 } 552 /* If EOF or we've read everything then return */ 553 if ((ret == Z_STREAM_END) || !zin->avail_out) 554 return outl - zin->avail_out; 555 } 556 557 /* 558 * No data in input buffer try to read some in, if an error then 559 * return the total data read. 560 */ 561 ret = BIO_read(b->next_bio, ctx->ibuf, ctx->ibufsize); 562 if (ret <= 0) { 563 /* Total data read */ 564 int tot = outl - zin->avail_out; 565 BIO_copy_next_retry(b); 566 if (ret < 0) 567 return (tot > 0) ? tot : ret; 568 return tot; 569 } 570 zin->avail_in = ret; 571 zin->next_in = ctx->ibuf; 572 } 573} 574 575static int bio_zlib_write(BIO *b, const char *in, int inl) 576{ 577 BIO_ZLIB_CTX *ctx; 578 int ret; 579 z_stream *zout; 580 if (!in || !inl) 581 return 0; 582 ctx = (BIO_ZLIB_CTX *) b->ptr; 583 if (ctx->odone) 584 return 0; 585 zout = &ctx->zout; 586 BIO_clear_retry_flags(b); 587 if (!ctx->obuf) { 588 ctx->obuf = OPENSSL_malloc(ctx->obufsize); 589 /* Need error here */ 590 if (!ctx->obuf) { 591 COMPerr(COMP_F_BIO_ZLIB_WRITE, ERR_R_MALLOC_FAILURE); 592 return 0; 593 } 594 ctx->optr = ctx->obuf; 595 ctx->ocount = 0; 596 deflateInit(zout, ctx->comp_level); 597 zout->next_out = ctx->obuf; 598 zout->avail_out = ctx->obufsize; 599 } 600 /* Obtain input data directly from supplied buffer */ 601 zout->next_in = (void *)in; 602 zout->avail_in = inl; 603 for (;;) { 604 /* If data in output buffer write it first */ 605 while (ctx->ocount) { 606 ret = BIO_write(b->next_bio, ctx->optr, ctx->ocount); 607 if (ret <= 0) { 608 /* Total data written */ 609 int tot = inl - zout->avail_in; 610 BIO_copy_next_retry(b); 611 if (ret < 0) 612 return (tot > 0) ? tot : ret; 613 return tot; 614 } 615 ctx->optr += ret; 616 ctx->ocount -= ret; 617 } 618 619 /* Have we consumed all supplied data? */ 620 if (!zout->avail_in) 621 return inl; 622 623 /* Compress some more */ 624 625 /* Reset buffer */ 626 ctx->optr = ctx->obuf; 627 zout->next_out = ctx->obuf; 628 zout->avail_out = ctx->obufsize; 629 /* Compress some more */ 630 ret = deflate(zout, 0); 631 if (ret != Z_OK) { 632 COMPerr(COMP_F_BIO_ZLIB_WRITE, COMP_R_ZLIB_DEFLATE_ERROR); 633 ERR_add_error_data(2, "zlib error:", zError(ret)); 634 return 0; 635 } 636 ctx->ocount = ctx->obufsize - zout->avail_out; 637 } 638} 639 640static int bio_zlib_flush(BIO *b) 641{ 642 BIO_ZLIB_CTX *ctx; 643 int ret; 644 z_stream *zout; 645 ctx = (BIO_ZLIB_CTX *) b->ptr; 646 /* If no data written or already flush show success */ 647 if (!ctx->obuf || (ctx->odone && !ctx->ocount)) 648 return 1; 649 zout = &ctx->zout; 650 BIO_clear_retry_flags(b); 651 /* No more input data */ 652 zout->next_in = NULL; 653 zout->avail_in = 0; 654 for (;;) { 655 /* If data in output buffer write it first */ 656 while (ctx->ocount) { 657 ret = BIO_write(b->next_bio, ctx->optr, ctx->ocount); 658 if (ret <= 0) { 659 BIO_copy_next_retry(b); 660 return ret; 661 } 662 ctx->optr += ret; 663 ctx->ocount -= ret; 664 } 665 if (ctx->odone) 666 return 1; 667 668 /* Compress some more */ 669 670 /* Reset buffer */ 671 ctx->optr = ctx->obuf; 672 zout->next_out = ctx->obuf; 673 zout->avail_out = ctx->obufsize; 674 /* Compress some more */ 675 ret = deflate(zout, Z_FINISH); 676 if (ret == Z_STREAM_END) 677 ctx->odone = 1; 678 else if (ret != Z_OK) { 679 COMPerr(COMP_F_BIO_ZLIB_FLUSH, COMP_R_ZLIB_DEFLATE_ERROR); 680 ERR_add_error_data(2, "zlib error:", zError(ret)); 681 return 0; 682 } 683 ctx->ocount = ctx->obufsize - zout->avail_out; 684 } 685} 686 687static long bio_zlib_ctrl(BIO *b, int cmd, long num, void *ptr) 688{ 689 BIO_ZLIB_CTX *ctx; 690 int ret, *ip; 691 int ibs, obs; 692 if (!b->next_bio) 693 return 0; 694 ctx = (BIO_ZLIB_CTX *) b->ptr; 695 switch (cmd) { 696 697 case BIO_CTRL_RESET: 698 ctx->ocount = 0; 699 ctx->odone = 0; 700 ret = 1; 701 break; 702 703 case BIO_CTRL_FLUSH: 704 ret = bio_zlib_flush(b); 705 if (ret > 0) 706 ret = BIO_flush(b->next_bio); 707 break; 708 709 case BIO_C_SET_BUFF_SIZE: 710 ibs = -1; 711 obs = -1; 712 if (ptr != NULL) { 713 ip = ptr; 714 if (*ip == 0) 715 ibs = (int)num; 716 else 717 obs = (int)num; 718 } else { 719 ibs = (int)num; 720 obs = ibs; 721 } 722 723 if (ibs != -1) { 724 if (ctx->ibuf) { 725 OPENSSL_free(ctx->ibuf); 726 ctx->ibuf = NULL; 727 } 728 ctx->ibufsize = ibs; 729 } 730 731 if (obs != -1) { 732 if (ctx->obuf) { 733 OPENSSL_free(ctx->obuf); 734 ctx->obuf = NULL; 735 } 736 ctx->obufsize = obs; 737 } 738 ret = 1; 739 break; 740 741 case BIO_C_DO_STATE_MACHINE: 742 BIO_clear_retry_flags(b); 743 ret = BIO_ctrl(b->next_bio, cmd, num, ptr); 744 BIO_copy_next_retry(b); 745 break; 746 747 default: 748 ret = BIO_ctrl(b->next_bio, cmd, num, ptr); 749 break; 750 751 } 752 753 return ret; 754} 755 756static long bio_zlib_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp) 757{ 758 if (!b->next_bio) 759 return 0; 760 return BIO_callback_ctrl(b->next_bio, cmd, fp); 761} 762 763#endif 764