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, unsigned int ilen); 31static int zlib_stateful_expand_block(COMP_CTX *ctx, unsigned char *out, 32 unsigned int olen, unsigned char *in, unsigned int ilen); 33 34#if 0 35static int zlib_compress_block(COMP_CTX *ctx, unsigned char *out, 36 unsigned int olen, unsigned char *in, unsigned int ilen); 37static int zlib_expand_block(COMP_CTX *ctx, unsigned char *out, 38 unsigned int olen, unsigned char *in, unsigned int ilen); 39 40static int zz_uncompress(Bytef *dest, uLongf *destLen, const Bytef *source, 41 uLong sourceLen); 42 43static COMP_METHOD zlib_stateless_method={ 44 NID_zlib_compression, 45 LN_zlib_compression, 46 NULL, 47 NULL, 48 zlib_compress_block, 49 zlib_expand_block, 50 NULL, 51 NULL, 52 }; 53#endif 54 55static COMP_METHOD zlib_stateful_method={ 56 NID_zlib_compression, 57 LN_zlib_compression, 58 zlib_stateful_init, 59 zlib_stateful_finish, 60 zlib_stateful_compress_block, 61 zlib_stateful_expand_block, 62 NULL, 63 NULL, 64 }; 65 66/* 67 * When OpenSSL is built on Windows, we do not want to require that 68 * the ZLIB.DLL be available in order for the OpenSSL DLLs to 69 * work. Therefore, all ZLIB routines are loaded at run time 70 * and we do not link to a .LIB file. 71 */ 72#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32) 73# include <windows.h> 74 75# define Z_CALLCONV _stdcall 76# ifndef ZLIB_SHARED 77# define ZLIB_SHARED 78# endif 79#else 80# define Z_CALLCONV 81#endif /* !(OPENSSL_SYS_WINDOWS || OPENSSL_SYS_WIN32) */ 82 83#ifdef ZLIB_SHARED 84#include <openssl/dso.h> 85 86/* Prototypes for built in stubs */ 87#if 0 88static int stub_compress(Bytef *dest,uLongf *destLen, 89 const Bytef *source, uLong sourceLen); 90#endif 91static int stub_inflateEnd(z_streamp strm); 92static int stub_inflate(z_streamp strm, int flush); 93static int stub_inflateInit_(z_streamp strm, const char * version, 94 int stream_size); 95static int stub_deflateEnd(z_streamp strm); 96static int stub_deflate(z_streamp strm, int flush); 97static int stub_deflateInit_(z_streamp strm, int level, 98 const char * version, int stream_size); 99 100/* Function pointers */ 101typedef int (Z_CALLCONV *compress_ft)(Bytef *dest,uLongf *destLen, 102 const Bytef *source, uLong sourceLen); 103typedef int (Z_CALLCONV *inflateEnd_ft)(z_streamp strm); 104typedef int (Z_CALLCONV *inflate_ft)(z_streamp strm, int flush); 105typedef int (Z_CALLCONV *inflateInit__ft)(z_streamp strm, 106 const char * version, int stream_size); 107typedef int (Z_CALLCONV *deflateEnd_ft)(z_streamp strm); 108typedef int (Z_CALLCONV *deflate_ft)(z_streamp strm, int flush); 109typedef int (Z_CALLCONV *deflateInit__ft)(z_streamp strm, int level, 110 const char * version, int stream_size); 111static compress_ft p_compress=NULL; 112static inflateEnd_ft p_inflateEnd=NULL; 113static inflate_ft p_inflate=NULL; 114static inflateInit__ft p_inflateInit_=NULL; 115static deflateEnd_ft p_deflateEnd=NULL; 116static deflate_ft p_deflate=NULL; 117static deflateInit__ft p_deflateInit_=NULL; 118 119static int zlib_loaded = 0; /* only attempt to init func pts once */ 120static DSO *zlib_dso = NULL; 121 122#define compress stub_compress 123#define inflateEnd stub_inflateEnd 124#define inflate stub_inflate 125#define inflateInit_ stub_inflateInit_ 126#define deflateEnd stub_deflateEnd 127#define deflate stub_deflate 128#define deflateInit_ stub_deflateInit_ 129#endif /* ZLIB_SHARED */ 130 131struct zlib_state 132 { 133 z_stream istream; 134 z_stream ostream; 135 }; 136 137static int zlib_stateful_ex_idx = -1; 138 139static void zlib_stateful_free_ex_data(void *obj, void *item, 140 CRYPTO_EX_DATA *ad, int ind,long argl, void *argp) 141 { 142 struct zlib_state *state = (struct zlib_state *)item; 143 inflateEnd(&state->istream); 144 deflateEnd(&state->ostream); 145 OPENSSL_free(state); 146 } 147 148static int zlib_stateful_init(COMP_CTX *ctx) 149 { 150 int err; 151 struct zlib_state *state = 152 (struct zlib_state *)OPENSSL_malloc(sizeof(struct zlib_state)); 153 154 if (state == NULL) 155 goto err; 156 157 state->istream.zalloc = Z_NULL; 158 state->istream.zfree = Z_NULL; 159 state->istream.opaque = Z_NULL; 160 state->istream.next_in = Z_NULL; 161 state->istream.next_out = Z_NULL; 162 state->istream.avail_in = 0; 163 state->istream.avail_out = 0; 164 err = inflateInit_(&state->istream, 165 ZLIB_VERSION, sizeof(z_stream)); 166 if (err != Z_OK) 167 goto err; 168 169 state->ostream.zalloc = Z_NULL; 170 state->ostream.zfree = Z_NULL; 171 state->ostream.opaque = Z_NULL; 172 state->ostream.next_in = Z_NULL; 173 state->ostream.next_out = Z_NULL; 174 state->ostream.avail_in = 0; 175 state->ostream.avail_out = 0; 176 err = deflateInit_(&state->ostream,Z_DEFAULT_COMPRESSION, 177 ZLIB_VERSION, sizeof(z_stream)); 178 if (err != Z_OK) 179 goto err; 180 181 CRYPTO_new_ex_data(CRYPTO_EX_INDEX_COMP,ctx,&ctx->ex_data); 182 if (zlib_stateful_ex_idx == -1) 183 { 184 CRYPTO_w_lock(CRYPTO_LOCK_COMP); 185 if (zlib_stateful_ex_idx == -1) 186 zlib_stateful_ex_idx = 187 CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_COMP, 188 0,NULL,NULL,NULL,zlib_stateful_free_ex_data); 189 CRYPTO_w_unlock(CRYPTO_LOCK_COMP); 190 if (zlib_stateful_ex_idx == -1) 191 goto err; 192 } 193 CRYPTO_set_ex_data(&ctx->ex_data,zlib_stateful_ex_idx,state); 194 return 1; 195 err: 196 if (state) OPENSSL_free(state); 197 return 0; 198 } 199 200static void zlib_stateful_finish(COMP_CTX *ctx) 201 { 202 CRYPTO_free_ex_data(CRYPTO_EX_INDEX_COMP,ctx,&ctx->ex_data); 203 } 204 205static int zlib_stateful_compress_block(COMP_CTX *ctx, unsigned char *out, 206 unsigned int olen, unsigned char *in, unsigned int ilen) 207 { 208 int err = Z_OK; 209 struct zlib_state *state = 210 (struct zlib_state *)CRYPTO_get_ex_data(&ctx->ex_data, 211 zlib_stateful_ex_idx); 212 213 if (state == NULL) 214 return -1; 215 216 state->ostream.next_in = in; 217 state->ostream.avail_in = ilen; 218 state->ostream.next_out = out; 219 state->ostream.avail_out = olen; 220 if (ilen > 0) 221 err = deflate(&state->ostream, Z_SYNC_FLUSH); 222 if (err != Z_OK) 223 return -1; 224#ifdef DEBUG_ZLIB 225 fprintf(stderr,"compress(%4d)->%4d %s\n", 226 ilen,olen - state->ostream.avail_out, 227 (ilen != olen - state->ostream.avail_out)?"zlib":"clear"); 228#endif 229 return olen - state->ostream.avail_out; 230 } 231 232static int zlib_stateful_expand_block(COMP_CTX *ctx, unsigned char *out, 233 unsigned int olen, unsigned char *in, unsigned int ilen) 234 { 235 int err = Z_OK; 236 237 struct zlib_state *state = 238 (struct zlib_state *)CRYPTO_get_ex_data(&ctx->ex_data, 239 zlib_stateful_ex_idx); 240 241 if (state == NULL) 242 return 0; 243 244 state->istream.next_in = in; 245 state->istream.avail_in = ilen; 246 state->istream.next_out = out; 247 state->istream.avail_out = olen; 248 if (ilen > 0) 249 err = inflate(&state->istream, Z_SYNC_FLUSH); 250 if (err != Z_OK) 251 return -1; 252#ifdef DEBUG_ZLIB 253 fprintf(stderr,"expand(%4d)->%4d %s\n", 254 ilen,olen - state->istream.avail_out, 255 (ilen != olen - state->istream.avail_out)?"zlib":"clear"); 256#endif 257 return olen - state->istream.avail_out; 258 } 259 260#if 0 261static int zlib_compress_block(COMP_CTX *ctx, unsigned char *out, 262 unsigned int olen, unsigned char *in, unsigned int ilen) 263 { 264 unsigned long l; 265 int i; 266 int clear=1; 267 268 if (ilen > 128) 269 { 270 out[0]=1; 271 l=olen-1; 272 i=compress(&(out[1]),&l,in,(unsigned long)ilen); 273 if (i != Z_OK) 274 return(-1); 275 if (ilen > l) 276 { 277 clear=0; 278 l++; 279 } 280 } 281 if (clear) 282 { 283 out[0]=0; 284 memcpy(&(out[1]),in,ilen); 285 l=ilen+1; 286 } 287#ifdef DEBUG_ZLIB 288 fprintf(stderr,"compress(%4d)->%4d %s\n", 289 ilen,(int)l,(clear)?"clear":"zlib"); 290#endif 291 return((int)l); 292 } 293 294static int zlib_expand_block(COMP_CTX *ctx, unsigned char *out, 295 unsigned int olen, unsigned char *in, unsigned int ilen) 296 { 297 unsigned long l; 298 int i; 299 300 if (in[0]) 301 { 302 l=olen; 303 i=zz_uncompress(out,&l,&(in[1]),(unsigned long)ilen-1); 304 if (i != Z_OK) 305 return(-1); 306 } 307 else 308 { 309 memcpy(out,&(in[1]),ilen-1); 310 l=ilen-1; 311 } 312#ifdef DEBUG_ZLIB 313 fprintf(stderr,"expand (%4d)->%4d %s\n", 314 ilen,(int)l,in[0]?"zlib":"clear"); 315#endif 316 return((int)l); 317 } 318 319static int zz_uncompress (Bytef *dest, uLongf *destLen, const Bytef *source, 320 uLong sourceLen) 321{ 322 z_stream stream; 323 int err; 324 325 stream.next_in = (Bytef*)source; 326 stream.avail_in = (uInt)sourceLen; 327 /* Check for source > 64K on 16-bit machine: */ 328 if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; 329 330 stream.next_out = dest; 331 stream.avail_out = (uInt)*destLen; 332 if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; 333 334 stream.zalloc = (alloc_func)0; 335 stream.zfree = (free_func)0; 336 337 err = inflateInit_(&stream, 338 ZLIB_VERSION, sizeof(z_stream)); 339 if (err != Z_OK) return err; 340 341 err = inflate(&stream, Z_FINISH); 342 if (err != Z_STREAM_END) { 343 inflateEnd(&stream); 344 return err; 345 } 346 *destLen = stream.total_out; 347 348 err = inflateEnd(&stream); 349 return err; 350} 351#endif 352 353#endif 354 355COMP_METHOD *COMP_zlib(void) 356 { 357 COMP_METHOD *meth = &zlib_method_nozlib; 358 359#ifdef ZLIB_SHARED 360 if (!zlib_loaded) 361 { 362#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32) 363 zlib_dso = DSO_load(NULL, "ZLIB1", NULL, 0); 364 if (!zlib_dso) 365 { 366 zlib_dso = DSO_load(NULL, "ZLIB", NULL, 0); 367 if (zlib_dso) 368 { 369 /* Clear the errors from the first failed 370 DSO_load() */ 371 ERR_clear_error(); 372 } 373 } 374#else 375 zlib_dso = DSO_load(NULL, "z", NULL, 0); 376#endif 377 if (zlib_dso != NULL) 378 { 379 p_compress 380 = (compress_ft) DSO_bind_func(zlib_dso, 381 "compress"); 382 p_inflateEnd 383 = (inflateEnd_ft) DSO_bind_func(zlib_dso, 384 "inflateEnd"); 385 p_inflate 386 = (inflate_ft) DSO_bind_func(zlib_dso, 387 "inflate"); 388 p_inflateInit_ 389 = (inflateInit__ft) DSO_bind_func(zlib_dso, 390 "inflateInit_"); 391 p_deflateEnd 392 = (deflateEnd_ft) DSO_bind_func(zlib_dso, 393 "deflateEnd"); 394 p_deflate 395 = (deflate_ft) DSO_bind_func(zlib_dso, 396 "deflate"); 397 p_deflateInit_ 398 = (deflateInit__ft) DSO_bind_func(zlib_dso, 399 "deflateInit_"); 400 zlib_loaded++; 401 } 402 } 403 404#endif 405#if defined(ZLIB) || defined(ZLIB_SHARED) 406 meth = &zlib_stateful_method; 407#endif 408 409 return(meth); 410 } 411 412#ifdef ZLIB_SHARED 413#if 0 414/* Stubs for each function to be dynamicly loaded */ 415static int 416stub_compress(Bytef *dest,uLongf *destLen,const Bytef *source, uLong sourceLen) 417 { 418 if (p_compress) 419 return(p_compress(dest,destLen,source,sourceLen)); 420 else 421 return(Z_MEM_ERROR); 422 } 423#endif 424 425static int 426stub_inflateEnd(z_streamp strm) 427 { 428 if ( p_inflateEnd ) 429 return(p_inflateEnd(strm)); 430 else 431 return(Z_MEM_ERROR); 432 } 433 434static int 435stub_inflate(z_streamp strm, int flush) 436 { 437 if ( p_inflate ) 438 return(p_inflate(strm,flush)); 439 else 440 return(Z_MEM_ERROR); 441 } 442 443static int 444stub_inflateInit_(z_streamp strm, const char * version, int stream_size) 445 { 446 if ( p_inflateInit_ ) 447 return(p_inflateInit_(strm,version,stream_size)); 448 else 449 return(Z_MEM_ERROR); 450 } 451 452static int 453stub_deflateEnd(z_streamp strm) 454 { 455 if ( p_deflateEnd ) 456 return(p_deflateEnd(strm)); 457 else 458 return(Z_MEM_ERROR); 459 } 460 461static int 462stub_deflate(z_streamp strm, int flush) 463 { 464 if ( p_deflate ) 465 return(p_deflate(strm,flush)); 466 else 467 return(Z_MEM_ERROR); 468 } 469 470static int 471stub_deflateInit_(z_streamp strm, int level, 472 const char * version, int stream_size) 473 { 474 if ( p_deflateInit_ ) 475 return(p_deflateInit_(strm,level,version,stream_size)); 476 else 477 return(Z_MEM_ERROR); 478 } 479 480#endif /* ZLIB_SHARED */ 481