mirror of https://github.com/sipwise/kamailio.git
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.
258 lines
6.6 KiB
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 */
|