diff --git a/common/include/tfe_stream.h b/common/include/tfe_stream.h index f324145..4b62791 100644 --- a/common/include/tfe_stream.h +++ b/common/include/tfe_stream.h @@ -73,7 +73,7 @@ enum tfe_stream_opt_level STREAM_OPT_LEVEL_TCP, STREAM_OPT_LEVEL_SSL //see tfe_types.h enum SSL_STREAM_OPT }; -int tfe_stream_set_opt(struct tfe_stream * stream, enum tfe_stream_opt_level level, int type, const void* value, size_t size); +int tfe_stream_set_integer_opt(struct tfe_stream * stream, enum tfe_stream_opt_level level, int type, int val); /* @return 0 if successful, or -1 if an error occurred */ diff --git a/common/include/tfe_types.h b/common/include/tfe_types.h index 167642c..723a94f 100644 --- a/common/include/tfe_types.h +++ b/common/include/tfe_types.h @@ -159,20 +159,5 @@ char* tfe_string_addr_create_by_fd(int fd, enum tfe_conn_dir dir); char * tfe_stream_addr_to_str(const struct tfe_stream_addr * addr); int tfe_stream_addr_str_split(char* addr_str, const char** sip, const char** sport, const char** dip, const char** dport); -enum SSL_STREAM_OPT -{ - SSL_STREAM_OPT_BYPASS_EV_CERT, //VALUE is an interger, SIZE=sizeof(int). 1:BYPASS, 0:INTERCEPT. DEFAULT:0. - SSL_STREAM_OPT_BYPASS_CT_CERT, //VALUE is an interger, SIZE=sizeof(int). 1:BYPASS, 0:INTERCEPT. DEFAULT:0. - SSL_STREAM_OPT_BYPASS_MUTUAL_AUTH, //VALUE is an interger, SIZE=sizeof(int). 1:BYPASS, 0:BLOCKED. DEFAULT:1. - SSL_STREAM_OPT_BYPASS_CERT_PINNING, //VALUE is an interger, SIZE=sizeof(int). 1:BYPASS, 0:BLOCKED. DEFAULT:1. - SSL_STREAM_OPT_VERIFY_SELF_SIGNED, //VALUE is an interger, SIZE=sizeof(int). 1:ON, 0:OFF. DEFAULT:1. - SSL_STREAM_OPT_VERIFY_COMMON_NAME, //VALUE is an interger, SIZE=sizeof(int). 1:ON, 0:OFF. DEFAULT:1. - SSL_STREAM_OPT_VERIFY_ISSUER, //VALUE is an interger, SIZE=sizeof(int). 1:ON, 0:OFF. DEFAULT:1. - SSL_STREAM_OPT_VERIFY_EXPIRY_DATE, //VALUE is an interger, SIZE=sizeof(int). 1:ON, 0:OFF. DEFAULT:1. - SST_STREAM_OPT_VERIFY_FAIL_ACTION, //VALUE is an interger, SIZE=sizeof(int). 1:PASSTHROUGH, 0:BLOCK. DEFAULT:1. - SSL_STREAM_OPT_PROTOCOL_MIN_VERSION, - SSL_STREAM_OPT_PROTOCOL_MAX_VERSION -}; - diff --git a/platform/CMakeLists.txt b/platform/CMakeLists.txt index cad21c5..2d8148d 100644 --- a/platform/CMakeLists.txt +++ b/platform/CMakeLists.txt @@ -1,7 +1,8 @@ add_executable(tfe src/key_keeper.cpp src/kni_acceptor.cpp src/ssl_stream.cpp src/ssl_sess_cache.cpp src/ssl_service_cache.cpp src/ssl_trusted_cert_storage.cpp src/ev_root_ca_metadata.cpp - src/ssl_utils.cpp src/tcp_stream.cpp src/main.cpp src/proxy.cpp) + src/ssl_policy.cpp src/ssl_utils.cpp + src/tcp_stream.cpp src/main.cpp src/proxy.cpp) target_include_directories(tfe PUBLIC ${CMAKE_CURRENT_LIST_DIR}/include/external) target_include_directories(tfe PRIVATE ${CMAKE_CURRENT_LIST_DIR}/include/internal) diff --git a/platform/include/internal/platform.h b/platform/include/internal/platform.h index 2c25831..adb41b8 100644 --- a/platform/include/internal/platform.h +++ b/platform/include/internal/platform.h @@ -104,8 +104,8 @@ struct tfe_stream_private unsigned int nr_plugin_ctxs; struct plugin_ctx * plugin_ctxs; - /* TCP forward without scan or decode when the passthough is set */ - bool passthough; + /* TCP forward without scan or decode when the tcp_passthough is set */ + bool tcp_passthough; /* For defer connection setup */ evutil_socket_t defer_fd_downstream; diff --git a/platform/include/internal/ssl_sess_cache.h b/platform/include/internal/ssl_sess_cache.h index e4cc601..49080ce 100644 --- a/platform/include/internal/ssl_sess_cache.h +++ b/platform/include/internal/ssl_sess_cache.h @@ -8,8 +8,8 @@ struct sess_cache; struct sess_cache * ssl_sess_cache_create(unsigned int slot_size, unsigned int expire_seconds, enum tfe_conn_dir served); void ssl_sess_cache_destroy(struct sess_cache * cache); -void up_session_set(struct sess_cache * cache, struct sockaddr * addr, socklen_t addr_len, const char * sni, SSL_SESSION * value); -SSL_SESSION * up_session_get(struct sess_cache * cache, struct sockaddr * addr, socklen_t addr_len, const char * sni); +void up_session_set(struct sess_cache * cache, struct sockaddr * addr, socklen_t addr_len, const char * sni, int version, SSL_SESSION * sess); +SSL_SESSION * up_session_get(struct sess_cache * cache, struct sockaddr * addr, socklen_t addr_len, const char * sni, int min_ver, int max_ver); void down_session_set(struct sess_cache * cache, const SSL_SESSION * sess); void down_session_del(struct sess_cache * cache, const SSL_SESSION * sess); diff --git a/platform/include/internal/ssl_stream.h b/platform/include/internal/ssl_stream.h index fe4b657..1fb2044 100644 --- a/platform/include/internal/ssl_stream.h +++ b/platform/include/internal/ssl_stream.h @@ -8,14 +8,6 @@ struct ssl_stream; struct ssl_mgr; -typedef void ssl_stream_new_cb(struct ssl_stream *, void* u_para); -typedef void ssl_stream_free_cb(struct ssl_stream *, void* u_para); - -struct ssl_mgr * ssl_manager_init(const char * ini_profile, const char * section, struct event_base * ev_base_gc, - void * logger); -//, ssl_stream_new_cb* new_func, ssl_stream_free_cb* free_func, void* u_para); -void ssl_manager_destroy(struct ssl_mgr * mgr); -unsigned long ssl_stream_log_error(struct bufferevent * bev, enum tfe_conn_dir dir, struct ssl_mgr* mgr); enum ssl_stream_action { @@ -24,7 +16,17 @@ enum ssl_stream_action SSL_ACTION_SHUTDOWN }; +typedef enum ssl_stream_action ssl_stream_new_hook(struct ssl_stream *upstream, void* u_para); + +struct ssl_mgr * ssl_manager_init(const char * ini_profile, const char * section, struct event_base * ev_base_gc, + void * logger, ssl_stream_new_hook* hook_func, void* u_para); +void ssl_manager_destroy(struct ssl_mgr * mgr); +unsigned long ssl_stream_log_error(struct bufferevent * bev, enum tfe_conn_dir dir, struct ssl_mgr* mgr); + + enum ssl_stream_action ssl_upstream_create_result_release_action(future_result_t * result); +evutil_socket_t ssl_upstream_create_result_release_fd(future_result_t * result); + struct ssl_stream * ssl_upstream_create_result_release_stream(future_result_t * result); struct bufferevent * ssl_upstream_create_result_release_bev(future_result_t * result); void ssl_async_upstream_create(struct future * f, struct ssl_mgr * mgr, evutil_socket_t fd_upstream, @@ -43,6 +45,22 @@ int ssl_manager_add_crl(struct ssl_mgr* mgr, const char* pem_file); int ssl_manager_del_crl(struct ssl_mgr* mgr, const char* pem_file); void ssl_manager_reset_trust_ca(struct ssl_mgr* mgr); -//s_stream must be upstream. -int ssl_stream_set_opt(struct ssl_stream *s_stream, enum SSL_STREAM_OPT type, const void* value, size_t size); +enum SSL_STREAM_OPT +{ + SSL_STREAM_OPT_IS_EV_CERT, //0:FALSE, 1:TRUE. + SSL_STREAM_OPT_IS_CT_CERT, //0:FALSE, 1:TRUE. + SSL_STREAM_OPT_IS_MUTUAL_AUTH, //0:FALSE, 1:TRUE. + SSL_STREAM_OPT_PINNING_STATUS, //0:FALSE, 1:TRUE. + SSL_STREAM_OPT_NO_VERIFY_SELF_SIGNED, //VALUE is an interger, SIZE=sizeof(int). 1:ON, 0:OFF. DEFAULT:0. + SSL_STREAM_OPT_NO_VERIFY_COMMON_NAME, //VALUE is an interger, SIZE=sizeof(int). 1:ON, 0:OFF. DEFAULT:1. + SSL_STREAM_OPT_NO_VERIFY_ISSUER, //VALUE is an interger, SIZE=sizeof(int). 1:ON, 0:OFF. DEFAULT:0. + SSL_STREAM_OPT_NO_VERIFY_EXPIRY_DATE, //VALUE is an interger, SIZE=sizeof(int). 1:ON, 0:OFF. DEFAULT:0. + SST_STREAM_OPT_VERIFY_FAIL_ACTION, //VALUE is an interger, SIZE=sizeof(int). 1:PASSTHROUGH, 0:BLOCK. DEFAULT:1. + SSL_STREAM_OPT_PROTOCOL_MIN_VERSION, + SSL_STREAM_OPT_PROTOCOL_MAX_VERSION +}; + +//s_stream must be upstream. +int ssl_stream_set_integer_opt(struct ssl_stream *upstream, enum SSL_STREAM_OPT opt_type, int opt_val); +int ssl_stream_get_integer_opt(struct ssl_stream *upstream, enum SSL_STREAM_OPT opt_type, int *opt_val); diff --git a/platform/src/proxy.cpp b/platform/src/proxy.cpp index d4915c9..1dfc6a8 100644 --- a/platform/src/proxy.cpp +++ b/platform/src/proxy.cpp @@ -335,6 +335,8 @@ int tfe_stat_init(struct tfe_proxy * proxy, const char * profile) proxy->fs_handle = fs_handle; return 0; } +extern struct ssl_policy_enforcer* ssl_policy_enforcer_create(void); +extern enum ssl_stream_action ssl_policy_enforce(struct ssl_stream *upstream, void* u_para); int main(int argc, char * argv[]) { @@ -382,8 +384,10 @@ int main(int argc, char * argv[]) g_default_proxy->gcev = event_new(g_default_proxy->evbase, -1, EV_PERSIST, __gc_handler_cb, g_default_proxy); CHECK_OR_EXIT(g_default_proxy->gcev, "Failed at creating GC event. Exit. "); + /* SSL INIT */ - g_default_proxy->ssl_mgr_handler = ssl_manager_init(main_profile, "ssl", g_default_proxy->evbase, g_default_logger); + g_default_proxy->ssl_mgr_handler = ssl_manager_init(main_profile, "ssl", g_default_proxy->evbase, g_default_logger, + ssl_policy_enforce, ssl_policy_enforcer_create()); CHECK_OR_EXIT(g_default_proxy->ssl_mgr_handler, "Failed at init SSL manager. Exit."); for (size_t i = 0; i < (sizeof(signals) / sizeof(int)); i++) diff --git a/platform/src/ssl_policy.cpp b/platform/src/ssl_policy.cpp new file mode 100644 index 0000000..f483a4b --- /dev/null +++ b/platform/src/ssl_policy.cpp @@ -0,0 +1,30 @@ +#include +#include +struct ssl_policy_enforcer +{ + +}; + +struct ssl_policy_enforcer* ssl_policy_enforcer_create(void) +{ + return NULL; +} +enum ssl_stream_action ssl_policy_enforce(struct ssl_stream *upstream, void* u_para) +{ + UNUSED struct ssl_policy_enforcer* enforcer=(struct ssl_policy_enforcer*)u_para; + UNUSED int ret=0; + int pinning_staus=0, is_ev=0; + ret=ssl_stream_get_integer_opt(upstream, SSL_STREAM_OPT_PINNING_STATUS, &pinning_staus); + assert(ret==1); + ret=ssl_stream_get_integer_opt(upstream, SSL_STREAM_OPT_IS_EV_CERT, &is_ev); + assert(ret==1); + if(pinning_staus>0||is_ev) + { + return SSL_ACTION_PASSTHROUGH; + } + else + { + return SSL_ACTION_INTERCEPT; + } +} + diff --git a/platform/src/ssl_policy.h b/platform/src/ssl_policy.h new file mode 100644 index 0000000..9428323 --- /dev/null +++ b/platform/src/ssl_policy.h @@ -0,0 +1,6 @@ +#pragma once +#include +struct ssl_policy_enforcer; +struct ssl_policy_enforcer* ssl_policy_enforcer_create(void); +enum ssl_stream_action ssl_policy_enforce(struct ssl_stream *upstream, void* u_para); + diff --git a/platform/src/ssl_sess_cache.cpp b/platform/src/ssl_sess_cache.cpp index 991bc90..52b57a8 100644 --- a/platform/src/ssl_sess_cache.cpp +++ b/platform/src/ssl_sess_cache.cpp @@ -17,6 +17,7 @@ struct asn1_sess { unsigned char * buff; size_t size; + int version; }; struct sess_set_args @@ -24,6 +25,11 @@ struct sess_set_args MESA_htable_handle hash; struct asn1_sess * new_sess; }; +struct sess_get_args +{ + SSL_SESSION *sess; + int version; +}; struct sess_cache { @@ -41,7 +47,7 @@ static void ssl_sess_free_serialized(void * data) return; } -static struct asn1_sess * ssl_sess_serialize(SSL_SESSION * sess) +static struct asn1_sess * ssl_sess_serialize(SSL_SESSION * sess, int version) { struct asn1_sess * result = ALLOC(struct asn1_sess, 1); @@ -62,6 +68,7 @@ static struct asn1_sess * ssl_sess_serialize(SSL_SESSION * sess) j=i2d_SSL_SESSION(sess, &(temp)); assert(i == j); assert(result->buff + i == temp); + result->version=version; return result; } @@ -101,6 +108,8 @@ static int ssl_sess_verify_cb(void * data, int eliminate_type) static long sess_cache_get_cb(void * data, const uchar * key, uint size, void * user_arg) { + struct sess_get_args *result=(struct sess_get_args *)user_arg; + SSL_SESSION * sess = NULL; int is_valid = 0; if (data == NULL) @@ -119,7 +128,8 @@ static long sess_cache_get_cb(void * data, const uchar * key, uint size, void * } else { - *(SSL_SESSION **) user_arg = sess; + result->sess=sess; + result->version=asn1->version; return SESS_CACHE_FOUND; } } @@ -137,6 +147,7 @@ static long sess_cache_set_cb(void * data, const uchar * key, uint size, void * cur_asn1->size = new_asn1->size; cur_asn1->buff = ALLOC(unsigned char, cur_asn1->size); memcpy(cur_asn1->buff, new_asn1->buff, cur_asn1->size); + cur_asn1->version=new_asn1->version; return SESS_CACHE_UPDATE_OLD; } else @@ -178,16 +189,20 @@ static size_t upsess_mk_key(struct sockaddr * res, socklen_t addrlen, const char } void up_session_set(struct sess_cache * cache, struct sockaddr * addr, socklen_t addr_len, const char * sni, - SSL_SESSION * sess) + int version, SSL_SESSION * sess) { unsigned char * key = NULL; size_t key_size = 0; long cb_ret = 0; assert(cache->served_for == CONN_DIR_UPSTREAM); + if(!SSL_SESSION_is_resumable(sess)) + { + return; + } key_size = upsess_mk_key(addr, addr_len, sni, &key); struct asn1_sess * asn1 = NULL; - asn1 = ssl_sess_serialize(sess); + asn1 = ssl_sess_serialize(sess, version); struct sess_set_args set_args={.hash = cache->hash, .new_sess = asn1}; MESA_htable_search_cb(cache->hash, key, key_size, sess_cache_set_cb, &set_args, &cb_ret); @@ -200,9 +215,9 @@ void up_session_set(struct sess_cache * cache, struct sockaddr * addr, socklen_t return; } -SSL_SESSION * up_session_get(struct sess_cache * cache, struct sockaddr * addr, socklen_t addr_len, const char * sni) -{ - SSL_SESSION * sess = NULL; +SSL_SESSION * up_session_get(struct sess_cache * cache, struct sockaddr * addr, socklen_t addr_len, const char * sni, int min_ver, int max_ver) +{ + struct sess_get_args args={NULL, 0}; long cb_ret = 0; size_t key_size = 0; @@ -210,14 +225,14 @@ SSL_SESSION * up_session_get(struct sess_cache * cache, struct sockaddr * addr, unsigned char * key = NULL; key_size = upsess_mk_key(addr, addr_len, sni, &key); - MESA_htable_search_cb(cache->hash, key, key_size, sess_cache_get_cb, &sess, &cb_ret); + MESA_htable_search_cb(cache->hash, key, key_size, sess_cache_get_cb, &args, &cb_ret); // printf("%s %s\n", __FUNCTION__, key); free(key); key = NULL; - if (cb_ret == SESS_CACHE_FOUND) + if (cb_ret == SESS_CACHE_FOUND && args.version>=min_ver && args.version<=max_ver) { ATOMIC_INC(&(cache->hit_cnt)); - return sess; + return args.sess; } else { @@ -232,7 +247,7 @@ void down_session_set(struct sess_cache * cache, const SSL_SESSION * sess) struct asn1_sess * asn1 = NULL; long cb_ret = 0; assert(cache->served_for == CONN_DIR_DOWNSTREAM); - asn1 = ssl_sess_serialize((SSL_SESSION *) sess); + asn1 = ssl_sess_serialize((SSL_SESSION *) sess, 0); /* * SSL_SESSION_get_id() returns a pointer to the internal session id value for the session s. diff --git a/platform/src/ssl_stream.cpp b/platform/src/ssl_stream.cpp index fc17a5b..c86e6e8 100644 --- a/platform/src/ssl_stream.cpp +++ b/platform/src/ssl_stream.cpp @@ -134,6 +134,8 @@ struct ssl_mgr struct sess_cache * down_sess_cache; struct sess_cache * up_sess_cache; struct ssl_service_cache* svc_cache; + ssl_stream_new_hook* on_new_hook_func; + void* hook_u_para; struct session_ticket_key ticket_key; char default_ciphers[TFE_SYMBOL_MAX]; @@ -165,7 +167,7 @@ struct __ssl_stream_debug { evutil_socket_t fd; }; -struct ssl_bypass +struct ssl_bypass_condition { char bypass_ev_cert; char bypass_ct_cert; @@ -177,10 +179,10 @@ struct ssl_upstream_parts struct cert_verify_param verify_param; struct cert_verify_result verify_result; - char verify_failed_action; + char block_fake_cert; struct ssl_service_status svc_status; + enum ssl_stream_action action; - struct ssl_bypass bypass_condition; struct ssl_chello * client_hello; int is_server_cert_verify_passed; }; @@ -198,6 +200,7 @@ struct ssl_stream struct ssl_upstream_parts up_parts; struct ssl_downstream_parts down_parts; }; + int ssl_min_ver, ssl_max_ver; const unsigned char* alpn_selected; //reference to SSL_ALPN_HTTP_2/SSL_ALPN_HTTP_1_1 struct ssl_stream* peer; struct __ssl_stream_debug _do_not_use; @@ -417,13 +420,13 @@ struct ssl_stream * ssl_stream_new(struct ssl_mgr * mgr, evutil_socket_t fd, enu { case CONN_DIR_DOWNSTREAM: ATOMIC_INC(&(s_stream->mgr->stat_val[SSL_DOWN_NEW])); - s_stream->ssl = downstream_ssl_create(mgr, kyr, selected_alpn); s_stream->down_parts.keyring = kyr; + s_stream->ssl = downstream_ssl_create(mgr, kyr, selected_alpn); break; case CONN_DIR_UPSTREAM: ATOMIC_INC(&(s_stream->mgr->stat_val[SSL_UP_NEW])); s_stream->up_parts.verify_param.no_verify_expiry_date=1; - s_stream->up_parts.client_hello = client_hello; + s_stream->up_parts.client_hello = client_hello; s_stream->ssl = upstream_ssl_create(mgr, s_stream, fd); break; default: assert(0); @@ -552,8 +555,8 @@ void ssl_manager_destroy(struct ssl_mgr * mgr) } -struct ssl_mgr * ssl_manager_init(const char * ini_profile, const char * section, - struct event_base * ev_base_gc, void * logger) +struct ssl_mgr * ssl_manager_init(const char * ini_profile, const char * section, + struct event_base * ev_base_gc, void * logger, ssl_stream_new_hook* hook_func, void* hook_u_para) { unsigned char key_name[]="!mesalab-tfe3a~&"; unsigned char aes_key_def[]={0xC5,0xAC,0xC1,0xA6,0xB2,0xBB,0xCA,0xC7,0xE3,0xBE,0xE3,0xB2,0xC6,0xA3,0xB1,0xB9 @@ -622,7 +625,8 @@ struct ssl_mgr * ssl_manager_init(const char * ini_profile, const char * section mgr->down_sess_cache = ssl_sess_cache_create(mgr->cache_slots, mgr->sess_expire_seconds, CONN_DIR_DOWNSTREAM); } mgr->svc_cache=ssl_service_cache_create(mgr->cache_slots, mgr->sess_expire_seconds); - + mgr->on_new_hook_func=hook_func; + mgr->hook_u_para=hook_u_para; //Reference to NGINX: http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_session_ticket_key //Support key rotation in futher. @@ -863,7 +867,8 @@ static SSL * upstream_ssl_create(struct ssl_mgr * mgr, struct ssl_stream* s_stre if(ret == 0) { /* session resuming based on remote endpoint address and port */ - sess = up_session_get(mgr->up_sess_cache, (struct sockaddr *) &addr, addrlen, chello->sni); + sess = up_session_get(mgr->up_sess_cache, (struct sockaddr *) &addr, addrlen, chello->sni, + SSL_get_min_proto_version(ssl), SSL_get_max_proto_version(ssl)); if (sess) { SSL_set_session(ssl, sess); /* increments sess refcount */ @@ -904,6 +909,16 @@ void wrap_ssl_connect_server_ctx_free(void *p) struct ssl_connect_server_ctx * ctx = (struct ssl_connect_server_ctx *)p; ssl_connect_server_ctx_free(ctx); } +enum ssl_stream_action ssl_upstream_create_result_release_action(future_result_t * result) +{ + struct ssl_connect_server_ctx * ctx = (struct ssl_connect_server_ctx *) result; + return ctx->s_stream->up_parts.action; +} +evutil_socket_t ssl_upstream_create_result_release_fd(future_result_t * result) +{ + struct ssl_connect_server_ctx * ctx = (struct ssl_connect_server_ctx *) result; + return ctx->fd_upstream; +} struct ssl_stream * ssl_upstream_create_result_release_stream(future_result_t * result) { @@ -1105,6 +1120,10 @@ static void ssl_server_connected_eventcb(struct bufferevent * bev, short events, s_stream->up_parts.verify_result.is_hostmatched, s_stream->up_parts.verify_result.is_ct, s_stream->up_parts.verify_result.is_ev); + if((!s_stream->up_parts.is_server_cert_verify_passed || !s_stream->up_parts.verify_result.is_hostmatched) && s_stream->up_parts.block_fake_cert) + { + s_stream->up_parts.action=SSL_ACTION_SHUTDOWN; + } } if(s_stream->up_parts.is_server_cert_verify_passed) { @@ -1114,7 +1133,7 @@ static void ssl_server_connected_eventcb(struct bufferevent * bev, short events, //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_upstream->client_hello->sni, ssl_sess); + ctx->addrlen, s_upstream->client_hello->sni, SSL_version(s_stream->ssl), ssl_sess); } } else @@ -1161,10 +1180,10 @@ static void ssl_server_connected_eventcb(struct bufferevent * bev, short events, static void peek_chello_on_succ(future_result_t * result, void * user) { struct promise * p = (struct promise *) user; - struct ssl_connect_server_ctx * ctx = (struct ssl_connect_server_ctx *) promise_get_ctx(p); + struct ssl_connect_server_ctx* ctx = (struct ssl_connect_server_ctx *) promise_get_ctx(p); struct event_base* evbase=tfe_proxy_get_work_thread_evbase(ctx->thread_id); - - struct ssl_chello * chello = ssl_peek_result_release_chello(result);//chello has been saved in ssl_stream. + struct ssl_stream* s_stream=NULL; + struct ssl_chello* chello = ssl_peek_result_release_chello(result);//chello has been saved in ssl_stream. if(chello->sni==NULL) { ATOMIC_INC(&(ctx->mgr->stat_val[SSL_NO_SNI])); @@ -1172,8 +1191,8 @@ static void peek_chello_on_succ(future_result_t * result, void * user) int ret=0; struct ssl_service_status* svc_status=NULL; clock_gettime(CLOCK_MONOTONIC, &(ctx->start)); - ctx->s_stream = ssl_stream_new(ctx->mgr, ctx->fd_upstream, CONN_DIR_UPSTREAM, chello, NULL, NULL); - svc_status=&ctx->s_stream->up_parts.svc_status; + s_stream= ssl_stream_new(ctx->mgr, ctx->fd_upstream, CONN_DIR_UPSTREAM, chello, NULL, NULL); + svc_status=&s_stream->up_parts.svc_status; ret=ssl_service_cache_read(ctx->mgr->svc_cache, chello, svc_status); if(ret==1) { @@ -1184,15 +1203,25 @@ static void peek_chello_on_succ(future_result_t * result, void * user) svc_status->is_ct, svc_status->is_ev); } - ctx->bev = bufferevent_openssl_socket_new(evbase, ctx->fd_upstream, - ctx->s_stream->ssl, BUFFEREVENT_SSL_CONNECTING, BEV_OPT_DEFER_CALLBACKS | BEV_OPT_THREADSAFE ); + s_stream->up_parts.action=ctx->mgr->on_new_hook_func(s_stream, ctx->mgr->hook_u_para); + ctx->s_stream = s_stream; + if(s_stream->up_parts.action==SSL_ACTION_PASSTHROUGH) + { + promise_success(p, ctx); + wrap_ssl_connect_server_ctx_free(ctx); + } + else + { + ctx->bev = bufferevent_openssl_socket_new(evbase, ctx->fd_upstream, + ctx->s_stream->ssl, BUFFEREVENT_SSL_CONNECTING, BEV_OPT_DEFER_CALLBACKS | BEV_OPT_THREADSAFE ); - bufferevent_openssl_set_allow_dirty_shutdown(ctx->bev, 1); - bufferevent_setcb(ctx->bev, NULL, NULL, ssl_server_connected_eventcb, p); - bufferevent_enable(ctx->bev, EV_READ | EV_WRITE); //waiting for connect event only + bufferevent_openssl_set_allow_dirty_shutdown(ctx->bev, 1); + bufferevent_setcb(ctx->bev, NULL, NULL, ssl_server_connected_eventcb, p); + bufferevent_enable(ctx->bev, EV_READ | EV_WRITE); //waiting for connect event only - future_destroy(ctx->f_peek_chello); - ctx->f_peek_chello = NULL; + future_destroy(ctx->f_peek_chello); + ctx->f_peek_chello = NULL; + } return; } @@ -1316,7 +1345,7 @@ static int ossl_session_ticket_key_callback(SSL *ssl_conn, * the refcount decrementing. In other words, return 0 if we did not * keep a pointer to the object (which we never do here). */ -static int ossl_sessnew_cb(SSL * ssl, SSL_SESSION * sess) +static int ossl_downsess_new_cb(SSL * ssl, SSL_SESSION * sess) { struct ssl_mgr * mgr = (struct ssl_mgr *) SSL_get_ex_data(ssl, SSL_CTX_EX_DATA_IDX_SSLMGR); @@ -1343,7 +1372,7 @@ static int ossl_sessnew_cb(SSL * ssl, SSL_SESSION * sess) * OpenSSL calls SSL_SESSION_free() after calling the callback; * we do not need to free the reference here. */ -static void ossl_sessremove_cb(SSL_CTX * sslctx, SSL_SESSION * sess) +static void ossl_downsess_remove_cb(SSL_CTX * sslctx, SSL_SESSION * sess) { struct ssl_mgr * mgr = (struct ssl_mgr *) SSL_CTX_get_ex_data(sslctx, SSL_CTX_EX_DATA_IDX_SSLMGR); assert(mgr != NULL); @@ -1360,7 +1389,7 @@ static void ossl_sessremove_cb(SSL_CTX * sslctx, SSL_SESSION * sess) * Called by OpenSSL when a src SSL session is requested by the client. OPENSSL_VERSION_NUMBER >= 0x10100000L required. */ -static SSL_SESSION * ossl_sessget_cb(SSL * ssl, const unsigned char * id, int idlen, int * copy) +static SSL_SESSION * ossl_downsess_get_cb(SSL * ssl, const unsigned char * id, int idlen, int * copy) { struct ssl_mgr * mgr = (struct ssl_mgr *) SSL_get_ex_data(ssl, SSL_CTX_EX_DATA_IDX_SSLMGR); SSL_SESSION * sess=NULL; @@ -1470,9 +1499,9 @@ static SSL * downstream_ssl_create(struct ssl_mgr * mgr, struct keyring * crt, c } } - SSL_CTX_sess_set_new_cb(sslctx, ossl_sessnew_cb); - SSL_CTX_sess_set_remove_cb(sslctx, ossl_sessremove_cb); - SSL_CTX_sess_set_get_cb(sslctx, ossl_sessget_cb); + SSL_CTX_sess_set_new_cb(sslctx, ossl_downsess_new_cb); + SSL_CTX_sess_set_remove_cb(sslctx, ossl_downsess_remove_cb); + SSL_CTX_sess_set_get_cb(sslctx, ossl_downsess_get_cb); if(!mgr->no_sessticket) { SSL_CTX_set_tlsext_ticket_key_cb(sslctx, ossl_session_ticket_key_callback); @@ -1652,7 +1681,8 @@ void ask_keyring_on_succ(void * result, void * user) kyr = key_keeper_release_keyring(result); //kyr will be freed at ssl downstream closing. clock_gettime(CLOCK_MONOTONIC, &(ctx->start)); - ctx->downstream = ssl_stream_new(mgr, ctx->fd_downstream, CONN_DIR_DOWNSTREAM, NULL, kyr, + ctx->downstream = ssl_stream_new(mgr, ctx->fd_downstream, CONN_DIR_DOWNSTREAM, + ctx->origin_ssl->up_parts.client_hello, kyr, ctx->origin_ssl?ctx->origin_ssl->alpn_selected:NULL); ctx->downstream->peer=ctx->origin_ssl; ctx->bev_down = bufferevent_openssl_socket_new(evbase, ctx->fd_downstream, ctx->downstream->ssl, @@ -1877,4 +1907,57 @@ void ssl_manager_reset_trust_ca(struct ssl_mgr* mgr) ssl_trusted_cert_storage_reset(mgr->trust_CA_store); return; } +int ssl_stream_set_integer_opt(struct ssl_stream *upstream, enum SSL_STREAM_OPT opt_type, int opt_val) +{ + struct cert_verify_param *verify_param=&(upstream->up_parts.verify_param); + + switch(opt_type) + { + case SSL_STREAM_OPT_NO_VERIFY_SELF_SIGNED: + verify_param->no_verify_self_signed=opt_val; + break; + case SSL_STREAM_OPT_NO_VERIFY_COMMON_NAME: + verify_param->no_verify_cn=opt_val; + break; + case SSL_STREAM_OPT_NO_VERIFY_ISSUER: + verify_param->no_verify_issuer=opt_val; + break; + case SSL_STREAM_OPT_NO_VERIFY_EXPIRY_DATE: + verify_param->no_verify_expiry_date=opt_val; + break; + case SST_STREAM_OPT_VERIFY_FAIL_ACTION: + upstream->up_parts.block_fake_cert=opt_val; + break; + case SSL_STREAM_OPT_PROTOCOL_MIN_VERSION: + case SSL_STREAM_OPT_PROTOCOL_MAX_VERSION: + break; + default: + return 0; + + } + return 1; +} +int ssl_stream_get_integer_opt(struct ssl_stream *upstream, enum SSL_STREAM_OPT opt_type, int *opt_val) +{ + struct ssl_service_status* svc=&upstream->up_parts.svc_status; + switch(opt_type) + { + case SSL_STREAM_OPT_IS_EV_CERT: + *opt_val=svc->is_ev; + break; + case SSL_STREAM_OPT_IS_CT_CERT: + *opt_val=svc->is_ct; + break; + case SSL_STREAM_OPT_IS_MUTUAL_AUTH: + *opt_val=svc->is_mutual_auth; + break; + case SSL_STREAM_OPT_PINNING_STATUS: + *opt_val=svc->pinning_status; + break; + default: + return 0; + } + return 1; + +} diff --git a/platform/src/tcp_stream.cpp b/platform/src/tcp_stream.cpp index 83f00b2..49dd2f2 100644 --- a/platform/src/tcp_stream.cpp +++ b/platform/src/tcp_stream.cpp @@ -341,6 +341,10 @@ int tfe_stream_action_set_opt(const struct tfe_stream * stream, enum tfe_stream_ return 0; } +int tfe_stream_set_integer_opt(struct tfe_stream * stream, enum tfe_stream_opt_level level, int type, int val) +{ + return 1; +} /* ==================================================================================================================== * CONNECTION STRUCTURE AND OPERATION FUCTIONS * ===================================================================================================================*/ @@ -795,7 +799,15 @@ static tfe_conn_private * __conn_private_create_by_bev(struct tfe_stream_private __conn_private->bev = bev; __conn_private->fd = bufferevent_getfd(bev); - bufferevent_setcb(__conn_private->bev, __stream_bev_readcb, __stream_bev_writecb, __stream_bev_eventcb, stream); + if(stream->tcp_passthough) + { + bufferevent_setcb(__conn_private->bev, __stream_bev_passthrough_readcb, + __stream_bev_passthrough_writecb, __stream_bev_passthrough_eventcb, stream); + } + else + { + bufferevent_setcb(__conn_private->bev, __stream_bev_readcb, __stream_bev_writecb, __stream_bev_eventcb, stream); + } bufferevent_disable(__conn_private->bev, EV_READ | EV_WRITE); struct tfe_proxy * proxy_ref = stream->proxy_ref; @@ -825,7 +837,7 @@ static tfe_conn_private * __conn_private_create_by_fd(struct tfe_stream_private goto __errout; } - if (stream->passthough) + if (stream->tcp_passthough) { bufferevent_setcb(__conn_private->bev, __stream_bev_passthrough_readcb, __stream_bev_passthrough_writecb, __stream_bev_passthrough_eventcb, stream); @@ -896,28 +908,43 @@ void ssl_downstream_create_on_fail(enum e_future_error err, const char * what, v void ssl_upstream_create_on_success(future_result_t * result, void * user) { struct tfe_stream_private * _stream = (struct tfe_stream_private *) user; + evutil_socket_t fd=-1; + enum ssl_stream_action ssl_action=ssl_upstream_create_result_release_action(result); + if(SSL_ACTION_PASSTHROUGH==ssl_action) + { + _stream->tcp_passthough=1; + fd=ssl_upstream_create_result_release_fd(result); + _stream->conn_upstream=__conn_private_create_by_fd(_stream, fd); + _stream->conn_downstream=__conn_private_create_by_fd(_stream, _stream->defer_fd_downstream); + } + else if(SSL_ACTION_SHUTDOWN==ssl_action) + { + tfe_stream_destory(_stream); + } + else + { + struct ssl_stream * upstream = ssl_upstream_create_result_release_stream(result); + struct bufferevent * bev = ssl_upstream_create_result_release_bev(result); + assert(upstream != NULL && bev != NULL); - struct ssl_stream * upstream = ssl_upstream_create_result_release_stream(result); - struct bufferevent * bev = ssl_upstream_create_result_release_bev(result); - assert(upstream != NULL && bev != NULL); + /* Create connection ctx by bev */ + _stream->conn_upstream = __conn_private_create_by_bev(_stream, bev); + _stream->ssl_upstream = upstream; - /* Create connection ctx by bev */ - _stream->conn_upstream = __conn_private_create_by_bev(_stream, bev); - _stream->ssl_upstream = upstream; + assert(_stream->conn_upstream != NULL); + assert(_stream->ssl_upstream != NULL); - assert(_stream->conn_upstream != NULL); - assert(_stream->ssl_upstream != NULL); + future_destroy(_stream->future_upstream_create); + _stream->future_upstream_create = NULL; + _stream->defer_fd_upstream = 0; - future_destroy(_stream->future_upstream_create); - _stream->future_upstream_create = NULL; - _stream->defer_fd_upstream = 0; + /* Next, create downstream */ + _stream->future_downstream_create = future_create("ssl_down", ssl_downstream_create_on_success, + ssl_downstream_create_on_fail, _stream); - /* Next, create downstream */ - _stream->future_downstream_create = future_create("ssl_down", ssl_downstream_create_on_success, - ssl_downstream_create_on_fail, _stream); - - ssl_async_downstream_create(_stream->future_downstream_create, _stream->ssl_mgr, - _stream->ssl_upstream, _stream->defer_fd_downstream, _stream->keyring_id, _stream->thread_ref->thread_id); + ssl_async_downstream_create(_stream->future_downstream_create, _stream->ssl_mgr, + _stream->ssl_upstream, _stream->defer_fd_downstream, _stream->keyring_id, _stream->thread_ref->thread_id); + } } void ssl_upstream_create_on_fail(enum e_future_error err, const char * what, void * user) @@ -948,7 +975,7 @@ struct tfe_stream * tfe_stream_create(struct tfe_proxy * pxy, struct tfe_thread_ void __stream_access_log_write(struct tfe_stream_private * stream) { - const char * str_passthrough = stream->passthough ? "PASSTHROUGH" : "-"; + const char * str_passthrough = stream->tcp_passthough ? "PASSTHROUGH" : "-"; const char * str_kill = stream->need_to_be_kill ? "KILL" : "-"; char str_log_event[TFE_STRING_MAX] = ""; @@ -1259,7 +1286,7 @@ int tfe_stream_option_set(struct tfe_stream * stream, enum tfe_stream_option opt else if (opt == TFE_STREAM_OPT_PASSTHROUGH) { assert(sz_arg == sizeof(bool)); - _stream->passthough = *(bool *) arg; + _stream->tcp_passthough = *(bool *) arg; } else if (opt == TFE_STREAM_OPT_KEYRING_ID) { @@ -1300,4 +1327,4 @@ void tfe_stream_kill(const struct tfe_stream * stream) { struct tfe_stream_private * _stream = to_stream_private(stream); _stream->need_to_be_kill = true; -} \ No newline at end of file +}