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) 408 DSO_free(zlib_dso); 409#endif 410} 411 412#ifdef ZLIB 413 414/* Zlib based compression/decompression filter BIO */ 415 416typedef struct { 417 unsigned char *ibuf; /* Input buffer */ 418 int ibufsize; /* Buffer size */ 419 z_stream zin; /* Input decompress context */ 420 unsigned char *obuf; /* Output buffer */ 421 int obufsize; /* Output buffer size */ 422 unsigned char *optr; /* Position in output buffer */ 423 int ocount; /* Amount of data in output buffer */ 424 int odone; /* deflate EOF */ 425 int comp_level; /* Compression level to use */ 426 z_stream zout; /* Output compression context */ 427} BIO_ZLIB_CTX; 428 429# define ZLIB_DEFAULT_BUFSIZE 1024 430 431static int bio_zlib_new(BIO *bi); 432static int bio_zlib_free(BIO *bi); 433static int bio_zlib_read(BIO *b, char *out, int outl); 434static int bio_zlib_write(BIO *b, const char *in, int inl); 435static long bio_zlib_ctrl(BIO *b, int cmd, long num, void *ptr); 436static long bio_zlib_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp); 437 438static BIO_METHOD bio_meth_zlib = { 439 BIO_TYPE_COMP, 440 "zlib", 441 bio_zlib_write, 442 bio_zlib_read, 443 NULL, 444 NULL, 445 bio_zlib_ctrl, 446 bio_zlib_new, 447 bio_zlib_free, 448 bio_zlib_callback_ctrl 449}; 450 451BIO_METHOD *BIO_f_zlib(void) 452{ 453 return &bio_meth_zlib; 454} 455 456static int bio_zlib_new(BIO *bi) 457{ 458 BIO_ZLIB_CTX *ctx; 459# ifdef ZLIB_SHARED 460 (void)COMP_zlib(); 461 if (!zlib_loaded) { 462 COMPerr(COMP_F_BIO_ZLIB_NEW, COMP_R_ZLIB_NOT_SUPPORTED); 463 return 0; 464 } 465# endif 466 ctx = OPENSSL_malloc(sizeof(BIO_ZLIB_CTX)); 467 if (!ctx) { 468 COMPerr(COMP_F_BIO_ZLIB_NEW, ERR_R_MALLOC_FAILURE); 469 return 0; 470 } 471 ctx->ibuf = NULL; 472 ctx->obuf = NULL; 473 ctx->ibufsize = ZLIB_DEFAULT_BUFSIZE; 474 ctx->obufsize = ZLIB_DEFAULT_BUFSIZE; 475 ctx->zin.zalloc = Z_NULL; 476 ctx->zin.zfree = Z_NULL; 477 ctx->zin.next_in = NULL; 478 ctx->zin.avail_in = 0; 479 ctx->zin.next_out = NULL; 480 ctx->zin.avail_out = 0; 481 ctx->zout.zalloc = Z_NULL; 482 ctx->zout.zfree = Z_NULL; 483 ctx->zout.next_in = NULL; 484 ctx->zout.avail_in = 0; 485 ctx->zout.next_out = NULL; 486 ctx->zout.avail_out = 0; 487 ctx->odone = 0; 488 ctx->comp_level = Z_DEFAULT_COMPRESSION; 489 bi->init = 1; 490 bi->ptr = (char *)ctx; 491 bi->flags = 0; 492 return 1; 493} 494 495static int bio_zlib_free(BIO *bi) 496{ 497 BIO_ZLIB_CTX *ctx; 498 if (!bi) 499 return 0; 500 ctx = (BIO_ZLIB_CTX *) bi->ptr; 501 if (ctx->ibuf) { 502 /* Destroy decompress context */ 503 inflateEnd(&ctx->zin); 504 OPENSSL_free(ctx->ibuf); 505 } 506 if (ctx->obuf) { 507 /* Destroy compress context */ 508 deflateEnd(&ctx->zout); 509 OPENSSL_free(ctx->obuf); 510 } 511 OPENSSL_free(ctx); 512 bi->ptr = NULL; 513 bi->init = 0; 514 bi->flags = 0; 515 return 1; 516} 517 518static int bio_zlib_read(BIO *b, char *out, int outl) 519{ 520 BIO_ZLIB_CTX *ctx; 521 int ret; 522 z_stream *zin; 523 if (!out || !outl) 524 return 0; 525 ctx = (BIO_ZLIB_CTX *) b->ptr; 526 zin = &ctx->zin; 527 BIO_clear_retry_flags(b); 528 if (!ctx->ibuf) { 529 ctx->ibuf = OPENSSL_malloc(ctx->ibufsize); 530 if (!ctx->ibuf) { 531 COMPerr(COMP_F_BIO_ZLIB_READ, ERR_R_MALLOC_FAILURE); 532 return 0; 533 } 534 inflateInit(zin); 535 zin->next_in = ctx->ibuf; 536 zin->avail_in = 0; 537 } 538 539 /* Copy output data directly to supplied buffer */ 540 zin->next_out = (unsigned char *)out; 541 zin->avail_out = (unsigned int)outl; 542 for (;;) { 543 /* Decompress while data available */ 544 while (zin->avail_in) { 545 ret = inflate(zin, 0); 546 if ((ret != Z_OK) && (ret != Z_STREAM_END)) { 547 COMPerr(COMP_F_BIO_ZLIB_READ, COMP_R_ZLIB_INFLATE_ERROR); 548 ERR_add_error_data(2, "zlib error:", zError(ret)); 549 return 0; 550 } 551 /* If EOF or we've read everything then return */ 552 if ((ret == Z_STREAM_END) || !zin->avail_out) 553 return outl - zin->avail_out; 554 } 555 556 /* 557 * No data in input buffer try to read some in, if an error then 558 * return the total data read. 559 */ 560 ret = BIO_read(b->next_bio, ctx->ibuf, ctx->ibufsize); 561 if (ret <= 0) { 562 /* Total data read */ 563 int tot = outl - zin->avail_out; 564 BIO_copy_next_retry(b); 565 if (ret < 0) 566 return (tot > 0) ? tot : ret; 567 return tot; 568 } 569 zin->avail_in = ret; 570 zin->next_in = ctx->ibuf; 571 } 572} 573 574static int bio_zlib_write(BIO *b, const char *in, int inl) 575{ 576 BIO_ZLIB_CTX *ctx; 577 int ret; 578 z_stream *zout; 579 if (!in || !inl) 580 return 0; 581 ctx = (BIO_ZLIB_CTX *) b->ptr; 582 if (ctx->odone) 583 return 0; 584 zout = &ctx->zout; 585 BIO_clear_retry_flags(b); 586 if (!ctx->obuf) { 587 ctx->obuf = OPENSSL_malloc(ctx->obufsize); 588 /* Need error here */ 589 if (!ctx->obuf) { 590 COMPerr(COMP_F_BIO_ZLIB_WRITE, ERR_R_MALLOC_FAILURE); 591 return 0; 592 } 593 ctx->optr = ctx->obuf; 594 ctx->ocount = 0; 595 deflateInit(zout, ctx->comp_level); 596 zout->next_out = ctx->obuf; 597 zout->avail_out = ctx->obufsize; 598 } 599 /* Obtain input data directly from supplied buffer */ 600 zout->next_in = (void *)in; 601 zout->avail_in = inl; 602 for (;;) { 603 /* If data in output buffer write it first */ 604 while (ctx->ocount) { 605 ret = BIO_write(b->next_bio, ctx->optr, ctx->ocount); 606 if (ret <= 0) { 607 /* Total data written */ 608 int tot = inl - zout->avail_in; 609 BIO_copy_next_retry(b); 610 if (ret < 0) 611 return (tot > 0) ? tot : ret; 612 return tot; 613 } 614 ctx->optr += ret; 615 ctx->ocount -= ret; 616 } 617 618 /* Have we consumed all supplied data? */ 619 if (!zout->avail_in) 620 return inl; 621 622 /* Compress some more */ 623 624 /* Reset buffer */ 625 ctx->optr = ctx->obuf; 626 zout->next_out = ctx->obuf; 627 zout->avail_out = ctx->obufsize; 628 /* Compress some more */ 629 ret = deflate(zout, 0); 630 if (ret != Z_OK) { 631 COMPerr(COMP_F_BIO_ZLIB_WRITE, COMP_R_ZLIB_DEFLATE_ERROR); 632 ERR_add_error_data(2, "zlib error:", zError(ret)); 633 return 0; 634 } 635 ctx->ocount = ctx->obufsize - zout->avail_out; 636 } 637} 638 639static int bio_zlib_flush(BIO *b) 640{ 641 BIO_ZLIB_CTX *ctx; 642 int ret; 643 z_stream *zout; 644 ctx = (BIO_ZLIB_CTX *) b->ptr; 645 /* If no data written or already flush show success */ 646 if (!ctx->obuf || (ctx->odone && !ctx->ocount)) 647 return 1; 648 zout = &ctx->zout; 649 BIO_clear_retry_flags(b); 650 /* No more input data */ 651 zout->next_in = NULL; 652 zout->avail_in = 0; 653 for (;;) { 654 /* If data in output buffer write it first */ 655 while (ctx->ocount) { 656 ret = BIO_write(b->next_bio, ctx->optr, ctx->ocount); 657 if (ret <= 0) { 658 BIO_copy_next_retry(b); 659 return ret; 660 } 661 ctx->optr += ret; 662 ctx->ocount -= ret; 663 } 664 if (ctx->odone) 665 return 1; 666 667 /* Compress some more */ 668 669 /* Reset buffer */ 670 ctx->optr = ctx->obuf; 671 zout->next_out = ctx->obuf; 672 zout->avail_out = ctx->obufsize; 673 /* Compress some more */ 674 ret = deflate(zout, Z_FINISH); 675 if (ret == Z_STREAM_END) 676 ctx->odone = 1; 677 else if (ret != Z_OK) { 678 COMPerr(COMP_F_BIO_ZLIB_FLUSH, COMP_R_ZLIB_DEFLATE_ERROR); 679 ERR_add_error_data(2, "zlib error:", zError(ret)); 680 return 0; 681 } 682 ctx->ocount = ctx->obufsize - zout->avail_out; 683 } 684} 685 686static long bio_zlib_ctrl(BIO *b, int cmd, long num, void *ptr) 687{ 688 BIO_ZLIB_CTX *ctx; 689 int ret, *ip; 690 int ibs, obs; 691 if (!b->next_bio) 692 return 0; 693 ctx = (BIO_ZLIB_CTX *) b->ptr; 694 switch (cmd) { 695 696 case BIO_CTRL_RESET: 697 ctx->ocount = 0; 698 ctx->odone = 0; 699 ret = 1; 700 break; 701 702 case BIO_CTRL_FLUSH: 703 ret = bio_zlib_flush(b); 704 if (ret > 0) 705 ret = BIO_flush(b->next_bio); 706 break; 707 708 case BIO_C_SET_BUFF_SIZE: 709 ibs = -1; 710 obs = -1; 711 if (ptr != NULL) { 712 ip = ptr; 713 if (*ip == 0) 714 ibs = (int)num; 715 else 716 obs = (int)num; 717 } else { 718 ibs = (int)num; 719 obs = ibs; 720 } 721 722 if (ibs != -1) { 723 if (ctx->ibuf) { 724 OPENSSL_free(ctx->ibuf); 725 ctx->ibuf = NULL; 726 } 727 ctx->ibufsize = ibs; 728 } 729 730 if (obs != -1) { 731 if (ctx->obuf) { 732 OPENSSL_free(ctx->obuf); 733 ctx->obuf = NULL; 734 } 735 ctx->obufsize = obs; 736 } 737 ret = 1; 738 break; 739 740 case BIO_C_DO_STATE_MACHINE: 741 BIO_clear_retry_flags(b); 742 ret = BIO_ctrl(b->next_bio, cmd, num, ptr); 743 BIO_copy_next_retry(b); 744 break; 745 746 default: 747 ret = BIO_ctrl(b->next_bio, cmd, num, ptr); 748 break; 749 750 } 751 752 return ret; 753} 754 755static long bio_zlib_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp) 756{ 757 if (!b->next_bio) 758 return 0; 759 return BIO_callback_ctrl(b->next_bio, cmd, fp); 760} 761 762#endif 763