You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kamailio/modules/tls/fixed_c_zlib.h

258 lines
6.6 KiB

/*
* TLS module
*
* This file contains modified zlib compression functions
* originally part of crypto/comp/c_zlib.c from the openssl library
* (version 0.9.8a).
* It's distributed under the same license as OpenSSL.
*
* Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved.
*/
/*!
* \file
* \brief Kamailio TLS support :: Zlib functions
* \ingroup tls
* Module: \ref tls
*
* This file contains modified zlib compression functions
* originally part of crypto/comp/c_zlib.c from the openssl library
* (version 0.9.8a).
*
* The changes are:
* - proper zalloc and zfree initialization for the zlib compression
* methods (use OPENSSL_malloc & OPENSSL_free to construct zalloc/zfree)
* - zlib_stateful_ex_idx is now a macro, a pointer to int is alloc'ed now
* on init and zlib_stateful_ex_idx is now the contents of this pointer
* (deref). This allows using compression from different processes (if
* the OPENSSL_malloc's are initialized previously to a shared mem. using
* version).
* -- andrei
*/
#ifdef TLS_FIX_ZLIB_COMPRESSION
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/objects.h>
#include <openssl/comp.h>
#include <openssl/err.h>
#include <zlib.h>
/* alloc functions for zlib initialization */
static void* comp_calloc(void* foo, unsigned int no, unsigned int size)
{
void *p;
p=OPENSSL_malloc(no*size);
if (p)
memset(p, 0, no*size);
return p;
}
/* alloc functions for zlib initialization */
static void comp_free(void* foo, void* p)
{
OPENSSL_free(p);
}
static int zlib_stateful_init(COMP_CTX *ctx);
static void zlib_stateful_finish(COMP_CTX *ctx);
static int zlib_stateful_compress_block(COMP_CTX *ctx, unsigned char *out,
unsigned int olen, unsigned char *in, unsigned int ilen);
static int zlib_stateful_expand_block(COMP_CTX *ctx, unsigned char *out,
unsigned int olen, unsigned char *in, unsigned int ilen);
static COMP_METHOD zlib_method={
NID_zlib_compression,
LN_zlib_compression,
zlib_stateful_init,
zlib_stateful_finish,
zlib_stateful_compress_block,
zlib_stateful_expand_block,
NULL,
NULL,
};
struct zlib_state
{
z_stream istream;
z_stream ostream;
};
static int* pzlib_stateful_ex_idx = 0;
#define zlib_stateful_ex_idx (*pzlib_stateful_ex_idx)
static void zlib_stateful_free_ex_data(void *obj, void *item,
CRYPTO_EX_DATA *ad, int ind,long argl, void *argp);
int fixed_c_zlib_init()
{
if (pzlib_stateful_ex_idx==0){
if ((pzlib_stateful_ex_idx=OPENSSL_malloc(sizeof(int)))!=0){
/* good side effect: it makes sure the ex_data hash
* in crypto/ex_data.c is created before fork
* (else each process would have its own copy :-( ) */
CRYPTO_w_lock(CRYPTO_LOCK_COMP);
zlib_stateful_ex_idx =
CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_COMP,
0,NULL,NULL,NULL,zlib_stateful_free_ex_data);
CRYPTO_w_unlock(CRYPTO_LOCK_COMP);
return 0;
} else return -1;
}
return -1;
}
static void zlib_stateful_free_ex_data(void *obj, void *item,
CRYPTO_EX_DATA *ad, int ind,long argl, void *argp)
{
struct zlib_state *state = (struct zlib_state *)item;
if (state)
{
inflateEnd(&state->istream);
deflateEnd(&state->ostream);
OPENSSL_free(state);
}
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);
}
static int zlib_stateful_init(COMP_CTX *ctx)
{
int err;
struct zlib_state *state =
(struct zlib_state *)OPENSSL_malloc(sizeof(struct zlib_state));
int inflate_init, deflate_init;
if (state == NULL)
goto err;
inflate_init=0;
deflate_init=0;
state->istream.zalloc = comp_calloc;
state->istream.zfree = comp_free;
state->istream.opaque = Z_NULL;
state->istream.next_in = Z_NULL;
state->istream.next_out = Z_NULL;
state->istream.avail_in = 0;
state->istream.avail_out = 0;
err = inflateInit_(&state->istream,
ZLIB_VERSION, sizeof(z_stream));
if (err != Z_OK)
goto err;
inflate_init=1;
state->ostream.zalloc = comp_calloc;
state->ostream.zfree = comp_free;
state->ostream.opaque = Z_NULL;
state->ostream.next_in = Z_NULL;
state->ostream.next_out = Z_NULL;
state->ostream.avail_in = 0;
state->ostream.avail_out = 0;
err = deflateInit_(&state->ostream,Z_DEFAULT_COMPRESSION,
ZLIB_VERSION, sizeof(z_stream));
if (err != Z_OK)
goto err;
deflate_init=1;
if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_COMP,ctx,&ctx->ex_data))
goto err;
if (zlib_stateful_ex_idx == -1)
{
CRYPTO_w_lock(CRYPTO_LOCK_COMP);
if (zlib_stateful_ex_idx == -1)
zlib_stateful_ex_idx =
CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_COMP,
0,NULL,NULL,NULL,zlib_stateful_free_ex_data);
CRYPTO_w_unlock(CRYPTO_LOCK_COMP);
if (zlib_stateful_ex_idx == -1)
goto err_ex_data;
}
if (!CRYPTO_set_ex_data(&ctx->ex_data,zlib_stateful_ex_idx,state))
goto err_ex_data;
return 1;
err_ex_data:
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_COMP,ctx,&ctx->ex_data);
err:
if (state){
/* ctx->ex_data freed from outside */
if (inflate_init)
inflateEnd(&state->istream);
if (deflate_init)
deflateEnd(&state->ostream);
OPENSSL_free(state);
}
return 0;
}
static void zlib_stateful_finish(COMP_CTX *ctx)
{
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_COMP,ctx,&ctx->ex_data);
}
static int zlib_stateful_compress_block(COMP_CTX *ctx, unsigned char *out,
unsigned int olen, unsigned char *in, unsigned int ilen)
{
int err = Z_OK;
struct zlib_state *state =
(struct zlib_state *)CRYPTO_get_ex_data(&ctx->ex_data,
zlib_stateful_ex_idx);
if (state == NULL)
return -1;
state->ostream.next_in = in;
state->ostream.avail_in = ilen;
state->ostream.next_out = out;
state->ostream.avail_out = olen;
if (ilen > 0)
err = deflate(&state->ostream, Z_SYNC_FLUSH);
if (err != Z_OK)
return -1;
#ifdef DEBUG_ZLIB
fprintf(stderr,"compress(%4d)->%4d %s\n",
ilen,olen - state->ostream.avail_out,
(ilen != olen - state->ostream.avail_out)?"zlib":"clear");
#endif
return olen - state->ostream.avail_out;
}
static int zlib_stateful_expand_block(COMP_CTX *ctx, unsigned char *out,
unsigned int olen, unsigned char *in, unsigned int ilen)
{
int err = Z_OK;
struct zlib_state *state =
(struct zlib_state *)CRYPTO_get_ex_data(&ctx->ex_data,
zlib_stateful_ex_idx);
if (state == NULL)
return 0;
state->istream.next_in = in;
state->istream.avail_in = ilen;
state->istream.next_out = out;
state->istream.avail_out = olen;
if (ilen > 0)
err = inflate(&state->istream, Z_SYNC_FLUSH);
if (err != Z_OK)
return -1;
#ifdef DEBUG_ZLIB
fprintf(stderr,"expand(%4d)->%4d %s\n",
ilen,olen - state->istream.avail_out,
(ilen != olen - state->istream.avail_out)?"zlib":"clear");
#endif
return olen - state->istream.avail_out;
}
#endif /* TLS_FIX_ZLIB_COMPRESSION */