From ed21a5973711c1a73522c904ddefbaf9f13205c3 Mon Sep 17 00:00:00 2001 From: zhengchao Date: Sun, 26 Aug 2018 18:26:24 +0800 Subject: [PATCH] =?UTF-8?q?1=E3=80=81=E5=A2=9E=E5=8A=A0=E8=AF=81=E4=B9=A6?= =?UTF-8?q?=E6=A0=A1=E9=AA=8C=EF=BC=9B2=E3=80=81=E4=BF=AE=E6=94=B9cert=20m?= =?UTF-8?q?anager=E4=B8=BAkey=20keeper=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- platform/include/internal/cert.h | 19 -- platform/include/internal/key_keeper.h | 21 ++ platform/include/internal/ssl_stream.h | 1 - platform/src/{cert.cpp => key_keeper.cpp} | 68 ++--- platform/src/ssl_stream.cpp | 289 ++++++++++++++-------- 5 files changed, 246 insertions(+), 152 deletions(-) delete mode 100644 platform/include/internal/cert.h create mode 100644 platform/include/internal/key_keeper.h rename platform/src/{cert.cpp => key_keeper.cpp} (77%) diff --git a/platform/include/internal/cert.h b/platform/include/internal/cert.h deleted file mode 100644 index e392297..0000000 --- a/platform/include/internal/cert.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef CERT_H -#define CERT_H - -#include -#include - -struct cert -{ - EVP_PKEY *key; - X509 *crt; - STACK_OF(X509) * chain; -}; -struct cert_mgr; -struct cert_mgr * cert_mgr_init(const char * profile, const char* section); -struct cert* cert_mgr_query_result_release_cert(future_result_t* result); -void cert_mgr_free_cert(struct cert* cert); -void cert_mgr_async_query(struct future * future, struct cert_mgr * mgr, int keyring_id, - X509 * origin_cert, struct event_base * evbase); -#endif /* !CERT_H */ diff --git a/platform/include/internal/key_keeper.h b/platform/include/internal/key_keeper.h new file mode 100644 index 0000000..5b3b77e --- /dev/null +++ b/platform/include/internal/key_keeper.h @@ -0,0 +1,21 @@ +#ifndef CERT_H +#define CERT_H + +#include +#include + +struct keyring +{ + EVP_PKEY *key; + X509 *cert; + STACK_OF(X509) * chain; +}; +struct key_keeper; +struct key_keeper * key_keeper_init(const char * profile, const char* section, void* logger); +struct key_keeper * key_keeper_destroy(struct key_keeper *keeper); + +struct keyring* key_keeper_release_cert(future_result_t* result); +void key_keeper_free_keyring(struct keyring* cert); +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); +#endif /* !CERT_H */ diff --git a/platform/include/internal/ssl_stream.h b/platform/include/internal/ssl_stream.h index e93d32e..9242d00 100644 --- a/platform/include/internal/ssl_stream.h +++ b/platform/include/internal/ssl_stream.h @@ -1,7 +1,6 @@ #pragma once #include #include -#include #include diff --git a/platform/src/cert.cpp b/platform/src/key_keeper.cpp similarity index 77% rename from platform/src/cert.cpp rename to platform/src/key_keeper.cpp index 62e5974..6d8ca31 100644 --- a/platform/src/cert.cpp +++ b/platform/src/key_keeper.cpp @@ -1,21 +1,21 @@ -#include +#include #include #include -struct cert_mgr +struct key_keeper { }; -struct tfe_cert_private +struct key_keeper_private { - struct cert head; + struct keyring head; pthread_mutex_t mutex; size_t references; }; #if 0 /* - * Certificate, including private key and cert chain. + * Certificate, including private key and keyring chain. */ cert_t * @@ -175,7 +175,7 @@ cert_set_chain(cert_t *c, STACK_OF(X509) *chain) } /* - * Free cert including internal objects. + * Free keyring including internal objects. */ void cert_free(cert_t *c) @@ -200,22 +200,22 @@ cert_free(cert_t *c) free(c); } -struct cert_mgr* cert_mgr_init(const char* profile) +struct key_keeper* key_keeper_init(const char* profile) { } -void cert_mgr_async_get(struct future* future, struct cert_mgr* mgr, int keyring_id, X509* origin_cert, struct event_base* evbase) +void cert_mgr_async_get(struct future* future, struct key_keeper* mgr, int keyring_id, X509* origin_cert, struct event_base* evbase) { X509* orig_cert=SSL_get_peer_certificate(origssl); //todo: need implement - cert_t * cert = NULL; + cert_t * keyring = NULL; if (opts->tgcrtdir) { if (ctx->sni) { - cert = (cert_t *) cachemgr_tgcrt_get(ctx->sni); - if (!cert) + keyring = (cert_t *) cachemgr_tgcrt_get(ctx->sni); + if (!keyring) { char * wildcarded = ssl_wildcardify(ctx->sni); if (!wildcarded) @@ -223,12 +223,12 @@ void cert_mgr_async_get(struct future* future, struct cert_mgr* mgr, int keyring ctx->enomem = 1; return NULL; } - cert = (cert_t *) cachemgr_tgcrt_get(wildcarded); + keyring = (cert_t *) cachemgr_tgcrt_get(wildcarded); free(wildcarded); } - if (cert && OPTS_DEBUG(ctx->opts)) + if (keyring && OPTS_DEBUG(ctx->opts)) { - log_dbg_printf("Target cert by SNI\n"); + log_dbg_printf("Target keyring by SNI\n"); } } else if (ctx->origcrt) @@ -236,11 +236,11 @@ void cert_mgr_async_get(struct future* future, struct cert_mgr* mgr, int keyring char ** names = ssl_x509_names(ctx->origcrt); for (char ** p = names; *p; p++) { - if (!cert) + if (!keyring) { - cert = (cert_t *) cachemgr_tgcrt_get(*p); + keyring = (cert_t *) cachemgr_tgcrt_get(*p); } - if (!cert) + if (!keyring) { char * wildcarded = ssl_wildcardify(*p); if (!wildcarded) @@ -249,7 +249,7 @@ void cert_mgr_async_get(struct future* future, struct cert_mgr* mgr, int keyring } else { - cert = (cert_t *) (wildcarded); + keyring = (cert_t *) (wildcarded); free(wildcarded); } } @@ -260,41 +260,41 @@ void cert_mgr_async_get(struct future* future, struct cert_mgr* mgr, int keyring { return NULL; } - if (cert && OPTS_DEBUG(ctx->opts)) + if (keyring && OPTS_DEBUG(ctx->opts)) { - log_dbg_printf("Target cert by origcrt\n"); + log_dbg_printf("Target keyring by origcrt\n"); } } - if (cert) + if (keyring) { ctx->immutable_cert = 1; } } - if (!cert && ctx->origcrt && ctx->opts->key) + if (!keyring && ctx->origcrt && ctx->opts->key) { - cert = cert_new(); - cert->crt = (X509 *) cachemgr_fkcrt_get(ctx->origcrt); + keyring = cert_new(); + keyring->cert = (X509 *) cachemgr_fkcrt_get(ctx->origcrt); - if (cert->crt) + 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"); - cert->crt = ssl_x509_forge(ctx->opts->cacrt, + 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, cert->crt); + cachemgr_fkcrt_set(ctx->origcrt, keyring->cert); } - cert_set_key(cert, ctx->opts->key); - cert_set_chain(cert, ctx->opts->chain); + cert_set_key(keyring, ctx->opts->key); + cert_set_chain(keyring, ctx->opts->chain); ctx->generated_cert = 1; } @@ -306,18 +306,18 @@ void cert_mgr_async_get(struct future* future, struct cert_mgr* mgr, int keyring } if ((WANT_CONNECT_LOG(ctx) || ctx->opts->certgen_writeall) && - cert && cert->crt) + keyring && keyring->cert) { - ctx->usedcrtfpr = ssl_x509_fingerprint(cert->crt, 0); + ctx->usedcrtfpr = ssl_x509_fingerprint(keyring->cert, 0); if (!ctx->usedcrtfpr) ctx->enomem = 1; } - return cert; + return keyring; } -void cert_manager_free(cert_t * cert) +void cert_manager_free(cert_t * keyring) { - cert_free(cert); + cert_free(keyring); return; } #endif diff --git a/platform/src/ssl_stream.cpp b/platform/src/ssl_stream.cpp index 9a597a4..e254460 100644 --- a/platform/src/ssl_stream.cpp +++ b/platform/src/ssl_stream.cpp @@ -32,7 +32,7 @@ #include #include #include -#include +#include #include #include #include @@ -55,22 +55,32 @@ struct ssl_mgr { int sess_expire_seconds; struct sess_cache * down_sess_cache; struct sess_cache * up_sess_cache; - char * default_ciphers[TFE_SYMBOL_MAX]; + char default_ciphers[TFE_STRING_MAX]; DH * dh; char * ecdhcurve; char * crlurl; uint8_t SSL_MODE_RELEASE_BUFFERS; void * logger; - struct cert_mgr * cert_mgr; + char trust_CA_file[TFE_STRING_MAX]; + char trust_CA_dir[TFE_STRING_MAX]; + X509_STORE* trust_CA_store; + struct key_keeper * keeper_of_keys; }; - +struct __ssl_stream_debug +{ + evutil_socket_t fd; +}; struct ssl_stream { enum tfe_conn_dir dir; SSL * ssl; struct ssl_mgr * mgr; - struct ssl_chello * client_hello; - struct ssl_stream* peer; + union + { + struct ssl_chello * client_hello; //dir=upstream, a little weird, which send by downstream client. + struct keyring* keyring; //dir=downstream. + }; + struct __ssl_stream_debug _do_not_use; }; @@ -106,10 +116,11 @@ struct ssl_connect_origin_ctx { }; -struct query_cert_ctx { +struct ask_keyring_ctx { int keyring_id; struct ssl_stream * origin_ssl; X509 * origin_crt; + int is_origin_crt_vaild; struct ssl_mgr * ssl_mgr; evutil_socket_t fd_downstream; struct event_base * evbase; @@ -130,23 +141,56 @@ struct ssl_shutdown_ctx { unsigned int retries; }; - -struct ssl_stream * ssl_stream_create(struct ssl_chello * client_hello, struct ssl_mgr * mgr, struct sockaddr * addr, - socklen_t addrlen) { +struct ssl_stream * ssl_stream_new(struct ssl_mgr * mgr, evutil_socket_t fd, enum tfe_conn_dir dir, struct ssl_chello * client_hello, struct keyring* crt) +{ + struct sockaddr addr; + socklen_t addrlen; + int ret=0; struct ssl_stream * s_stream = ALLOC(struct ssl_stream, 1); - s_stream->client_hello = client_hello; - s_stream->ssl = upstream_ssl_create(mgr, client_hello, addr, addrlen); + s_stream->dir=dir; + s_stream->mgr=mgr; + s_stream->_do_not_use.fd=fd; + ret = getpeername(fd , &addr, &addrlen); + assert(ret == 0); + switch (dir) + { + case CONN_DIR_DOWNSTREAM: + s_stream->ssl= downstream_ssl_create(mgr, crt); + s_stream->keyring=crt; + break; + case CONN_DIR_UPSTREAM: + s_stream->ssl= upstream_ssl_create(mgr, client_hello, fd); + s_stream->client_hello=client_hello; + break; + default: + assert(0); + } return s_stream; -} +} static void ssl_stream_free(struct ssl_stream * s_stream) { SSL_free(s_stream->ssl); s_stream->ssl = NULL; - - if (s_stream->client_hello != NULL) { - ssl_free_chello(s_stream->client_hello;); + switch (s_stream->dir) + { + case CONN_DIR_DOWNSTREAM: + if(s_stream->keyring!=NULL) + { + key_keeper_free_keyring(s_stream->keyring); + s_stream->keyring=NULL; + } + break; + case CONN_DIR_UPSTREAM: + if(s_stream->client_hello!=NULL) + { + ssl_free_chello(s_stream->client_hello); + s_stream->client_hello=NULL; + } + break; + default: + assert(0); } s_stream->mgr = NULL; @@ -166,19 +210,24 @@ static int sslver_str2num(const char * version_str) * SSLv2_server_method() and SSLv2_client_method() functions were * removed in OpenSSL 1.1.0. */ - if (!strcmp(version_str, "ssl3")) { + if (!strcmp(version_str, "ssl3")) + { sslversion = SSL3_VERSION; } - else if (!strcmp(version_str, "tls10") || !strcmp(version_str, "tls1")) { + else if (!strcmp(version_str, "tls10") || !strcmp(version_str, "tls1")) + { sslversion = TLS1_VERSION; } - else if (!strcmp(version_str, "tls11")) { + else if (!strcmp(version_str, "tls11")) + { sslversion = TLS1_1_VERSION; } - else if (!strcmp(version_str, "tls12")) { + else if (!strcmp(version_str, "tls12")) + { sslversion = TLS1_2_VERSION; } - else { + else + { sslversion = -1; } @@ -188,6 +237,15 @@ static int sslver_str2num(const char * version_str) void ssl_manager_destroy(struct ssl_mgr * mgr) { + if(mgr->keeper_of_keys!=NULL) + { + key_keeper_destroy(mgr->keeper_of_keys); + } + if(mgr->trust_CA_store!=NULL) + { + X509_STORE_free(mgr->trust_CA_store); + mgr->trust_CA_store=NULL; + } free(mgr); } @@ -220,34 +278,70 @@ struct ssl_mgr * ssl_manager_init(const char * ini_profile, const char * section mgr->up_sess_cache = ssl_sess_cache_create(mgr->cache_slot_num, mgr->sess_expire_seconds, CONN_DIR_UPSTREAM); mgr->down_sess_cache = ssl_sess_cache_create(mgr->cache_slot_num, mgr->sess_expire_seconds, CONN_DIR_DOWNSTREAM); - mgr->cert_mgr = cert_mgr_init(ini_profile, section); - if (mgr->cert_mgr == NULL) { + + + mgr->keeper_of_keys = key_keeper_init(ini_profile, section, logger); + + if (mgr->keeper_of_keys == NULL) + { TFE_LOG_ERROR(logger, "Certificate Manager initiate failed."); goto error_out; } + mgr->trust_CA_store=X509_STORE_new(); + if(mgr->trust_CA_store==NULL) + { + TFE_LOG_ERROR(logger,"Failed at creating X509_STORE"); + goto error_out; + } + ret=X509_STORE_set_default_paths(mgr->trust_CA_store); + if(ret==0) + { + TFE_LOG_ERROR(logger,"Failed at setting default paths for X509_STORE"); + goto error_out; + } + MESA_load_profile_string_def(ini_profile, section, "trust_CA_file", mgr->trust_CA_file, sizeof(mgr->trust_CA_file), ""); + MESA_load_profile_string_def(ini_profile, section, "trust_CA_dir", mgr->trust_CA_dir, sizeof(mgr->trust_CA_dir), ""); - + ret=X509_STORE_load_locations(mgr->trust_CA_store,strlen(mgr->trust_CA_file)>0? mgr->trust_CA_file:NULL + ,strlen(mgr->trust_CA_dir)>0? mgr->trust_CA_dir:NULL); + if(ret==0) + { + TFE_LOG_ERROR(logger,"Failed at setting load locations for X509_STORE"); + goto error_out; + } memcpy(mgr->ssl_session_context, "mesa-tfe", sizeof(mgr->ssl_session_context)); return mgr; - - - - - - - - - error_out: ssl_manager_destroy(mgr); return NULL; -} void peek_client_hello_ctx_free(void * ctx) +} +int ssl_conn_verify_cert(X509_STORE *store, const SSL * ssl) { - struct peek_client_hello_ctx * _ctx = (struct peek_client_hello_ctx *) - ctx; + int ret=0; + STACK_OF(X509) * cert_chain = SSL_get_peer_cert_chain(ssl); + if(cert_chain==NULL) + { + // The peer certificate chain is not necessarily available after reusing a session, in which case a NULL pointer is returned. + return 1; + } + X509_STORE_CTX *ctx=X509_STORE_CTX_new(); + X509 * cert = sk_X509_value(cert_chain, 0); + ret=X509_STORE_CTX_init(ctx, store, cert, cert_chain); + assert(ret==1); + + //If a complete chain can be built and validated this function returns 1, otherwise it return zero or negtive code. + ret=X509_verify_cert(ctx); + X509_STORE_CTX_free(ctx); + return (ret==1); +} + + +void peek_client_hello_ctx_free(void * ctx) +{ + struct peek_client_hello_ctx * _ctx = (struct peek_client_hello_ctx *)ctx; event_free(_ctx->ev); _ctx->ev = NULL; free(_ctx->chello.sni); @@ -259,10 +353,10 @@ error_out: } -struct ssl_chello * ssl_peek_result_release_chello(future_result_t * result) { - struct ssl_chello * p = (struct ssl_chello *) - result, *copy = NULL; - copy = ALLOC(struct ssl_chello *, 1); +struct ssl_chello * ssl_peek_result_release_chello(future_result_t * result) +{ + struct ssl_chello * p = (struct ssl_chello *)result, *copy = NULL; + copy = ALLOC(struct ssl_chello, 1); if (p != NULL) { copy->sni = tfe_strdup(p->sni); @@ -270,7 +364,6 @@ struct ssl_chello * ssl_peek_result_release_chello(future_result_t * result) { copy->version = p->version; } - return copy; } void ssl_free_chello(struct ssl_chello * p) { @@ -290,6 +383,7 @@ struct ssl_chello * ssl_peek_result_release_chello(future_result_t * result) { static void peek_client_hello_cb(evutil_socket_t fd, short what, void * arg) { struct promise * promise = (struct promise *)arg; + //use promise_get_ctx instead of promise_dettach_ctx for try more times. struct peek_client_hello_ctx * ctx = (struct peek_client_hello_ctx *)promise_get_ctx(promise); const char * reason_too_many_retries = "too many tries"; const char * reason_see_no_client_hello = "see no client hello"; @@ -358,7 +452,6 @@ failed: promise_dettach_ctx(promise); promise_failed(promise, FUTURE_ERROR_EXCEPTION, reason); peek_client_hello_ctx_free(ctx); - ssl_free_chello(result); return; } @@ -382,8 +475,7 @@ static void ssl_async_peek_client_hello(struct future * future, evutil_socket_t * Create new SSL context for outgoing connections to the original destination. * If hostname sni is provided, use it for Server Name Indication. */ -static SSL * upstream_ssl_create(struct ssl_mgr * mgr, const struct ssl_chello * chello, struct sockaddr * addr, - socklen_t addrlen) +static SSL * upstream_ssl_create(struct ssl_mgr * mgr, const struct ssl_chello * chello, evutil_socket_t fd) { SSL_CTX * sslctx = NULL; SSL * ssl = NULL; @@ -429,17 +521,18 @@ static SSL * upstream_ssl_create(struct ssl_mgr * mgr, const struct ssl_chello * SSL_set_mode(ssl, SSL_get_mode(ssl) | SSL_MODE_RELEASE_BUFFERS); #endif /* SSL_MODE_RELEASE_BUFFERS */ - //Todo: Refactor below session resumption. - + struct sockaddr addr; + socklen_t addrlen; + int ret=0; + ret = getpeername(fd , &addr, &addrlen); + assert(ret==0); /* session resuming based on remote endpoint address and port */ - sess = up_session_get(mgr->up_sess_cache, addr, - addrlen, chello->sni); /* new sess inst */ - - if (sess) { + sess = up_session_get(mgr->up_sess_cache, &addr, addrlen, chello->sni); /* new sess insert */ + if (sess) + { SSL_set_session(ssl, sess); /* increments sess refcount */ SSL_SESSION_free(sess); } - return ssl; } @@ -520,7 +613,7 @@ static void peek_chello_on_succ(future_result_t * result, void * user) struct ssl_connect_origin_ctx * ctx = (struct ssl_connect_origin_ctx *) promise_dettach_ctx(p); struct ssl_chello * chello = ssl_peek_result_release_chello(result);//chello has been saved in ssl_stream. - ctx->s_stream = ssl_stream_create(chello, ctx->mgr, & (ctx->addr), ctx->addrlen); + ctx->s_stream = ssl_stream_new(ctx->mgr, ctx->fd_upstream, CONN_DIR_UPSTREAM, chello, NULL); ctx->bev = bufferevent_openssl_socket_new(ctx->evbase, ctx->fd_upstream, ctx->s_stream, BUFFEREVENT_SSL_CONNECTING, BEV_OPT_DEFER_CALLBACKS); bufferevent_openssl_set_allow_dirty_shutdown(ctx->bev, 1); @@ -718,15 +811,15 @@ static void sslctx_set_opts(SSL_CTX * sslctx, struct ssl_mgr * mgr) /* * Create and set up a new SSL_CTX instance for terminating SSL. - * Set up all the necessary callbacks, the cert, the cert chain and key. + * Set up all the necessary callbacks, the keyring, the keyring chain and key. */ -static SSL_CTX * down_sslctx_create(struct ssl_mgr * mgr, struct cert * crt) +static SSL* downstream_ssl_create(struct ssl_mgr * mgr, struct keyring * crt) { SSL_CTX * sslctx = SSL_CTX_new(mgr->sslmethod()); - if (!sslctx) return NULL; - + SSL* ssl=NULL; + int ret=0; sslctx_set_opts(sslctx, mgr); //TFE's OPENSSL_VERSION_NUMBER >= 0x10100000L @@ -771,7 +864,7 @@ static SSL_CTX * down_sslctx_create(struct ssl_mgr * mgr, struct cert * crt) #endif /* !OPENSSL_NO_ECDH */ - SSL_CTX_use_certificate(sslctx, crt->crt); + SSL_CTX_use_certificate(sslctx, crt->cert); SSL_CTX_use_PrivateKey(sslctx, crt->key); for (int i = 0; i < sk_X509_num(crt->chain); i++) { @@ -779,12 +872,23 @@ static SSL_CTX * down_sslctx_create(struct ssl_mgr * mgr, struct cert * crt) ssl_x509_refcount_inc(c); /* next call consumes a reference */ SSL_CTX_add_extra_chain_cert(sslctx, c); } + ssl=SSL_new(sslctx); + SSL_CTX_free(sslctx); // SSL_new() increments refcount + sslctx=NULL; + ret = SSL_set_ex_data(ssl, SSL_EX_DATA_IDX_SSLMGR, mgr); + assert(ret == 1); + + if (mgr->SSL_MODE_RELEASE_BUFFERS == 1) + { + /* lower memory footprint for idle connections */ + SSL_set_mode(ssl, SSL_get_mode(ssl) | SSL_MODE_RELEASE_BUFFERS); + } - return sslctx; + return ssl; } -void query_cert_ctx_free(struct query_cert_ctx * ctx) +void query_cert_ctx_free(struct ask_keyring_ctx * ctx) { X509_free(ctx->origin_crt); @@ -805,67 +909,51 @@ void query_cert_ctx_free(struct query_cert_ctx * ctx) struct ssl_stream* ssl_downstream_create_result_release_stream(future_result_t* result) { - struct query_cert_ctx * ctx = (struct query_cert_ctx *)result; + struct ask_keyring_ctx * ctx = (struct ask_keyring_ctx *)result; struct ssl_stream* ret=ctx->downstream; ctx->downstream=NULL; return ret; } struct bufferevent* ssl_downstream_create_result_release_bev(future_result_t* result) { - struct query_cert_ctx * ctx = (struct query_cert_ctx *)result; + struct ask_keyring_ctx * ctx = (struct ask_keyring_ctx *)result; struct bufferevent* ret=ctx->bev_down; ctx->bev_down=NULL; return ret; } -void query_cert_on_succ(void * result, void * user) +void ask_keyring_on_succ(void * result, void * user) { struct promise* p=(struct promise*)user; - struct query_cert_ctx * ctx = (struct query_cert_ctx *)promise_dettach_ctx(promise); + struct ask_keyring_ctx * ctx = (struct ask_keyring_ctx *)promise_dettach_ctx(promise); struct ssl_stream * downstream = NULL; - struct cert* crt=NULL; - SSL_CTX * sslctx=NULL; + struct keyring* crt=NULL; struct ssl_mgr* mgr=ctx->ssl_mgr; future_destroy(ctx->f_query_cert); ctx->f_query_cert=NULL; - crt=cert_mgr_query_result_release_cert(result); - sslctx = down_sslctx_create(mgr, crt); - assert(sslctx!=NULL); - - downstream = ALLOC(struct ssl_stream, 1); - downstream->mgr = mgr; - downstream->dir = CONN_DIR_DOWNSTREAM; - downstream->ssl = SSL_new(sslctx); - downstream->peer = ctx->origin_ssl; - ctx->origin_ssl->peer= downstream; - int ret = SSL_set_ex_data(downstream->ssl, SSL_EX_DATA_IDX_SSLMGR, mgr); - assert(ret == 1); - SSL_CTX_free(sslctx); /* SSL_new() increments refcount */ + crt=key_keeper_release_cert(result); - if (mgr->SSL_MODE_RELEASE_BUFFERS == 1) { - /* lower memory footprint for idle connections */ - SSL_set_mode(downstream->ssl, SSL_get_mode(downstream->ssl) | SSL_MODE_RELEASE_BUFFERS); - } - ctx->downstream = downstream; + ctx->downstream = ssl_stream_new(mgr, ctx->fd_downstream, CONN_DIR_DOWNSTREAM, NULL, crt); + ctx->bev_down = bufferevent_openssl_socket_new(ctx->evbase, ctx->fd_downstream, ctx->downstream->ssl, BUFFEREVENT_SSL_CONNECTING, BEV_OPT_DEFER_CALLBACKS); bufferevent_openssl_set_allow_dirty_shutdown(ctx->bev_down, 1); promise_success(p, ctx); - cert_mgr_free_cert(crt); + key_keeper_free_keyring(crt); query_cert_ctx_free(ctx); return; } -void query_cert_on_fail(enum e_future_error error, const char * what, void * user) +void ask_keyring_on_fail(enum e_future_error error, const char * what, void * user) { struct promise* p=(struct promise*)user; - struct query_cert_ctx * ctx = (struct query_cert_ctx *)promise_dettach_ctx(promise); + struct ask_keyring_ctx * ctx = (struct ask_keyring_ctx *)promise_dettach_ctx(promise); promise_failed(p, error, what); query_cert_ctx_free(ctx); return; @@ -873,26 +961,32 @@ void query_cert_on_fail(enum e_future_error error, const char * what, void * use /* - * Create a SSL stream for the incoming connection, based on the a upstream. + * Create a SSL stream for the incoming connection, based on the upstream. */ void ssl_async_downstream_create(struct future * f, struct ssl_mgr * mgr, struct ssl_stream * upstream, evutil_socket_t fd_downstream, int keyring_id, struct event_base * evbase) { assert(upstream->dir == CONN_DIR_UPSTREAM); - struct query_cert_ctx * ctx = ALLOC(struct query_cert_ctx, 1); + struct ask_keyring_ctx * ctx = ALLOC(struct ask_keyring_ctx, 1); ctx->keyring_id = keyring_id; - ctx->origin_ssl = upstream; - ctx->origin_crt = SSL_get_peer_certificate(upstream->ssl); ctx->ssl_mgr = mgr; ctx->fd_downstream = fd_downstream; ctx->evbase = evbase; + + if(upstream!=NULL) + { + ctx->origin_ssl = upstream; + ctx->origin_crt = SSL_get_peer_certificate(upstream->ssl); + } struct promise* p = future_to_promise(f); promise_set_ctx(p, ctx, query_cert_ctx_free); - //todo: verify original certificate. - ctx->f_query_cert = future_create(query_cert_on_succ, query_cert_on_fail, p); - cert_mgr_async_query(ctx->f_query_cert, mgr->cert_mgr, keyring_id, ctx->origin_crt, evbase); + ctx->is_origin_crt_vaild=ssl_conn_verify_cert(mgr->trust_CA_store, upstream->ssl); + + ctx->f_query_cert = future_create(ask_keyring_on_succ, ask_keyring_on_fail, p); + //todo add a is_valid_cert flag to keyring manager query API. + key_keeper_async_ask(ctx->f_query_cert, mgr->keeper_of_keys, keyring_id, ctx->origin_crt, ctx->is_origin_crt_vaild, evbase); return; } @@ -904,17 +998,16 @@ void ssl_async_downstream_create(struct future * f, struct ssl_mgr * mgr, struct * with the older SSL_shutdown() semantics, not exposing WANT_READ/WRITE * may or may not work. */ -static - - -struct ssl_shutdown_ctx * ssl_shutdown_ctx_new(struct ssl_stream * s_stream, struct event_base * evbase) { +static struct ssl_shutdown_ctx * ssl_shutdown_ctx_new(struct ssl_stream * s_stream, struct event_base * evbase) { struct ssl_shutdown_ctx * ctx = ALLOC(struct ssl_shutdown_ctx, 1); ctx->evbase = evbase; ctx->s_stream = s_stream; ctx->ev = NULL; ctx->retries = 0; return ctx; -} static void ssl_shutdown_ctx_free(struct ssl_shutdown_ctx * ctx) +} + +static void ssl_shutdown_ctx_free(struct ssl_shutdown_ctx * ctx) { free(ctx); }