#include"bio.h" #include"errno.h" #include"cryptlib.h" #include"lhash.h" #include"myfunction.h" static int ex_data_check(void); #define EX_IMPL(a) impl->cb_##a #define IMPL_CHECK if(!impl) impl_check(); #define EX_DATA_CHECK(iffail) if(!ex_data && !ex_data_check()) {iffail} typedef struct st_ex_class_item { int class_index; STACK_OF(CRYPTO_EX_DATA_FUNCS) *meth; int meth_num; } EX_CLASS_ITEM; typedef struct st_CRYPTO_EX_DATA_IMPL CRYPTO_EX_DATA_IMPL; static const CRYPTO_EX_DATA_IMPL *impl = NULL; static LHASH *ex_data = NULL; struct st_CRYPTO_EX_DATA_IMPL { int (*cb_new_ex_data)(int class_index, void *obj, CRYPTO_EX_DATA *ad); void (*cb_free_ex_data)(int class_index, void *obj, CRYPTO_EX_DATA *ad); }; ///////////////////impl_default///////////// static int int_new_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad); static void int_free_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad); static CRYPTO_EX_DATA_IMPL impl_default = { int_new_ex_data, int_free_ex_data }; ///////////////ex_hash_cb//////////////////////ok static unsigned long ex_hash_cb(const void *a_void) { return ((const EX_CLASS_ITEM *)a_void)->class_index; } ///////////////ex_cmp_cb/////////////////////////////ok static int ex_cmp_cb(const void *a_void, const void *b_void) { return (((const EX_CLASS_ITEM *)a_void)->class_index - ((const EX_CLASS_ITEM *)b_void)->class_index); } ///////////IMPL_CHECK///////////////////////ok static void impl_check(void) { //CRYPTO_w_lock(CRYPTO_LOCK_EX_DATA); if(!impl) impl = &impl_default; //CRYPTO_w_unlock(CRYPTO_LOCK_EX_DATA); } ////////////////CRYPTO_new_ex_data/////////////////ok int CRYPTO_new_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad) { IMPL_CHECK return EX_IMPL(new_ex_data)(class_index, obj, ad); } /////////////////CRYPTO_free_ex_data///////////////////////////ok void CRYPTO_free_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad) { IMPL_CHECK EX_IMPL(free_ex_data)(class_index, obj, ad); } //////////bio_set////////////////////////ok int BIO_set(BIO *bio, BIO_METHOD *method) { bio->method=method; bio->callback=NULL; bio->cb_arg=NULL; bio->init=0; bio->shutdown=1; bio->flags=0; bio->retry_reason=0; bio->num=0; bio->ptr=NULL; bio->prev_bio=NULL; bio->next_bio=NULL; bio->references=1; bio->num_read=0L; bio->num_write=0L; CRYPTO_new_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data); if (method->create != NULL) if (!method->create(bio)) { CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data); return(0); } return(1); } /////////////////BI0_new//////////////ok BIO *BIO_new(BIO_METHOD *method) { BIO *ret=NULL; ret=(BIO *)OPENSSL_malloc(sizeof(BIO)); if (ret == NULL) { return(NULL); } if (!BIO_set(ret,method)) { OPENSSL_free(ret); ret=NULL; } return(ret); } ///////////////////def_get_class////////////////////////////////////////ok static EX_CLASS_ITEM *def_get_class(int class_index) { EX_CLASS_ITEM d, *p, *gen; EX_DATA_CHECK(return NULL;) d.class_index = class_index; //CRYPTO_w_lock(CRYPTO_LOCK_EX_DATA); p = lh_retrieve(ex_data, &d); if(!p) { gen = OPENSSL_malloc(sizeof(EX_CLASS_ITEM)); if(gen) { gen->class_index = class_index; gen->meth_num = 0; gen->meth = sk_CRYPTO_EX_DATA_FUNCS_new_null(); if(!gen->meth) OPENSSL_free(gen); else { lh_insert(ex_data, gen); p = gen; } } } //CRYPTO_w_unlock(CRYPTO_LOCK_EX_DATA); if(!p) CRYPTOerr(CRYPTO_F_DEF_GET_CLASS,ERR_R_MALLOC_FAILURE); return p; } ///////////////////int_new_ex_data/////////////////////////////////////////ok static int int_new_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad) { int mx,i; CRYPTO_EX_DATA_FUNCS **storage = NULL; EX_CLASS_ITEM *item = def_get_class(class_index); if(!item) /* error is already set */ return 0; ad->sk = NULL; //CRYPTO_r_lock(CRYPTO_LOCK_EX_DATA); mx = sk_CRYPTO_EX_DATA_FUNCS_num(item->meth); if(mx > 0) { storage = OPENSSL_malloc(mx * sizeof(CRYPTO_EX_DATA_FUNCS*)); if(!storage) goto skip; for(i = 0; i < mx; i++) storage[i] = sk_CRYPTO_EX_DATA_FUNCS_value(item->meth,i); } skip: //CRYPTO_r_unlock(CRYPTO_LOCK_EX_DATA); if((mx > 0) && !storage) { CRYPTOerr(CRYPTO_F_INT_NEW_EX_DATA,ERR_R_MALLOC_FAILURE); return 0; } for(i = 0; i < mx; i++) { if(storage[i] && storage[i]->new_func) { ; } } if(storage) OPENSSL_free(storage); return 1; } ////////////ex_data_check//////////////////////////////////////////ok static int ex_data_check(void) { int toret = 1; //CRYPTO_w_lock(CRYPTO_LOCK_EX_DATA); if(!ex_data && ((ex_data = lh_new(ex_hash_cb, ex_cmp_cb)) == NULL)) toret = 0; //CRYPTO_w_unlock(CRYPTO_LOCK_EX_DATA); return toret; } ///////////////int_free_ex_data/////////////////////////////////////////ok static void int_free_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad) { int mx,i; EX_CLASS_ITEM *item; CRYPTO_EX_DATA_FUNCS **storage = NULL; if((item = def_get_class(class_index)) == NULL) return; //CRYPTO_r_lock(CRYPTO_LOCK_EX_DATA); mx = sk_CRYPTO_EX_DATA_FUNCS_num(item->meth); if(mx > 0) { storage = OPENSSL_malloc(mx * sizeof(CRYPTO_EX_DATA_FUNCS*)); if(!storage) goto skip; for(i = 0; i < mx; i++) storage[i] = sk_CRYPTO_EX_DATA_FUNCS_value(item->meth,i); } skip: //CRYPTO_r_unlock(CRYPTO_LOCK_EX_DATA); if((mx > 0) && !storage) { CRYPTOerr(CRYPTO_F_INT_FREE_EX_DATA,ERR_R_MALLOC_FAILURE); return; } for(i = 0; i < mx; i++) { if(storage[i] && storage[i]->free_func) { ; } } if(storage) OPENSSL_free(storage); if(ad->sk) { sk_free(ad->sk); ad->sk=NULL; } } void reset_BIO_reset(void) { impl = NULL; ex_data = NULL; }