优化原站证书验证处理流程,不对缓存证书校验不通过的session,重用连接不进行验证。

This commit is contained in:
zhengchao
2018-10-08 15:06:01 +08:00
parent d63dfaa4d4
commit de94bc645c

View File

@@ -33,6 +33,11 @@
#include <platform.h>
int SSL_EX_DATA_IDX_SSLMGR;
int SSL_EX_DATA_IDX_VERIFIED;
int SSL_PEER_CERT_VERIFY_PASSED=1;
int SSL_PEER_CERT_VERIFY_FAILED=0;
#define MAX_NET_RETRIES 50
/*
@@ -142,6 +147,7 @@ struct ssl_stream
struct keyring * keyring; //dir=downstream.
};
struct __ssl_stream_debug _do_not_use;
int is_peer_cert_verify_passed;
};
@@ -174,12 +180,12 @@ struct ask_keyring_ctx
int keyring_id;
struct ssl_stream * origin_ssl;
X509 * origin_crt;
int is_origin_crt_vaild;
int is_origin_crt_verify_passed;
struct ssl_mgr * ssl_mgr;
evutil_socket_t fd_downstream;
struct event_base * evbase;
struct future * f_query_cert;
struct future * f_ask_keyring;
struct bufferevent * bev_down;
struct ssl_stream * downstream;
};
@@ -469,7 +475,9 @@ struct ssl_mgr * ssl_manager_init(const char * ini_profile, const char * section
}
//tfe2a uses SSLv23_method, it was been deprecated and replaced with the TLS_method() in openssl 1.1.0.
mgr->sslmethod = TLS_method;
SSL_EX_DATA_IDX_SSLMGR = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
SSL_EX_DATA_IDX_SSLMGR = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
SSL_EX_DATA_IDX_VERIFIED = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
MESA_load_profile_uint_def(ini_profile, section, "ssl_compression", &(mgr->sslcomp), 1);
MESA_load_profile_uint_def(ini_profile, section, "no_ssl2", &(mgr->no_ssl2), 1);
MESA_load_profile_uint_def(ini_profile, section, "no_ssl3", &(mgr->no_ssl3), 1);
@@ -897,6 +905,7 @@ static void ssl_connect_origin_eventcb(struct bufferevent * bev, short events, v
struct ssl_connect_origin_ctx * ctx = (struct ssl_connect_origin_ctx *) promise_dettach_ctx(promise);
struct ssl_stream * s_stream = ctx->s_stream;
struct ssl_mgr* mgr=s_stream->mgr;
SSL_SESSION * ssl_sess = NULL;
if (events & BEV_EVENT_ERROR)
@@ -919,10 +928,29 @@ static void ssl_connect_origin_eventcb(struct bufferevent * bev, short events, v
{
bufferevent_disable(ctx->bev, EV_READ | EV_WRITE);
bufferevent_setcb(ctx->bev, NULL, NULL, NULL, NULL); //leave a clean bev for on_success
//The reference count of the SSL_SESSION is not incremented, so no need to free.
ssl_sess = SSL_get0_session(s_stream->ssl);
up_session_set(s_stream->mgr->up_sess_cache, (struct sockaddr *)&(ctx->addr),
ctx->addrlen, s_stream->client_hello->sni, ssl_sess);
if(!SSL_session_reused(s_stream->ssl))
{
s_stream->is_peer_cert_verify_passed = ssl_conn_verify_cert(s_stream->mgr->trust_CA_store, s_stream->ssl);
if(s_stream->is_peer_cert_verify_passed)
{
//ONLY verified session is cacheable.
//The reference count of the SSL_SESSION is not incremented, so no need to free.
ssl_sess = SSL_get0_session(s_stream->ssl);
up_session_set(mgr->up_sess_cache, (struct sockaddr *)&(ctx->addr),
ctx->addrlen, s_stream->client_hello->sni, ssl_sess);
}
else
{
ATOMIC_INC(&(mgr->stat_val[SSL_FAKE_CRT]));
}
}
else
{
//Do not perform cert check on reused session.
s_stream->is_peer_cert_verify_passed=1;
}
promise_success(promise, ctx);
}
ssl_connect_origin_ctx_free(ctx);
@@ -1260,14 +1288,15 @@ static SSL * downstream_ssl_create(struct ssl_mgr * mgr, struct keyring * crt)
return ssl;
}
void query_cert_ctx_free(struct ask_keyring_ctx * ctx)
void ask_keyring_ctx_free(struct ask_keyring_ctx * ctx)
{
X509_free(ctx->origin_crt);
if (ctx->f_query_cert != NULL)
ctx->origin_crt=NULL;
if (ctx->f_ask_keyring != NULL)
{
future_destroy(ctx->f_query_cert);
ctx->f_query_cert = NULL;
future_destroy(ctx->f_ask_keyring);
ctx->f_ask_keyring = NULL;
}
//on success, bev_down and downstream has been transfered to caller by release**
if (ctx->bev_down != NULL)
@@ -1283,10 +1312,10 @@ void query_cert_ctx_free(struct ask_keyring_ctx * ctx)
return;
}
void query_cert_ctx_free_cb(void * p)
void ask_keyring_ctx_free_cb(void * p)
{
struct ask_keyring_ctx * ctx = (struct ask_keyring_ctx *)p;
query_cert_ctx_free(ctx);
ask_keyring_ctx_free(ctx);
}
struct ssl_stream * ssl_downstream_create_result_release_stream(future_result_t * result)
@@ -1315,8 +1344,8 @@ void ask_keyring_on_succ(void * result, void * user)
kyr = key_keeper_release_keyring(result); //kyr will be freed at ssl downstream closing.
future_destroy(ctx->f_query_cert);
ctx->f_query_cert = NULL;
future_destroy(ctx->f_ask_keyring);
ctx->f_ask_keyring = NULL;
ctx->downstream = ssl_stream_new(mgr, ctx->fd_downstream, CONN_DIR_DOWNSTREAM, NULL, kyr);
ctx->bev_down = bufferevent_openssl_socket_new(ctx->evbase, ctx->fd_downstream, ctx->downstream->ssl,
@@ -1324,7 +1353,7 @@ void ask_keyring_on_succ(void * result, void * user)
bufferevent_openssl_set_allow_dirty_shutdown(ctx->bev_down, 1);
promise_success(p, ctx);
query_cert_ctx_free(ctx);
ask_keyring_ctx_free(ctx);
}
void ask_keyring_on_fail(enum e_future_error error, const char * what, void * user)
@@ -1332,7 +1361,7 @@ void ask_keyring_on_fail(enum e_future_error error, const char * what, void * us
struct promise * p = (struct promise *) user;
struct ask_keyring_ctx * ctx = (struct ask_keyring_ctx *) promise_dettach_ctx(p);
promise_failed(p, error, what);
query_cert_ctx_free(ctx);
ask_keyring_ctx_free(ctx);
return;
}
@@ -1344,13 +1373,14 @@ void ssl_async_downstream_create(struct future * f, struct ssl_mgr * mgr, struct
{
assert(upstream->dir == CONN_DIR_UPSTREAM);
int * previous_verfiy_result=NULL;
const char* sni=NULL;
struct ask_keyring_ctx * ctx = ALLOC(struct ask_keyring_ctx, 1);
ctx->keyring_id = keyring_id;
ctx->ssl_mgr = mgr;
ctx->fd_downstream = fd_downstream;
ctx->evbase = evbase;
if (upstream != NULL)
{
ctx->origin_ssl = upstream;
@@ -1359,14 +1389,11 @@ void ssl_async_downstream_create(struct future * f, struct ssl_mgr * mgr, struct
}
struct promise * p = future_to_promise(f);
promise_set_ctx(p, ctx, query_cert_ctx_free_cb);
ctx->is_origin_crt_vaild = ssl_conn_verify_cert(mgr->trust_CA_store, upstream->ssl);
if(!ctx->is_origin_crt_vaild)
{
ATOMIC_INC(&(mgr->stat_val[SSL_FAKE_CRT]));
}
ctx->f_query_cert = future_create("ask_kyr",ask_keyring_on_succ, ask_keyring_on_fail, p);
key_keeper_async_ask(ctx->f_query_cert, mgr->key_keeper, sni, keyring_id, ctx->origin_crt, ctx->is_origin_crt_vaild,
promise_set_ctx(p, ctx, ask_keyring_ctx_free_cb);
ctx->f_ask_keyring = future_create("ask_kyr",ask_keyring_on_succ, ask_keyring_on_fail, p);
ctx->is_origin_crt_verify_passed = upstream->is_peer_cert_verify_passed;
key_keeper_async_ask(ctx->f_ask_keyring, mgr->key_keeper, sni, keyring_id, ctx->origin_crt, ctx->is_origin_crt_verify_passed,
evbase);
return;
}