summaryrefslogtreecommitdiff
path: root/platform/src/key_keeper.cpp
diff options
context:
space:
mode:
author崔一鸣 <[email protected]>2018-09-07 17:42:57 +0800
committer崔一鸣 <[email protected]>2018-09-07 17:49:15 +0800
commitb5a937bad68eea51e0741dfd3275fe10cc2d02bd (patch)
treeda10667403513d655ab2cc90a1d52f5f3b2fbb8f /platform/src/key_keeper.cpp
parentb6a225078601fea5661b358155e678e6eb045b80 (diff)
fix memory leak bugs
Diffstat (limited to 'platform/src/key_keeper.cpp')
-rw-r--r--platform/src/key_keeper.cpp370
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;
-}
-
-
-