2018-09-04 15:47:41 +08:00
|
|
|
#include "key_keeper.h"
|
2018-08-14 19:44:34 +08:00
|
|
|
#include <string.h>
|
2018-09-04 15:47:41 +08:00
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <assert.h>
|
|
|
|
|
#include "MESA/MESA_prof_load.h"
|
|
|
|
|
#include "tfe_rpc.h"
|
|
|
|
|
#include "event2/http.h"
|
|
|
|
|
#define HTABLE_MAX_KEY_LEN 256
|
|
|
|
|
#define KEYRING_EXSITED 0
|
|
|
|
|
#define KEYRING_NOT_EXSITED -1
|
2018-08-23 19:46:38 +08:00
|
|
|
|
2018-09-04 15:47:41 +08:00
|
|
|
enum KEY_KEEPER_MODE{
|
|
|
|
|
NORMAL = 0,
|
|
|
|
|
DEBUG,
|
2018-08-23 19:46:38 +08:00
|
|
|
};
|
2018-09-04 15:47:41 +08:00
|
|
|
|
|
|
|
|
struct keyring_private
|
2018-08-23 19:46:38 +08:00
|
|
|
{
|
2018-08-26 18:26:24 +08:00
|
|
|
struct keyring head;
|
2018-08-23 19:46:38 +08:00
|
|
|
pthread_mutex_t mutex;
|
|
|
|
|
size_t references;
|
|
|
|
|
};
|
|
|
|
|
|
2018-09-04 15:47:41 +08:00
|
|
|
struct key_keeper_promise_ctx
|
|
|
|
|
{
|
|
|
|
|
void* logger;
|
|
|
|
|
MESA_htable_handle htable;
|
|
|
|
|
const uchar* key;
|
|
|
|
|
unsigned int key_len;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
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);
|
2018-08-14 19:44:34 +08:00
|
|
|
/*
|
2018-08-26 18:26:24 +08:00
|
|
|
* Certificate, including private key and keyring chain.
|
2018-08-14 19:44:34 +08:00
|
|
|
*/
|
2018-09-04 15:47:41 +08:00
|
|
|
struct keyring*
|
|
|
|
|
key_keeper_keyring_new(void)
|
2018-08-14 19:44:34 +08:00
|
|
|
{
|
2018-09-04 15:47:41 +08:00
|
|
|
struct keyring_private *keyring;
|
|
|
|
|
if (!(keyring = (struct keyring_private *)ALLOC(struct keyring_private, 1)))
|
|
|
|
|
{
|
2018-08-14 19:44:34 +08:00
|
|
|
return NULL;
|
2018-09-04 15:47:41 +08:00
|
|
|
}
|
|
|
|
|
if (pthread_mutex_init(&keyring->mutex, NULL)) {
|
|
|
|
|
free(keyring);
|
2018-08-14 19:44:34 +08:00
|
|
|
return NULL;
|
|
|
|
|
}
|
2018-09-04 15:47:41 +08:00
|
|
|
keyring->references = 1;
|
|
|
|
|
return &(keyring->head);
|
2018-08-14 19:44:34 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Passed OpenSSL objects are owned by cert_t; refcount will not be
|
|
|
|
|
* incremented, stack will not be duplicated.
|
|
|
|
|
*/
|
2018-09-04 15:47:41 +08:00
|
|
|
struct keyring*
|
|
|
|
|
key_keeper_keyring_new3(EVP_PKEY *key, X509 *cert, STACK_OF(X509) *chain)
|
2018-08-14 19:44:34 +08:00
|
|
|
{
|
2018-09-04 15:47:41 +08:00
|
|
|
struct keyring_private* keyring;
|
|
|
|
|
if (!(keyring = (struct keyring_private *)ALLOC(struct keyring_private, 1)))
|
|
|
|
|
{
|
2018-08-14 19:44:34 +08:00
|
|
|
return NULL;
|
2018-09-04 15:47:41 +08:00
|
|
|
}
|
|
|
|
|
if (pthread_mutex_init(&keyring->mutex, NULL)) {
|
|
|
|
|
free(keyring);
|
2018-08-14 19:44:34 +08:00
|
|
|
return NULL;
|
|
|
|
|
}
|
2018-09-04 15:47:41 +08:00
|
|
|
keyring->references = 1;
|
|
|
|
|
(keyring->head).key = key;
|
|
|
|
|
(keyring->head).cert = cert;
|
|
|
|
|
(keyring->head).chain = chain;
|
|
|
|
|
if(key)
|
|
|
|
|
{
|
|
|
|
|
ssl_key_refcount_inc(key);
|
|
|
|
|
}
|
|
|
|
|
if(cert)
|
|
|
|
|
{
|
|
|
|
|
ssl_x509_refcount_inc(cert);
|
|
|
|
|
}
|
|
|
|
|
if(chain){
|
|
|
|
|
int i = 0;
|
|
|
|
|
for (i = 0; i < sk_X509_num(chain); i++)
|
|
|
|
|
{
|
|
|
|
|
ssl_x509_refcount_inc(sk_X509_value(chain, i));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return &(keyring->head);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Increment reference count.
|
|
|
|
|
void
|
|
|
|
|
key_keeper_keyring_refcount_inc(struct keyring* ring)
|
|
|
|
|
{
|
|
|
|
|
struct keyring_private* keyring = (struct keyring_private*)ring;
|
|
|
|
|
pthread_mutex_lock(&keyring->mutex);
|
|
|
|
|
keyring->references++;
|
|
|
|
|
pthread_mutex_unlock(&keyring->mutex);
|
2018-08-14 19:44:34 +08:00
|
|
|
}
|
|
|
|
|
|
2018-09-04 15:47:41 +08:00
|
|
|
/*
|
|
|
|
|
* Thread-safe setter functions; they copy the value (refcounts are inc'd).
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
key_keeper_keyring_set_key(struct keyring* ring, EVP_PKEY *key)
|
|
|
|
|
{
|
|
|
|
|
struct keyring_private* keyring = (struct keyring_private*)ring;
|
|
|
|
|
pthread_mutex_lock(&keyring->mutex);
|
|
|
|
|
if ((keyring->head).key)
|
|
|
|
|
{
|
|
|
|
|
EVP_PKEY_free((keyring->head).key);
|
|
|
|
|
}
|
|
|
|
|
(keyring->head).key = key;
|
|
|
|
|
if (key)
|
|
|
|
|
{
|
|
|
|
|
ssl_key_refcount_inc((keyring->head).key);
|
|
|
|
|
}
|
|
|
|
|
pthread_mutex_unlock(&keyring->mutex);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
key_keeper_keyring_set_cert(struct keyring* ring, X509 *cert)
|
|
|
|
|
{
|
|
|
|
|
struct keyring_private* keyring = (struct keyring_private*)ring;
|
|
|
|
|
pthread_mutex_lock(&keyring->mutex);
|
|
|
|
|
if ((keyring->head).cert)
|
|
|
|
|
{
|
|
|
|
|
X509_free((keyring->head).cert);
|
|
|
|
|
}
|
|
|
|
|
(keyring->head).cert = cert;
|
|
|
|
|
if (cert)
|
|
|
|
|
{
|
|
|
|
|
ssl_x509_refcount_inc((keyring->head).cert);
|
|
|
|
|
}
|
|
|
|
|
pthread_mutex_unlock(&keyring->mutex);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
key_keeper_keyring_set_chain(struct keyring* ring, STACK_OF(X509) *chain)
|
|
|
|
|
{
|
|
|
|
|
struct keyring_private* keyring = (struct keyring_private*)ring;
|
|
|
|
|
pthread_mutex_lock(&keyring->mutex);
|
|
|
|
|
if ((keyring->head).chain)
|
|
|
|
|
{
|
|
|
|
|
sk_X509_pop_free((keyring->head).chain, X509_free);
|
|
|
|
|
}
|
|
|
|
|
if (chain)
|
|
|
|
|
{
|
|
|
|
|
(keyring->head).chain = sk_X509_dup(chain);
|
|
|
|
|
int i = 0;
|
|
|
|
|
for (i = 0; i < sk_X509_num((keyring->head).chain); i++)
|
|
|
|
|
{
|
|
|
|
|
ssl_x509_refcount_inc(sk_X509_value((keyring->head).chain, i));
|
|
|
|
|
}
|
|
|
|
|
} else
|
|
|
|
|
{
|
|
|
|
|
(keyring->head).chain = NULL;
|
|
|
|
|
}
|
|
|
|
|
pthread_mutex_unlock(&keyring->mutex);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Free keyring including internal objects.
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
key_keeper_free_keyring(struct keyring *ring)
|
|
|
|
|
{
|
|
|
|
|
struct keyring_private* keyring = (struct keyring_private*)ring;
|
|
|
|
|
pthread_mutex_lock(&keyring->mutex);
|
|
|
|
|
keyring->references--;
|
|
|
|
|
if (keyring->references)
|
|
|
|
|
{
|
|
|
|
|
pthread_mutex_unlock(&keyring->mutex);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
pthread_mutex_unlock(&keyring->mutex);
|
|
|
|
|
pthread_mutex_destroy(&keyring->mutex);
|
|
|
|
|
if ((keyring->head).key)
|
|
|
|
|
{
|
|
|
|
|
EVP_PKEY_free((keyring->head).key);
|
|
|
|
|
}
|
|
|
|
|
if ((keyring->head).cert)
|
|
|
|
|
{
|
|
|
|
|
X509_free((keyring->head).cert);
|
|
|
|
|
}
|
|
|
|
|
if ((keyring->head).chain)
|
|
|
|
|
{
|
|
|
|
|
sk_X509_pop_free((keyring->head).chain, X509_free);
|
|
|
|
|
}
|
|
|
|
|
free(keyring);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void key_keeper_free_serialized()
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void key_keeper_verify_cb()
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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, "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);
|
|
|
|
|
return keeper;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//return void ??
|
|
|
|
|
struct key_keeper *
|
|
|
|
|
key_keeper_destroy(struct key_keeper *keeper)
|
|
|
|
|
{
|
|
|
|
|
free(keeper);
|
|
|
|
|
keeper = NULL;
|
|
|
|
|
return keeper;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct keyring*
|
|
|
|
|
key_keeper_release_cert(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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//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)
|
|
|
|
|
{
|
|
|
|
|
//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);
|
|
|
|
|
unsigned int len = 0;
|
|
|
|
|
const 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);
|
|
|
|
|
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);
|
|
|
|
|
printf(cb_rtn == KEYRING_EXSITED ? "KEYRING_EXSITED\n": "KEYRING_NOT_EXSITED\n");
|
|
|
|
|
if(cb_rtn == KEYRING_EXSITED)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
int mode = keeper->mode;
|
|
|
|
|
printf("mode is %s", mode == NORMAL ? "normal\n":"debug\n");
|
|
|
|
|
switch(mode){
|
|
|
|
|
case NORMAL:
|
|
|
|
|
{
|
|
|
|
|
struct future* f_tfe_rpc = future_create("tfe_rpc", tfe_rpc_on_succ, tfe_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];
|
|
|
|
|
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);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case DEBUG:
|
|
|
|
|
{
|
|
|
|
|
//TOOD: generate X509 cert
|
|
|
|
|
const char* filename = "./conf/mesalab-ca.pem";
|
|
|
|
|
struct keyring* ring = generate_x509_cert(origin_cert, keyring_id, filename);
|
|
|
|
|
if(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);
|
|
|
|
|
promise_success(p, (void*)ring);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
promise_failed(p, FUTURE_ERROR_EXCEPTION, "generate X509 cert failed");
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
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)
|
|
|
|
|
{
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//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)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
}
|
2018-08-14 19:44:34 +08:00
|
|
|
/*
|
|
|
|
|
* Passed OpenSSL objects are copied by cert_t; crt/key refcount will be
|
|
|
|
|
* incremented, stack will be duplicated.
|
2018-09-04 15:47:41 +08:00
|
|
|
* /
|
|
|
|
|
cert_t *cert_new3_copy(EVP_PKEY *key, X509 *crt, STACK_OF(X509) *chain)
|
2018-08-14 19:44:34 +08:00
|
|
|
{
|
|
|
|
|
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;
|
|
|
|
|
}
|
2018-09-04 15:47:41 +08:00
|
|
|
*/
|
2018-08-14 19:44:34 +08:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Load cert_t from file.
|
2018-09-04 15:47:41 +08:00
|
|
|
* /
|
|
|
|
|
cert_t *cert_new_load(const char *filename)
|
2018-08-14 19:44:34 +08:00
|
|
|
{
|
|
|
|
|
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;
|
|
|
|
|
}
|
2018-09-04 15:47:41 +08:00
|
|
|
*/
|
2018-08-14 19:44:34 +08:00
|
|
|
|
|
|
|
|
/*
|
2018-09-04 15:47:41 +08:00
|
|
|
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)
|
2018-08-14 19:44:34 +08:00
|
|
|
{
|
|
|
|
|
X509* orig_cert=SSL_get_peer_certificate(origssl);
|
2018-09-04 15:47:41 +08:00
|
|
|
//todo: need implement
|
2018-08-26 18:26:24 +08:00
|
|
|
cert_t * keyring = NULL;
|
2018-08-14 19:44:34 +08:00
|
|
|
if (opts->tgcrtdir)
|
|
|
|
|
{
|
|
|
|
|
if (ctx->sni)
|
|
|
|
|
{
|
2018-08-26 18:26:24 +08:00
|
|
|
keyring = (cert_t *) cachemgr_tgcrt_get(ctx->sni);
|
|
|
|
|
if (!keyring)
|
2018-08-14 19:44:34 +08:00
|
|
|
{
|
|
|
|
|
char * wildcarded = ssl_wildcardify(ctx->sni);
|
|
|
|
|
if (!wildcarded)
|
|
|
|
|
{
|
|
|
|
|
ctx->enomem = 1;
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
2018-08-26 18:26:24 +08:00
|
|
|
keyring = (cert_t *) cachemgr_tgcrt_get(wildcarded);
|
2018-08-14 19:44:34 +08:00
|
|
|
free(wildcarded);
|
|
|
|
|
}
|
2018-08-26 18:26:24 +08:00
|
|
|
if (keyring && OPTS_DEBUG(ctx->opts))
|
2018-08-14 19:44:34 +08:00
|
|
|
{
|
2018-08-26 18:26:24 +08:00
|
|
|
log_dbg_printf("Target keyring by SNI\n");
|
2018-08-14 19:44:34 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (ctx->origcrt)
|
|
|
|
|
{
|
|
|
|
|
char ** names = ssl_x509_names(ctx->origcrt);
|
|
|
|
|
for (char ** p = names; *p; p++)
|
|
|
|
|
{
|
2018-08-26 18:26:24 +08:00
|
|
|
if (!keyring)
|
2018-08-14 19:44:34 +08:00
|
|
|
{
|
2018-08-26 18:26:24 +08:00
|
|
|
keyring = (cert_t *) cachemgr_tgcrt_get(*p);
|
2018-08-14 19:44:34 +08:00
|
|
|
}
|
2018-08-26 18:26:24 +08:00
|
|
|
if (!keyring)
|
2018-08-14 19:44:34 +08:00
|
|
|
{
|
|
|
|
|
char * wildcarded = ssl_wildcardify(*p);
|
|
|
|
|
if (!wildcarded)
|
|
|
|
|
{
|
|
|
|
|
ctx->enomem = 1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2018-08-26 18:26:24 +08:00
|
|
|
keyring = (cert_t *) (wildcarded);
|
2018-08-14 19:44:34 +08:00
|
|
|
free(wildcarded);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
free(*p);
|
|
|
|
|
}
|
|
|
|
|
free(names);
|
|
|
|
|
if (ctx->enomem)
|
|
|
|
|
{
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
2018-08-26 18:26:24 +08:00
|
|
|
if (keyring && OPTS_DEBUG(ctx->opts))
|
2018-08-14 19:44:34 +08:00
|
|
|
{
|
2018-08-26 18:26:24 +08:00
|
|
|
log_dbg_printf("Target keyring by origcrt\n");
|
2018-08-14 19:44:34 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-08-26 18:26:24 +08:00
|
|
|
if (keyring)
|
2018-08-14 19:44:34 +08:00
|
|
|
{
|
|
|
|
|
ctx->immutable_cert = 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-08-26 18:26:24 +08:00
|
|
|
if (!keyring && ctx->origcrt && ctx->opts->key)
|
2018-08-14 19:44:34 +08:00
|
|
|
{
|
2018-08-26 18:26:24 +08:00
|
|
|
keyring = cert_new();
|
|
|
|
|
keyring->cert = (X509 *) cachemgr_fkcrt_get(ctx->origcrt);
|
2018-08-14 19:44:34 +08:00
|
|
|
|
2018-08-26 18:26:24 +08:00
|
|
|
if (keyring->cert)
|
2018-08-14 19:44:34 +08:00
|
|
|
{
|
|
|
|
|
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");
|
2018-08-26 18:26:24 +08:00
|
|
|
keyring->cert = ssl_x509_forge(ctx->opts->cacrt,
|
2018-08-14 19:44:34 +08:00
|
|
|
ctx->opts->cakey,
|
|
|
|
|
ctx->origcrt,
|
|
|
|
|
ctx->opts->key,
|
|
|
|
|
NULL,
|
|
|
|
|
ctx->opts->crlurl);
|
2018-08-26 18:26:24 +08:00
|
|
|
cachemgr_fkcrt_set(ctx->origcrt, keyring->cert);
|
2018-08-14 19:44:34 +08:00
|
|
|
}
|
|
|
|
|
|
2018-08-26 18:26:24 +08:00
|
|
|
cert_set_key(keyring, ctx->opts->key);
|
|
|
|
|
cert_set_chain(keyring, ctx->opts->chain);
|
2018-08-14 19:44:34 +08:00
|
|
|
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) &&
|
2018-08-26 18:26:24 +08:00
|
|
|
keyring && keyring->cert)
|
2018-08-14 19:44:34 +08:00
|
|
|
{
|
2018-08-26 18:26:24 +08:00
|
|
|
ctx->usedcrtfpr = ssl_x509_fingerprint(keyring->cert, 0);
|
2018-08-14 19:44:34 +08:00
|
|
|
if (!ctx->usedcrtfpr)
|
|
|
|
|
ctx->enomem = 1;
|
|
|
|
|
}
|
|
|
|
|
|
2018-08-26 18:26:24 +08:00
|
|
|
return keyring;
|
2018-08-14 19:44:34 +08:00
|
|
|
}
|
2018-09-04 15:47:41 +08:00
|
|
|
*/
|
2018-08-28 15:25:09 +08:00
|
|
|
|