完成和key keeper的联调。

This commit is contained in:
zhengchao
2018-09-04 18:13:05 +08:00
parent 636e41cfca
commit af6340becf
7 changed files with 230 additions and 429 deletions

View File

@@ -10,6 +10,15 @@
#define KEYRING_EXSITED 0
#define KEYRING_NOT_EXSITED -1
struct key_keeper
{
unsigned int mode;
char cert_store_host[TFE_STRING_MAX];
unsigned int cert_store_port;
MESA_htable_handle htable;
void* logger;
};
enum KEY_KEEPER_MODE{
NORMAL = 0,
DEBUG,
@@ -32,64 +41,34 @@ struct key_keeper_promise_ctx
static const uchar* get_key_by_cert(X509* cert, int keyring_id, unsigned int* len);
static long htable_search_cb(void * data, const uchar * key, uint size, void * user_arg);
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 struct keyring* generate_x509_cert(X509* origin_cert, int keyring_id, const char* filename);
static void tfe_rpc_on_succ(void* result, void* user);
static void tfe_rpc_on_fail(enum e_future_error err, const char * what, void * user);
static void ctx_destory_cb(struct promise* p);
static X509* get_cert_from_response(const char* data, int len, void* logger);
static EVP_PKEY* get_key_from_response(const char* data, int len, void* logger);
static STACK_OF(X509)* get_chain_from_response(const char* data, int len, void* logger);
/*
* Certificate, including private key and keyring chain.
*/
struct keyring*
key_keeper_keyring_new(void)
static struct keyring_private* keyring_new(void)
{
struct keyring_private *keyring;
if (!(keyring = (struct keyring_private *)ALLOC(struct keyring_private, 1)))
struct keyring_private *kyr;
if (!(kyr = (struct keyring_private *)ALLOC(struct keyring_private, 1)))
{
return NULL;
}
if (pthread_mutex_init(&keyring->mutex, NULL)) {
free(keyring);
if (pthread_mutex_init(&kyr->mutex, NULL)) {
free(kyr);
return NULL;
}
keyring->references = 1;
return &(keyring->head);
kyr->references = 1;
return kyr;
}
/*
* Passed OpenSSL objects are owned by cert_t; refcount will not be
* incremented, stack will not be duplicated.
*/
struct keyring*
key_keeper_keyring_new3(EVP_PKEY *key, X509 *cert, STACK_OF(X509) *chain)
struct keyring* keyring_new3(EVP_PKEY *key, X509 *cert, STACK_OF(X509) *chain)
{
struct keyring_private* keyring;
if (!(keyring = (struct keyring_private *)ALLOC(struct keyring_private, 1)))
{
return NULL;
}
if (pthread_mutex_init(&keyring->mutex, NULL)) {
free(keyring);
return NULL;
}
keyring->references = 1;
(keyring->head).key = key;
(keyring->head).cert = cert;
(keyring->head).chain = chain;
struct keyring_private* kyr=NULL;
kyr=keyring_new();
kyr->references = 1;
(kyr->head).key = key;
(kyr->head).cert = cert;
(kyr->head).chain = chain;
if(key)
{
ssl_key_refcount_inc(key);
@@ -105,111 +84,213 @@ key_keeper_keyring_new3(EVP_PKEY *key, X509 *cert, STACK_OF(X509) *chain)
ssl_x509_refcount_inc(sk_X509_value(chain, i));
}
}
return &(keyring->head);
return &(kyr->head);
}
// Increment reference count.
void
key_keeper_keyring_refcount_inc(struct keyring* ring)
void keyring_ref_inc(struct keyring_private* kyr)
{
struct keyring_private* keyring = (struct keyring_private*)ring;
pthread_mutex_lock(&keyring->mutex);
keyring->references++;
pthread_mutex_unlock(&keyring->mutex);
pthread_mutex_lock(&kyr->mutex);
kyr->references++;
pthread_mutex_unlock(&kyr->mutex);
}
/*
* Thread-safe setter functions; they copy the value (refcounts are inc'd).
*/
void
key_keeper_keyring_set_key(struct keyring* ring, EVP_PKEY *key)
static void keyring_set_key(struct keyring_private* kyr, EVP_PKEY *key)
{
struct keyring_private* keyring = (struct keyring_private*)ring;
pthread_mutex_lock(&keyring->mutex);
if ((keyring->head).key)
pthread_mutex_lock(&kyr->mutex);
if ((kyr->head).key)
{
EVP_PKEY_free((keyring->head).key);
EVP_PKEY_free((kyr->head).key);
}
(keyring->head).key = key;
(kyr->head).key = key;
if (key)
{
ssl_key_refcount_inc((keyring->head).key);
ssl_key_refcount_inc((kyr->head).key);
}
pthread_mutex_unlock(&keyring->mutex);
pthread_mutex_unlock(&kyr->mutex);
}
void
key_keeper_keyring_set_cert(struct keyring* ring, X509 *cert)
static void keyring_set_cert(struct keyring_private* kry, X509 *cert)
{
struct keyring_private* keyring = (struct keyring_private*)ring;
pthread_mutex_lock(&keyring->mutex);
if ((keyring->head).cert)
pthread_mutex_lock(&kry->mutex);
if ((kry->head).cert)
{
X509_free((keyring->head).cert);
X509_free((kry->head).cert);
}
(keyring->head).cert = cert;
(kry->head).cert = cert;
if (cert)
{
ssl_x509_refcount_inc((keyring->head).cert);
ssl_x509_refcount_inc((kry->head).cert);
}
pthread_mutex_unlock(&keyring->mutex);
pthread_mutex_unlock(&kry->mutex);
}
void
key_keeper_keyring_set_chain(struct keyring* ring, STACK_OF(X509) *chain)
static void keyring_set_chain(struct keyring_private* kyr, STACK_OF(X509) *chain)
{
struct keyring_private* keyring = (struct keyring_private*)ring;
pthread_mutex_lock(&keyring->mutex);
if ((keyring->head).chain)
pthread_mutex_lock(&kyr->mutex);
if ((kyr->head).chain)
{
sk_X509_pop_free((keyring->head).chain, X509_free);
sk_X509_pop_free((kyr->head).chain, X509_free);
}
if (chain)
{
(keyring->head).chain = sk_X509_dup(chain);
(kyr->head).chain = sk_X509_dup(chain);
int i = 0;
for (i = 0; i < sk_X509_num((keyring->head).chain); i++)
for (i = 0; i < sk_X509_num((kyr->head).chain); i++)
{
ssl_x509_refcount_inc(sk_X509_value((keyring->head).chain, i));
ssl_x509_refcount_inc(sk_X509_value((kyr->head).chain, i));
}
} else
{
(keyring->head).chain = NULL;
(kyr->head).chain = NULL;
}
pthread_mutex_unlock(&keyring->mutex);
pthread_mutex_unlock(&kyr->mutex);
}
/*
* Free keyring including internal objects.
*/
void
key_keeper_free_keyring(struct keyring *ring)
void key_keeper_free_keyring(struct keyring *kyr)
{
struct keyring_private* keyring = (struct keyring_private*)ring;
pthread_mutex_lock(&keyring->mutex);
keyring->references--;
if (keyring->references)
struct keyring_private* _kyr = (struct keyring_private*)kyr;
pthread_mutex_lock(&_kyr->mutex);
_kyr->references--;
if (_kyr->references>0)
{
pthread_mutex_unlock(&keyring->mutex);
pthread_mutex_unlock(&_kyr->mutex);
return;
}
pthread_mutex_unlock(&keyring->mutex);
pthread_mutex_destroy(&keyring->mutex);
if ((keyring->head).key)
pthread_mutex_unlock(&_kyr->mutex);
pthread_mutex_destroy(&_kyr->mutex);
if ((_kyr->head).key)
{
EVP_PKEY_free((keyring->head).key);
EVP_PKEY_free((_kyr->head).key);
(_kyr->head).key=NULL;
}
if ((keyring->head).cert)
if ((_kyr->head).cert)
{
X509_free((keyring->head).cert);
X509_free((_kyr->head).cert);
(_kyr->head).cert=NULL;
}
if ((keyring->head).chain)
if ((_kyr->head).chain)
{
sk_X509_pop_free((keyring->head).chain, X509_free);
sk_X509_pop_free((_kyr->head).chain, X509_free);
(_kyr->head).chain=NULL;
}
free(keyring);
free(_kyr);
}
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)
{
return KEYRING_NOT_EXSITED;
}
else
{
struct promise* p = (struct promise*)user_arg;
promise_success(p, data);
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);
EVP_PKEY* cakey = ssl_key_load(filename);
EVP_PKEY* forge_key = ssl_key_genrsa(1024);
X509* forge_cert = ssl_x509_forge(ca, cakey, origin_cert, forge_key, NULL, NULL);
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)
{
}
static STACK_OF(X509)* get_chain_from_response(const char* data, int len, void* logger)
{
}
static void certstore_rpc_on_succ(void* result, void* user)
{
struct promise * p = (struct promise *) user;
struct key_keeper_promise_ctx* ctx = (struct key_keeper_promise_ctx*)promise_get_ctx(p);
void* logger = ctx->logger;
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;
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);
keyring_ref_inc(ring);
int ret = MESA_htable_add(htable, key, key_len, (void*)ring);
if(ret<0)
{
key_keeper_free_keyring((struct keyring*)ring);
}
}
else
{
promise_failed(p, FUTURE_ERROR_EXCEPTION, status_msg);
}
}
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 void key_keeper_free_serialized()
{
return;
@@ -235,79 +316,22 @@ key_keeper_init(const char * profile, const char* section, void* logger)
return keeper;
}
//return void ??
struct key_keeper *
key_keeper_destroy(struct key_keeper *keeper)
void key_keeper_destroy(struct key_keeper *keeper)
{
free(keeper);
keeper = NULL;
return keeper;
return;
}
struct keyring*
key_keeper_release_cert(future_result_t* result)
struct keyring* key_keeper_release_keyring(future_result_t* result)
{
return (struct keyring*)result;
}
static struct keyring*
generate_x509_cert(X509* origin_cert, int keyring_id, const char* filename)
{
X509* ca = ssl_x509_load(filename);
EVP_PKEY* cakey = ssl_key_load(filename);
EVP_PKEY* forge_key = ssl_key_genrsa(1024);
X509* forge_cert = ssl_x509_forge(ca, cakey, origin_cert, forge_key, NULL, NULL);
STACK_OF(X509)* chain = sk_X509_new_null();
sk_X509_push(chain, ca);
sk_X509_push(chain, forge_cert);
struct keyring* ring= key_keeper_keyring_new();
key_keeper_keyring_set_key(ring, forge_key);
key_keeper_keyring_set_cert(ring, forge_cert);
key_keeper_keyring_set_chain(ring, chain);
return ring;
}
static void
tfe_rpc_on_succ(void* result, void* user)
{
struct promise * p = (struct promise *) user;
struct key_keeper_promise_ctx* ctx = (struct key_keeper_promise_ctx*)promise_get_ctx(p);
void* logger = ctx->logger;
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;
int len = response->len;
if(status_code == HTTP_OK)
{
struct keyring* ring= key_keeper_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);
key_keeper_keyring_set_key(ring, forge_key);
key_keeper_keyring_set_cert(ring, forge_cert);
key_keeper_keyring_set_chain(ring, chain);
promise_success(p, (void*)ring);
int ret = MESA_htable_add(htable, key, key_len, (void*)ring);
assert(ret >= 0);
}
else
{
promise_failed(p, FUTURE_ERROR_EXCEPTION, status_msg);
}
struct keyring_private* kyr=(struct keyring_private*)result;
keyring_ref_inc(kyr);
return &(kyr->head);
}
static void
tfe_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 void ctx_destory_cb(struct promise* p)
@@ -316,7 +340,7 @@ static void ctx_destory_cb(struct promise* p)
}
//TODO: cert_not_valid
void key_keeper_async_ask(struct future * f, struct key_keeper * keeper, int keyring_id, X509 * origin_cert, int is_cert_valid, struct event_base * evbase)
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
@@ -331,7 +355,7 @@ void key_keeper_async_ask(struct future * f, struct key_keeper * keeper, int key
ctx->key_len = len;
promise_set_ctx(p, (void*)ctx, ctx_destory_cb);
long int cb_rtn = 0;
MESA_htable_search_cb(ctx->htable, (const unsigned char*)(ctx->key), ctx->key_len, htable_search_cb, p, &cb_rtn);
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)
{
@@ -342,7 +366,7 @@ void key_keeper_async_ask(struct future * f, struct key_keeper * keeper, int key
switch(mode){
case NORMAL:
{
struct future* f_tfe_rpc = future_create("tfe_rpc", tfe_rpc_on_succ, tfe_rpc_on_fail, p);
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);
char url[TFE_STRING_MAX];
@@ -355,13 +379,21 @@ void key_keeper_async_ask(struct future * f, struct key_keeper * keeper, int key
{
//TOOD: generate X509 cert
const char* filename = "./conf/mesalab-ca.pem";
struct keyring* ring = generate_x509_cert(origin_cert, keyring_id, filename);
struct keyring_private* ring = generate_x509_keyring(origin_cert, keyring_id, filename);
if(ring)
{
keyring_ref_inc(ring);
int ret = MESA_htable_add(ctx->htable, ctx->key, ctx->key_len, (void*)ring);
assert(ret >= 0);
printf("key %s is added to hash table\n", ctx->key);
if(ret<0)
{
key_keeper_free_keyring((struct keyring*)ring);
}
else
{
printf("key %s is added to hash table\n", ctx->key);
}
promise_success(p, (void*)ring);
key_keeper_free_keyring((struct keyring*)ring);
}
else
{
@@ -373,21 +405,6 @@ void key_keeper_async_ask(struct future * f, struct key_keeper * keeper, int key
return;
}
static long
htable_search_cb(void * data, const uchar * key, uint size, void * user_arg)
{
//data is (struct keyring*)
if(data == NULL)
{
return KEYRING_NOT_EXSITED;
}
else
{
struct promise* p = (struct promise*)user_arg;
promise_success(p, data);
return KEYRING_EXSITED;
}
}
static const uchar*
get_key_by_cert(X509* cert, int keyring_id, unsigned int* len)
@@ -438,201 +455,5 @@ create_hash_table(unsigned int slot_size, unsigned int expire_seconds)
return htable;
}
//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)
{
}
static STACK_OF(X509)*
get_chain_from_response(const char* data, int len, void* logger)
{
}
/*
* Passed OpenSSL objects are copied by cert_t; crt/key refcount will be
* incremented, stack will be duplicated.
* /
cert_t *cert_new3_copy(EVP_PKEY *key, X509 *crt, STACK_OF(X509) *chain)
{
cert_t *c;
if (!(c = (cert_t *)malloc(sizeof(cert_t))))
return NULL;
if (pthread_mutex_init(&c->mutex, NULL)) {
free(c);
return NULL;
}
c->key = key;
ssl_key_refcount_inc(c->key);
c->crt = crt;
ssl_x509_refcount_inc(c->crt);
c->chain = sk_X509_dup(chain);
for (int i = 0; i < sk_X509_num(c->chain); i++) {
ssl_x509_refcount_inc(sk_X509_value(c->chain, i));
}
c->references = 1;
return c;
}
*/
/*
* Load cert_t from file.
* /
cert_t *cert_new_load(const char *filename)
{
cert_t *c;
if (!(c = (cert_t *)malloc(sizeof(cert_t))))
return NULL;
memset(c, 0, sizeof(cert_t));
if (pthread_mutex_init(&c->mutex, NULL)) {
free(c);
return NULL;
}
if (ssl_x509chain_load(&c->crt, &c->chain, filename) == -1) {
free(c);
return NULL;
}
c->key = ssl_key_load(filename);
if (!c->key) {
X509_free(c->crt);
if (c->chain) {
sk_X509_pop_free(c->chain, X509_free);
}
free(c);
return NULL;
}
c->references = 1;
return c;
}
*/
/*
void key_keeper_async_ask(struct future * f, struct key_keeper * keeper, int keyring_id,
X509 * origin_cert, int is_cert_valid, struct event_base * evbase)
{
X509* orig_cert=SSL_get_peer_certificate(origssl);
//todo: need implement
cert_t * keyring = NULL;
if (opts->tgcrtdir)
{
if (ctx->sni)
{
keyring = (cert_t *) cachemgr_tgcrt_get(ctx->sni);
if (!keyring)
{
char * wildcarded = ssl_wildcardify(ctx->sni);
if (!wildcarded)
{
ctx->enomem = 1;
return NULL;
}
keyring = (cert_t *) cachemgr_tgcrt_get(wildcarded);
free(wildcarded);
}
if (keyring && OPTS_DEBUG(ctx->opts))
{
log_dbg_printf("Target keyring by SNI\n");
}
}
else if (ctx->origcrt)
{
char ** names = ssl_x509_names(ctx->origcrt);
for (char ** p = names; *p; p++)
{
if (!keyring)
{
keyring = (cert_t *) cachemgr_tgcrt_get(*p);
}
if (!keyring)
{
char * wildcarded = ssl_wildcardify(*p);
if (!wildcarded)
{
ctx->enomem = 1;
}
else
{
keyring = (cert_t *) (wildcarded);
free(wildcarded);
}
}
free(*p);
}
free(names);
if (ctx->enomem)
{
return NULL;
}
if (keyring && OPTS_DEBUG(ctx->opts))
{
log_dbg_printf("Target keyring by origcrt\n");
}
}
if (keyring)
{
ctx->immutable_cert = 1;
}
}
if (!keyring && ctx->origcrt && ctx->opts->key)
{
keyring = cert_new();
keyring->cert = (X509 *) cachemgr_fkcrt_get(ctx->origcrt);
if (keyring->cert)
{
if (OPTS_DEBUG(ctx->opts)) log_dbg_printf("Certificate cache: HIT\n");
}
else
{
if (OPTS_DEBUG(ctx->opts)) log_dbg_printf("Certificate cache: MISS\n");
keyring->cert = ssl_x509_forge(ctx->opts->cacrt,
ctx->opts->cakey,
ctx->origcrt,
ctx->opts->key,
NULL,
ctx->opts->crlurl);
cachemgr_fkcrt_set(ctx->origcrt, keyring->cert);
}
cert_set_key(keyring, ctx->opts->key);
cert_set_chain(keyring, ctx->opts->chain);
ctx->generated_cert = 1;
}
if ((WANT_CONNECT_LOG(ctx) || ctx->opts->certgendir) && ctx->origcrt)
{
ctx->origcrtfpr = ssl_x509_fingerprint(ctx->origcrt, 0);
if (!ctx->origcrtfpr)
ctx->enomem = 1;
}
if ((WANT_CONNECT_LOG(ctx) || ctx->opts->certgen_writeall) &&
keyring && keyring->cert)
{
ctx->usedcrtfpr = ssl_x509_fingerprint(keyring->cert, 0);
if (!ctx->usedcrtfpr)
ctx->enomem = 1;
}
return keyring;
}
*/