00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00030 #ifdef TLS_FIX_ZLIB_COMPRESSION
00031
00032 #include <stdio.h>
00033 #include <stdlib.h>
00034 #include <string.h>
00035 #include <openssl/objects.h>
00036 #include <openssl/comp.h>
00037 #include <openssl/err.h>
00038
00039 #include <zlib.h>
00040
00041
00042
00043 static void* comp_calloc(void* foo, unsigned int no, unsigned int size)
00044 {
00045 void *p;
00046
00047 p=OPENSSL_malloc(no*size);
00048 if (p)
00049 memset(p, 0, no*size);
00050 return p;
00051 }
00052
00053
00054
00055 static void comp_free(void* foo, void* p)
00056 {
00057 OPENSSL_free(p);
00058 }
00059
00060
00061 static int zlib_stateful_init(COMP_CTX *ctx);
00062 static void zlib_stateful_finish(COMP_CTX *ctx);
00063 static int zlib_stateful_compress_block(COMP_CTX *ctx, unsigned char *out,
00064 unsigned int olen, unsigned char *in, unsigned int ilen);
00065 static int zlib_stateful_expand_block(COMP_CTX *ctx, unsigned char *out,
00066 unsigned int olen, unsigned char *in, unsigned int ilen);
00067
00068
00069 static COMP_METHOD zlib_method={
00070 NID_zlib_compression,
00071 LN_zlib_compression,
00072 zlib_stateful_init,
00073 zlib_stateful_finish,
00074 zlib_stateful_compress_block,
00075 zlib_stateful_expand_block,
00076 NULL,
00077 NULL,
00078 };
00079
00080
00081 struct zlib_state
00082 {
00083 z_stream istream;
00084 z_stream ostream;
00085 };
00086
00087 static int* pzlib_stateful_ex_idx = 0;
00088 #define zlib_stateful_ex_idx (*pzlib_stateful_ex_idx)
00089
00090 static void zlib_stateful_free_ex_data(void *obj, void *item,
00091 CRYPTO_EX_DATA *ad, int ind,long argl, void *argp);
00092
00093 int fixed_c_zlib_init()
00094 {
00095 if (pzlib_stateful_ex_idx==0){
00096 if ((pzlib_stateful_ex_idx=OPENSSL_malloc(sizeof(int)))!=0){
00097
00098
00099
00100 CRYPTO_w_lock(CRYPTO_LOCK_COMP);
00101 zlib_stateful_ex_idx =
00102 CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_COMP,
00103 0,NULL,NULL,NULL,zlib_stateful_free_ex_data);
00104 CRYPTO_w_unlock(CRYPTO_LOCK_COMP);
00105 return 0;
00106 } else return -1;
00107 }
00108 return -1;
00109 }
00110
00111
00112
00113 static void zlib_stateful_free_ex_data(void *obj, void *item,
00114 CRYPTO_EX_DATA *ad, int ind,long argl, void *argp)
00115 {
00116 struct zlib_state *state = (struct zlib_state *)item;
00117 if (state)
00118 {
00119 inflateEnd(&state->istream);
00120 deflateEnd(&state->ostream);
00121 OPENSSL_free(state);
00122 }
00123 else LOG(L_CRIT, "WARNING: zlib_stateful_free_ex(%p, %p, %p, %d, %ld, %p)" ": cannot free, null item/state\n", obj, item, ad, ind, argl, argp);
00124 }
00125
00126 static int zlib_stateful_init(COMP_CTX *ctx)
00127 {
00128 int err;
00129 struct zlib_state *state =
00130 (struct zlib_state *)OPENSSL_malloc(sizeof(struct zlib_state));
00131 int inflate_init, deflate_init;
00132
00133 if (state == NULL)
00134 goto err;
00135 inflate_init=0;
00136 deflate_init=0;
00137
00138 state->istream.zalloc = comp_calloc;
00139 state->istream.zfree = comp_free;
00140 state->istream.opaque = Z_NULL;
00141 state->istream.next_in = Z_NULL;
00142 state->istream.next_out = Z_NULL;
00143 state->istream.avail_in = 0;
00144 state->istream.avail_out = 0;
00145 err = inflateInit_(&state->istream,
00146 ZLIB_VERSION, sizeof(z_stream));
00147 if (err != Z_OK)
00148 goto err;
00149 inflate_init=1;
00150
00151 state->ostream.zalloc = comp_calloc;
00152 state->ostream.zfree = comp_free;
00153 state->ostream.opaque = Z_NULL;
00154 state->ostream.next_in = Z_NULL;
00155 state->ostream.next_out = Z_NULL;
00156 state->ostream.avail_in = 0;
00157 state->ostream.avail_out = 0;
00158 err = deflateInit_(&state->ostream,Z_DEFAULT_COMPRESSION,
00159 ZLIB_VERSION, sizeof(z_stream));
00160 if (err != Z_OK)
00161 goto err;
00162 deflate_init=1;
00163
00164 if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_COMP,ctx,&ctx->ex_data))
00165 goto err;
00166 if (zlib_stateful_ex_idx == -1)
00167 {
00168 CRYPTO_w_lock(CRYPTO_LOCK_COMP);
00169 if (zlib_stateful_ex_idx == -1)
00170 zlib_stateful_ex_idx =
00171 CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_COMP,
00172 0,NULL,NULL,NULL,zlib_stateful_free_ex_data);
00173 CRYPTO_w_unlock(CRYPTO_LOCK_COMP);
00174 if (zlib_stateful_ex_idx == -1)
00175 goto err_ex_data;
00176 }
00177 if (!CRYPTO_set_ex_data(&ctx->ex_data,zlib_stateful_ex_idx,state))
00178 goto err_ex_data;
00179 return 1;
00180 err_ex_data:
00181 CRYPTO_free_ex_data(CRYPTO_EX_INDEX_COMP,ctx,&ctx->ex_data);
00182 err:
00183 if (state){
00184
00185 if (inflate_init)
00186 inflateEnd(&state->istream);
00187 if (deflate_init)
00188 deflateEnd(&state->ostream);
00189 OPENSSL_free(state);
00190 }
00191 return 0;
00192 }
00193
00194 static void zlib_stateful_finish(COMP_CTX *ctx)
00195 {
00196 CRYPTO_free_ex_data(CRYPTO_EX_INDEX_COMP,ctx,&ctx->ex_data);
00197 }
00198
00199 static int zlib_stateful_compress_block(COMP_CTX *ctx, unsigned char *out,
00200 unsigned int olen, unsigned char *in, unsigned int ilen)
00201 {
00202 int err = Z_OK;
00203 struct zlib_state *state =
00204 (struct zlib_state *)CRYPTO_get_ex_data(&ctx->ex_data,
00205 zlib_stateful_ex_idx);
00206
00207 if (state == NULL)
00208 return -1;
00209
00210 state->ostream.next_in = in;
00211 state->ostream.avail_in = ilen;
00212 state->ostream.next_out = out;
00213 state->ostream.avail_out = olen;
00214 if (ilen > 0)
00215 err = deflate(&state->ostream, Z_SYNC_FLUSH);
00216 if (err != Z_OK)
00217 return -1;
00218 #ifdef DEBUG_ZLIB
00219 fprintf(stderr,"compress(%4d)->%4d %s\n",
00220 ilen,olen - state->ostream.avail_out,
00221 (ilen != olen - state->ostream.avail_out)?"zlib":"clear");
00222 #endif
00223 return olen - state->ostream.avail_out;
00224 }
00225
00226 static int zlib_stateful_expand_block(COMP_CTX *ctx, unsigned char *out,
00227 unsigned int olen, unsigned char *in, unsigned int ilen)
00228 {
00229 int err = Z_OK;
00230
00231 struct zlib_state *state =
00232 (struct zlib_state *)CRYPTO_get_ex_data(&ctx->ex_data,
00233 zlib_stateful_ex_idx);
00234
00235 if (state == NULL)
00236 return 0;
00237
00238 state->istream.next_in = in;
00239 state->istream.avail_in = ilen;
00240 state->istream.next_out = out;
00241 state->istream.avail_out = olen;
00242 if (ilen > 0)
00243 err = inflate(&state->istream, Z_SYNC_FLUSH);
00244 if (err != Z_OK)
00245 return -1;
00246 #ifdef DEBUG_ZLIB
00247 fprintf(stderr,"expand(%4d)->%4d %s\n",
00248 ilen,olen - state->istream.avail_out,
00249 (ilen != olen - state->istream.avail_out)?"zlib":"clear");
00250 #endif
00251 return olen - state->istream.avail_out;
00252 }
00253
00254 #endif