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