diff options
| author | 崔一鸣 <[email protected]> | 2018-09-07 17:42:57 +0800 |
|---|---|---|
| committer | 崔一鸣 <[email protected]> | 2018-09-07 17:49:15 +0800 |
| commit | b5a937bad68eea51e0741dfd3275fe10cc2d02bd (patch) | |
| tree | da10667403513d655ab2cc90a1d52f5f3b2fbb8f /platform/src/key_keeper.cpp | |
| parent | b6a225078601fea5661b358155e678e6eb045b80 (diff) | |
fix memory leak bugs
Diffstat (limited to 'platform/src/key_keeper.cpp')
| -rw-r--r-- | platform/src/key_keeper.cpp | 370 |
1 files changed, 234 insertions, 136 deletions
diff --git a/platform/src/key_keeper.cpp b/platform/src/key_keeper.cpp index 15a830e..aa163fd 100644 --- a/platform/src/key_keeper.cpp +++ b/platform/src/key_keeper.cpp @@ -6,15 +6,20 @@ #include "MESA/MESA_prof_load.h" #include "tfe_rpc.h" #include "event2/http.h" +#include "cjson/cJSON.h" #define HTABLE_MAX_KEY_LEN 256 #define KEYRING_EXSITED 0 #define KEYRING_NOT_EXSITED -1 struct key_keeper { - unsigned int mode; + char mode[TFE_STRING_MAX]; + char ca_path[TFE_STRING_MAX]; + char untrusted_ca_path[TFE_STRING_MAX]; char cert_store_host[TFE_STRING_MAX]; unsigned int cert_store_port; + unsigned int hash_slot_size; + unsigned int hash_expire_seconds; MESA_htable_handle htable; void* logger; }; @@ -35,11 +40,18 @@ struct key_keeper_promise_ctx { void* logger; MESA_htable_handle htable; - const uchar* key; + uchar* key; + struct future* f_certstore_rpc; unsigned int key_len; }; -static const uchar* get_key_by_cert(X509* cert, int keyring_id, unsigned int* len); +static void key_keeper_promise_free_ctx(void* ctx) +{ + struct key_keeper_promise_ctx* _ctx = (struct key_keeper_promise_ctx*)ctx; + free(_ctx->key); + _ctx->key = NULL; + free(_ctx); +} static struct keyring_private* keyring_new(void) { @@ -60,7 +72,7 @@ static struct keyring_private* keyring_new(void) * Passed OpenSSL objects are owned by cert_t; refcount will not be * incremented, stack will not be duplicated. */ -struct keyring* keyring_new3(EVP_PKEY *key, X509 *cert, STACK_OF(X509) *chain) +static struct keyring* keyring_new3(EVP_PKEY *key, X509 *cert, STACK_OF(X509) *chain) { struct keyring_private* kyr=NULL; kyr=keyring_new(); @@ -88,7 +100,7 @@ struct keyring* keyring_new3(EVP_PKEY *key, X509 *cert, STACK_OF(X509) *chain) } // Increment reference count. -void keyring_ref_inc(struct keyring_private* kyr) +static void keyring_ref_inc(struct keyring_private* kyr) { pthread_mutex_lock(&kyr->mutex); kyr->references++; @@ -183,9 +195,116 @@ void key_keeper_free_keyring(struct keyring *kyr) free(_kyr); } + +static X509* transform_cert_to_x509(const char* str) +{ + BIO *bio; + X509 *cert; + bio = BIO_new(BIO_s_mem()); + BIO_write(bio, (const void*)str, strnlen(str, TFE_STRING_MAX)); + cert = PEM_read_bio_X509(bio, NULL, NULL, NULL); + BIO_free_all(bio); + return cert; +} + +static EVP_PKEY* transform_key_to_EVP(const char* str) +{ + BIO *mem; + mem = BIO_new_mem_buf(str, -1); + EVP_PKEY* key = PEM_read_bio_PrivateKey(mem, NULL, NULL, 0); + BIO_free(mem); + return key; +} + + +static void err_out(X509* cert, EVP_PKEY* key, STACK_OF(X509)* chain) +{ + if(cert) + { + X509_free(cert); + } + if(key) + { + EVP_PKEY_free(key); + } + if(chain) + { + sk_X509_pop_free(chain, X509_free); + } + return; +} + +static struct keyring* get_keyring_from_response(const char* data) +{ + X509* cert = NULL; + EVP_PKEY* key = NULL; + STACK_OF(X509)* chain = NULL; + if(data == NULL) + { + return NULL; + } + cJSON* data_json = cJSON_Parse(data); + if(data_json == NULL) + { + return NULL; + } + cJSON* cert_json = NULL; + cJSON* key_json = NULL; + cJSON* chain_json = NULL; + cert_json = cJSON_GetObjectItemCaseSensitive(data_json, "CERTIFICATE"); + key_json = cJSON_GetObjectItemCaseSensitive(data_json, "PRIVATE_KEY"); + chain_json = cJSON_GetObjectItemCaseSensitive(data_json, "CERTIFICATE_CHAIN"); + if (cert_json && cert_json->valuestring != NULL) + { + cert = transform_cert_to_x509(cert_json->valuestring); + } + if(cert == NULL) + { + err_out(cert, key, chain); + return NULL; + } + if (key_json && key_json->valuestring != NULL) + { + key = transform_key_to_EVP(key_json->valuestring); + } + if(key == NULL) + { + err_out(cert, key, chain); + return NULL; + } + if(chain_json == NULL) + { + err_out(cert, key, chain); + return NULL; + } + cJSON* chain_cert_json = NULL; + chain = sk_X509_new_null(); + cJSON_ArrayForEach(chain_cert_json, chain_json) + { + X509* chain_cert = NULL; + if (chain_cert_json && chain_cert_json->valuestring != NULL) + { + chain_cert = transform_cert_to_x509(chain_cert_json->valuestring); + } + if(chain_cert == NULL) + { + err_out(cert, key, chain); + return NULL; + } + sk_X509_push(chain, chain_cert); + } + struct keyring_private* _kyr= keyring_new(); + keyring_set_cert(_kyr, cert); + keyring_set_key(_kyr, key); + keyring_set_chain(_kyr, chain); + X509_free(cert); + EVP_PKEY_free(key); + sk_X509_pop_free(chain, X509_free); + return &(_kyr->head); +} + static long keyring_local_cache_query_cb(void * data, const uchar * key, uint size, void * user_arg) { - //data is (struct keyring*) struct keyring_private* kyr=(struct keyring_private*)data; if(kyr == NULL) { @@ -198,11 +317,8 @@ static long keyring_local_cache_query_cb(void * data, const uchar * key, uint si return KEYRING_EXSITED; } } -static void certstore_rpc_on_fail(enum e_future_error err, const char * what, void * user) -{ - struct promise * p = (struct promise *) user; - promise_failed(p, err, what); -} + + static struct keyring_private* generate_x509_keyring(X509* origin_cert, int keyring_id, const char* filename) { X509* ca = ssl_x509_load(filename); @@ -212,97 +328,112 @@ static struct keyring_private* generate_x509_keyring(X509* origin_cert, int keyr STACK_OF(X509)* chain = sk_X509_new_null(); sk_X509_push(chain, ca); sk_X509_push(chain, forge_cert); - struct keyring_private* ring= keyring_new(); - keyring_set_key(ring, forge_key); - keyring_set_cert(ring, forge_cert); - keyring_set_chain(ring, chain); - return ring; -} -//how to free -static X509* get_cert_from_response(const char* data, int len, void* logger) -{ - BIO *bio; - X509 *cert; - bio = BIO_new(BIO_s_mem()); - BIO_write(bio, (const void*)data, len); - cert = PEM_read_bio_X509(bio, NULL, NULL, NULL); - return cert; -} - -static EVP_PKEY* get_key_from_response(const char* data, int len, void* logger) -{ - return NULL; -} - - -static STACK_OF(X509)* get_chain_from_response(const char* data, int len, void* logger) -{ - return NULL; + struct keyring_private* _kyr= keyring_new(); + keyring_set_key(_kyr, forge_key); + keyring_set_cert(_kyr, forge_cert); + keyring_set_chain(_kyr, chain); + X509_free(ca); + EVP_PKEY_free(cakey); + X509_free(forge_cert); + EVP_PKEY_free(forge_key); + sk_X509_pop_free(chain, X509_free); + return _kyr; } static void certstore_rpc_on_succ(void* result, void* user) { + //printf("call certstore_rpc_on_succ\n"); struct promise * p = (struct promise *) user; struct key_keeper_promise_ctx* ctx = (struct key_keeper_promise_ctx*)promise_get_ctx(p); MESA_htable_handle htable= ctx->htable; const uchar* key = ctx->key; unsigned int key_len = ctx->key_len; - //transform to x509 struct tfe_rpc_response_result* response = tfe_rpc_release(result); int status_code = response->status_code; const char* status_msg = response->status_msg; - const char* data = response->data; + char* data = response->data; int len = response->len; if(status_code == HTTP_OK) { - struct keyring_private* ring= keyring_new(); - X509* forge_cert = get_cert_from_response(data, len, NULL); - EVP_PKEY* forge_key = get_key_from_response(data, len, NULL); - STACK_OF(X509)* chain = get_chain_from_response(data, len, NULL); - keyring_set_key(ring, forge_key); - keyring_set_cert(ring, forge_cert); - keyring_set_chain(ring, chain); - promise_success(p, (void*)ring); - - int ret = MESA_htable_add(htable, key, key_len, (void*)ring); + *(data+len) = '\0'; + struct keyring* kyr= get_keyring_from_response(data); + promise_success(p, (void*)kyr); + int ret = MESA_htable_add(htable, key, key_len, (void*)kyr); if(ret<0) { - key_keeper_free_keyring((struct keyring*)ring); + key_keeper_free_keyring((struct keyring*)kyr); } } else { promise_failed(p, FUTURE_ERROR_EXCEPTION, status_msg); } + future_destroy(ctx->f_certstore_rpc); + //promise_dettach_ctx(p); + //ctx_destroy_cb((void*)ctx); } +static void certstore_rpc_on_fail(enum e_future_error err, const char * what, void * user) +{ + struct promise * p = (struct promise *) user; + promise_failed(p, err, what); + struct key_keeper_promise_ctx* ctx= (struct key_keeper_promise_ctx*)promise_get_ctx(p); + future_destroy(ctx->f_certstore_rpc); + //promise_dettach_ctx(p); + //ctx_destroy_cb((void*)ctx); +} -static int __wrapper_MESA_htable_set_opt(MESA_htable_handle table, enum MESA_htable_opt opt_type, unsigned int value); - -static MESA_htable_handle create_hash_table(unsigned int slot_size, unsigned int expire_seconds); - -static STACK_OF(X509)* get_chain_from_response(const char* data, int len, void* logger); /* * Certificate, including private key and keyring chain. */ +static int __wrapper_MESA_htable_set_opt(MESA_htable_handle table, enum MESA_htable_opt opt_type, unsigned int value) +{ + int ret = MESA_htable_set_opt(table, opt_type, &value, (int)(sizeof(value))); + assert(ret == 0); + return ret; +} +static MESA_htable_handle create_hash_table(unsigned int slot_size, unsigned int expire_seconds) +{ + int ret = 0; + unsigned max_num = slot_size * 4; + MESA_htable_handle htable = MESA_htable_born(); + ret = __wrapper_MESA_htable_set_opt(htable, MHO_SCREEN_PRINT_CTRL, 0); + ret = __wrapper_MESA_htable_set_opt(htable, MHO_THREAD_SAFE, 1); + ret = __wrapper_MESA_htable_set_opt(htable, MHO_MUTEX_NUM, 16); + ret = __wrapper_MESA_htable_set_opt(htable, MHO_HASH_SLOT_SIZE, slot_size); + ret = __wrapper_MESA_htable_set_opt(htable, MHO_HASH_MAX_ELEMENT_NUM, max_num); + ret = __wrapper_MESA_htable_set_opt(htable, MHO_EXPIRE_TIME, expire_seconds); + ret = __wrapper_MESA_htable_set_opt(htable, MHO_ELIMIMINATE_TYPE, + HASH_ELIMINATE_ALGO_FIFO); + //TODO: how to do overide? + //ret = __wrapper_MESA_htable_set_opt(htable, MHO_CBFUN_DATA_FREE, + // (void *)key_keeper_free_serialized); + //ret = __wrapper_MESA_htable_set_opt(htable, MHO_CBFUN_DATA_EXPIRE_NOTIFY, + // (void *)key_keeper_verify_cb); + ret = MESA_htable_mature(htable); + assert(ret == 0); + return htable; +} struct key_keeper* key_keeper_init(const char * profile, const char* section, void* logger) { - //load conf - //TODO free struct key_keeper* keeper = ALLOC(struct key_keeper, 1); keeper->logger = logger; - MESA_load_profile_uint_def(profile, section, "mode", &(keeper->mode), 1); + MESA_load_profile_string_def(profile, section, "mode", keeper->mode, sizeof(keeper->mode), "debug"); + MESA_load_profile_string_def(profile, section, "ca_path", keeper->ca_path, sizeof(keeper->ca_path), "./conf/mesalab-ca.pem"); + MESA_load_profile_string_def(profile, section, "untrusted_ca_path", keeper->untrusted_ca_path, sizeof(keeper->untrusted_ca_path), "./conf/mesalab-ca.pem"); MESA_load_profile_string_def(profile, section, "cert_store_host", keeper->cert_store_host, sizeof(keeper->cert_store_host), "xxxxx"); MESA_load_profile_uint_def(profile, section, "cert_store_port", &(keeper->cert_store_port), 80); - //TODO: argument - keeper->htable = create_hash_table(16,16); + MESA_load_profile_uint_def(profile, section, "hash_slot_size", &(keeper->hash_slot_size), 16); + MESA_load_profile_uint_def(profile, section, "hash_expire_seconds", &(keeper->hash_expire_seconds), 16); + keeper->htable = create_hash_table(keeper->hash_slot_size, keeper->hash_expire_seconds); return keeper; } void key_keeper_destroy(struct key_keeper *keeper) { + MESA_htable_destroy(keeper->htable, NULL); free(keeper); keeper = NULL; return; @@ -315,52 +446,76 @@ struct keyring* key_keeper_release_keyring(future_result_t* result) return &(kyr->head); } -static void ctx_destory_cb(struct promise* p) -{ +static uchar* get_key_by_cert(X509* cert, int keyring_id, unsigned int* len) +{ + char* cert_fgr = NULL; + cert_fgr = ssl_x509_fingerprint(cert, 0); + char* key = (char*)malloc(HTABLE_MAX_KEY_LEN); + *key = '\0'; + if(cert == NULL) + { + return NULL; + } + snprintf(key, HTABLE_MAX_KEY_LEN, "%d:", keyring_id); + strncat(key, cert_fgr, HTABLE_MAX_KEY_LEN); + *len = strnlen(key, HTABLE_MAX_KEY_LEN); + free(cert_fgr); + return (uchar*)key; } -//TODO: cert_not_valid + void key_keeper_async_ask(struct future * f, struct key_keeper * keeper, const char* sni, int keyring_id, X509 * origin_cert, int is_cert_valid, struct event_base * evbase) { - //get subject name from cert - - //current promise, belong to key_keeper struct promise* p = future_to_promise(f); struct key_keeper_promise_ctx* ctx = ALLOC(struct key_keeper_promise_ctx, 1); - //TODO free ctx!! unsigned int len = 0; - const uchar* key = get_key_by_cert(origin_cert, keyring_id, &len); + uchar* key = get_key_by_cert(origin_cert, keyring_id, &len); ctx->logger = keeper->logger; ctx->htable = keeper->htable; ctx->key = key; ctx->key_len = len; - promise_set_ctx(p, (void*)ctx, ctx_destory_cb); + promise_set_ctx(p, (void*)ctx, key_keeper_promise_free_ctx); long int cb_rtn = 0; MESA_htable_search_cb(ctx->htable, (const unsigned char*)(ctx->key), ctx->key_len, keyring_local_cache_query_cb, p, &cb_rtn); - printf(cb_rtn == KEYRING_EXSITED ? "KEYRING_EXSITED\n": "KEYRING_NOT_EXSITED\n"); if(cb_rtn == KEYRING_EXSITED) { + printf("KEYRING_EXSITED\n"); return; } - int mode = keeper->mode; - printf("mode is %s", mode == NORMAL ? "normal\n":"debug\n"); + int mode = 0; + if(strncmp(keeper->mode, "debug", TFE_STRING_MAX) == 0) + { + mode = 1; + } switch(mode){ case NORMAL: { - struct future* f_tfe_rpc = future_create("tfe_rpc", certstore_rpc_on_succ, certstore_rpc_on_fail, p); - //TODO: init in main()? store in ctx - struct tfe_rpc* rpc = tfe_rpc_init(NULL, NULL, keeper->logger); + struct future* f_certstore_rpc = future_create("tfe_rpc", certstore_rpc_on_succ, certstore_rpc_on_fail, p); + ctx->f_certstore_rpc = f_certstore_rpc; char url[TFE_STRING_MAX]; - const char host[] = "www.baidu.com"; - snprintf(url, TFE_STRING_MAX, "%s:%d?host=%s&flag=1&valid=1&kering_id=%d", keeper->cert_store_host, keeper->cert_store_port, host, keyring_id); - tfe_rpc_async_ask(f_tfe_rpc, rpc, url, GET, DONE_CB, NULL, 0, evbase); + char _sni[TFE_STRING_MAX] = "www.baidu.com"; + if(sni) + { + strncpy(_sni, sni, TFE_STRING_MAX); + } + snprintf(url, TFE_STRING_MAX, "http://%s:%d/ca?host=%s&flag=1&valid=1&keyring_id=%d", keeper->cert_store_host, keeper->cert_store_port, _sni, keyring_id); + printf("url is %s\n", url); + tfe_rpc_async_ask(f_certstore_rpc, url, GET, DONE_CB, NULL, 0, evbase); break; } case DEBUG: { //TOOD: generate X509 cert - const char* filename = "./conf/mesalab-ca.pem"; + char* filename = NULL; + if(is_cert_valid == 1) + { + filename = keeper->ca_path; + } + else + { + filename = keeper->untrusted_ca_path; + } struct keyring_private* ring = generate_x509_keyring(origin_cert, keyring_id, filename); if(ring) { @@ -370,10 +525,6 @@ void key_keeper_async_ask(struct future * f, struct key_keeper * keeper, const c { key_keeper_free_keyring((struct keyring*)ring); } - else - { - printf("key %s is added to hash table\n", ctx->key); - } } else { @@ -384,56 +535,3 @@ void key_keeper_async_ask(struct future * f, struct key_keeper * keeper, const c } return; } - - -static const uchar* -get_key_by_cert(X509* cert, int keyring_id, unsigned int* len) -{ - char* cert_fgr = NULL; - cert_fgr = ssl_x509_fingerprint(cert, 0); - char* key = (char*)malloc(HTABLE_MAX_KEY_LEN); - *key = '\0'; - if(cert == NULL) - { - return NULL; - } - snprintf(key, HTABLE_MAX_KEY_LEN, "%d:", keyring_id); - strncat(key, cert_fgr, HTABLE_MAX_KEY_LEN); - *len = strnlen(key, HTABLE_MAX_KEY_LEN); - return (const uchar*)key; -} - - -static int __wrapper_MESA_htable_set_opt(MESA_htable_handle table, enum MESA_htable_opt opt_type, unsigned int value) -{ - int ret = MESA_htable_set_opt(table, opt_type, &value, (int)(sizeof(value))); - assert(ret == 0); - return ret; -} - -static MESA_htable_handle -create_hash_table(unsigned int slot_size, unsigned int expire_seconds) -{ - int ret = 0; - unsigned max_num = slot_size * 4; - MESA_htable_handle htable = MESA_htable_born(); - ret = __wrapper_MESA_htable_set_opt(htable, MHO_SCREEN_PRINT_CTRL, 0); - ret = __wrapper_MESA_htable_set_opt(htable, MHO_THREAD_SAFE, 1); - ret = __wrapper_MESA_htable_set_opt(htable, MHO_MUTEX_NUM, 16); - ret = __wrapper_MESA_htable_set_opt(htable, MHO_HASH_SLOT_SIZE, slot_size); - ret = __wrapper_MESA_htable_set_opt(htable, MHO_HASH_MAX_ELEMENT_NUM, max_num); - ret = __wrapper_MESA_htable_set_opt(htable, MHO_EXPIRE_TIME, expire_seconds); - ret = __wrapper_MESA_htable_set_opt(htable, MHO_ELIMIMINATE_TYPE, - HASH_ELIMINATE_ALGO_FIFO); - //TODO: how to do overide? - //ret = __wrapper_MESA_htable_set_opt(htable, MHO_CBFUN_DATA_FREE, - // (void *)key_keeper_free_serialized); - //ret = __wrapper_MESA_htable_set_opt(htable, MHO_CBFUN_DATA_EXPIRE_NOTIFY, - // (void *)key_keeper_verify_cb); - ret = MESA_htable_mature(htable); - assert(ret == 0); - return htable; -} - - - |
