diff --git a/common/include/ssl_stream.h b/common/include/ssl_stream.h index bc559e6..80510e2 100644 --- a/common/include/ssl_stream.h +++ b/common/include/ssl_stream.h @@ -22,7 +22,8 @@ enum SSL_STREAM_OPT SSL_STREAM_OPT_NO_VERIFY_EXPIRY_DATE, //VALUE is an interger, SIZE=sizeof(int). 1:ON, 0:OFF. DEFAULT:0. SSL_STREAM_OPT_BLOCK_FAKE_CERT, //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 + SSL_STREAM_OPT_PROTOCOL_MAX_VERSION, + SSL_STREAM_OPT_KEYRING_ID }; int sslver_str2num(const char * version_str); diff --git a/platform/include/internal/ssl_service_cache.h b/platform/include/internal/ssl_service_cache.h index 77a7be9..6d91517 100644 --- a/platform/include/internal/ssl_service_cache.h +++ b/platform/include/internal/ssl_service_cache.h @@ -21,4 +21,11 @@ void ssl_service_cache_destroy(struct ssl_service_cache* cache); int ssl_service_cache_read(struct ssl_service_cache* svc_cache, const struct ssl_chello* chello, struct ssl_service_status* result); void ssl_service_cache_write(struct ssl_service_cache* svc_cache, const struct ssl_chello* chello, const struct ssl_service_status* status); - +struct ssl_service_cache_statistics +{ + long long pinning_cli_cnt; + long long mutual_auth_cli_cnt; + long long ev_srv_cnt; + long long ct_srv_cnt; +}; +void ssl_service_cache_stat(struct ssl_service_cache* svc_cache, struct ssl_service_cache_statistics* result); diff --git a/platform/include/internal/ssl_stream_core.h b/platform/include/internal/ssl_stream_core.h index 47b2549..e922a6e 100644 --- a/platform/include/internal/ssl_stream_core.h +++ b/platform/include/internal/ssl_stream_core.h @@ -22,10 +22,13 @@ struct bufferevent * ssl_upstream_create_result_release_bev(future_result_t * re void ssl_async_upstream_create(struct future * f, struct ssl_mgr * mgr, evutil_socket_t fd_upstream, evutil_socket_t fd_downstream, unsigned int thread_id); + + struct ssl_stream * ssl_downstream_create_result_release_stream(future_result_t * result); struct bufferevent * ssl_downstream_create_result_release_bev(future_result_t * result); -void ssl_async_downstream_create(struct future * f, struct ssl_mgr * mgr, struct ssl_stream * upstream, - evutil_socket_t fd_downstream, int keyring_id, unsigned int thread_id); +void ssl_async_downstream_create(struct future * f, struct ssl_mgr * mgr, struct ssl_stream * upstream, + evutil_socket_t fd_downstream, unsigned int thread_id); + void ssl_stream_free_and_close_fd(struct ssl_stream * stream, struct event_base * evbase, evutil_socket_t fd); const char* ssl_stream_dump_info(struct ssl_stream *stream, char* buffer, size_t sz); //Follow functions are allowed to call during runtime. diff --git a/platform/src/ssl_service_cache.cpp b/platform/src/ssl_service_cache.cpp index 633361b..f2546a8 100644 --- a/platform/src/ssl_service_cache.cpp +++ b/platform/src/ssl_service_cache.cpp @@ -6,31 +6,64 @@ #define FAIL_AS_PINNING_COUNT 4 #define FAIL_AS_PINNING_TIME 30 -struct ssl_service_client_st +struct ssl_svc_client_st { time_t last_update_time; unsigned int fail_count; char is_mutual_auth; + struct ssl_service_cache* ref_svc_cache; }; -struct ssl_service_server_st +struct ssl_svc_server_st { char is_ev; char is_ct; long long ev_st_switched; long long ct_st_switched; + struct ssl_service_cache* ref_svc_cache; }; struct ssl_service_cache { MESA_htable_handle cli_st_hash; MESA_htable_handle srv_st_hash; - long long pinning_cli_cnt, mutual_auth_cli_cnt, ev_srv_cnt, ct_srv_cnt; + struct ssl_service_cache_statistics stat; }; struct ssl_service_write_args { struct ssl_service_cache* cache; const struct ssl_service_status* status; }; -static size_t ssl_service_client_st_mk_key(const struct ssl_chello* chello, char* key_buff, size_t sz) +static void ssl_svc_free_client_st(void * data) +{ + struct ssl_svc_client_st* p = (struct ssl_svc_client_st *) data; + struct ssl_service_cache* svc_cache=p->ref_svc_cache; + if(p->is_mutual_auth) + { + svc_cache->stat.mutual_auth_cli_cnt--; + } + if(p->fail_count>=FAIL_AS_PINNING_COUNT) + { + svc_cache->stat.pinning_cli_cnt--; + } + free(p); + return; +} +static void ssl_svc_free_server_st(void * data) +{ + struct ssl_svc_server_st* p = (struct ssl_svc_server_st *) data; + struct ssl_service_cache* svc_cache=p->ref_svc_cache; + if(p->is_ct) + { + svc_cache->stat.ct_srv_cnt--; + } + if(p->is_ev) + { + svc_cache->stat.ev_srv_cnt--; + } + free(p); + return; +} + +static size_t ssl_svc_client_st_mk_key(const struct ssl_chello* chello, char* key_buff, size_t sz) { size_t key_sz=0; key_sz=snprintf(key_buff, sz, "%d.%d-%d.%d:%s:%s:%s:%s", chello->min_version.major, chello->min_version.minor, @@ -40,7 +73,7 @@ static size_t ssl_service_client_st_mk_key(const struct ssl_chello* chello, char } static long cli_st_read_cb(void * data, const uchar * key, uint size, void * user_arg) { - struct ssl_service_client_st* cli_st=(struct ssl_service_client_st*)data; + struct ssl_svc_client_st* cli_st=(struct ssl_svc_client_st*)data; struct ssl_service_status* result=(struct ssl_service_status*)user_arg; if (cli_st == NULL) @@ -64,7 +97,7 @@ static long cli_st_read_cb(void * data, const uchar * key, uint size, void * use } static long cli_st_write_cb(void * data, const uchar * key, uint size, void * user_arg) { - struct ssl_service_client_st* cli_st=(struct ssl_service_client_st*)data; + struct ssl_svc_client_st* cli_st=(struct ssl_svc_client_st*)data; struct ssl_service_write_args* args=(struct ssl_service_write_args*)user_arg; const struct ssl_service_status* status=args->status; struct ssl_service_cache* cache=args->cache; @@ -72,7 +105,8 @@ static long cli_st_write_cb(void * data, const uchar * key, uint size, void * us time_t now=time(NULL); if(cli_st==NULL) { - cli_st=ALLOC(struct ssl_service_client_st, 1); + cli_st=ALLOC(struct ssl_svc_client_st, 1); + cli_st->ref_svc_cache=cache; ret = MESA_htable_add(cache->cli_st_hash, key, size, cli_st); assert(ret >= 0); } @@ -93,7 +127,7 @@ static long cli_st_write_cb(void * data, const uchar * key, uint size, void * us cli_st->last_update_time=now; if(cli_st->fail_count==FAIL_AS_PINNING_COUNT) { - cache->pinning_cli_cnt++; + cache->stat.pinning_cli_cnt++; } } else if(status->pinning_status==PINNING_ST_PINNING) @@ -104,7 +138,7 @@ static long cli_st_write_cb(void * data, const uchar * key, uint size, void * us if(status->is_mutual_auth==1&&cli_st->is_mutual_auth==0) { - cache->mutual_auth_cli_cnt++; + cache->stat.mutual_auth_cli_cnt++; cli_st->is_mutual_auth=1; } return 1; @@ -112,7 +146,7 @@ static long cli_st_write_cb(void * data, const uchar * key, uint size, void * us static long srv_st_read_cb(void * data, const uchar * key, uint size, void * user_arg) { - struct ssl_service_server_st* srv_st=(struct ssl_service_server_st*)data; + struct ssl_svc_server_st* srv_st=(struct ssl_svc_server_st*)data; struct ssl_service_status* result=(struct ssl_service_status*)user_arg; if (srv_st == NULL) { @@ -124,21 +158,22 @@ static long srv_st_read_cb(void * data, const uchar * key, uint size, void * use } static long srv_st_write_cb(void * data, const uchar * key, uint size, void * user_arg) { - struct ssl_service_server_st* srv_st=(struct ssl_service_server_st*)data; + struct ssl_svc_server_st* srv_st=(struct ssl_svc_server_st*)data; struct ssl_service_write_args* args=(struct ssl_service_write_args*)user_arg; const struct ssl_service_status* status=args->status; struct ssl_service_cache* cache=args->cache; UNUSED int ret = 0; if(srv_st==NULL) { - srv_st=ALLOC(struct ssl_service_server_st, 1); + srv_st=ALLOC(struct ssl_svc_server_st, 1); + srv_st->ref_svc_cache=cache; ret = MESA_htable_add(cache->srv_st_hash, key, size, srv_st); assert(ret >= 0); } if(status->is_ev==1&&srv_st->is_ev==0) { srv_st->is_ev=1; - cache->ev_srv_cnt++; + cache->stat.ev_srv_cnt++; } if(status->is_ev!=srv_st->is_ev) { @@ -147,7 +182,7 @@ static long srv_st_write_cb(void * data, const uchar * key, uint size, void * us if(status->is_ct==1&&srv_st->is_ct==0) { srv_st->is_ct=1; - cache->ct_srv_cnt++; + cache->stat.ct_srv_cnt++; } if(status->is_ct!=srv_st->is_ct) { @@ -166,7 +201,7 @@ int ssl_service_cache_read(struct ssl_service_cache* svc_cache, const struct ssl { return 0; } - cli_st_key_sz=ssl_service_client_st_mk_key(chello, cli_st_key, sizeof(cli_st_key)); + cli_st_key_sz=ssl_svc_client_st_mk_key(chello, cli_st_key, sizeof(cli_st_key)); MESA_htable_search_cb(svc_cache->cli_st_hash, (unsigned char*) cli_st_key, (unsigned int) cli_st_key_sz, cli_st_read_cb, result, &cli_st_cb_ret); MESA_htable_search_cb(svc_cache->srv_st_hash, (unsigned char*) chello->sni, (unsigned int) strlen(chello->sni), srv_st_read_cb, result, &svr_st_cb_ret); if(cli_st_cb_ret||svr_st_cb_ret) @@ -191,7 +226,7 @@ void ssl_service_cache_write(struct ssl_service_cache* svc_cache, const struct s struct ssl_service_write_args write_args={svc_cache, status}; if(status->is_mutual_auth||status->pinning_status!=PINNING_ST_NOT_PINNING) { - cli_st_key_sz=ssl_service_client_st_mk_key(chello, cli_st_key, sizeof(cli_st_key)); + cli_st_key_sz=ssl_svc_client_st_mk_key(chello, cli_st_key, sizeof(cli_st_key)); MESA_htable_search_cb(svc_cache->cli_st_hash, (unsigned char*)cli_st_key, (unsigned int) cli_st_key_sz, cli_st_write_cb, &write_args, &cli_st_cb_ret); } if(status->is_ct||status->is_ev) @@ -206,6 +241,7 @@ struct ssl_service_cache* ssl_service_cache_create(unsigned int slot_size, unsig UNUSED int ret = 0; MESA_htable_handle htable=NULL, saved[2]; int i=0, opt_val=0; + void (*free_func[])(void *)={ssl_svc_free_client_st, ssl_svc_free_server_st}; for(i=0; i<2; i++) { htable = MESA_htable_born(); @@ -223,7 +259,7 @@ struct ssl_service_cache* ssl_service_cache_create(unsigned int slot_size, unsig ret = MESA_htable_set_opt(htable, MHO_ELIMIMINATE_TYPE, &opt_val, sizeof(int)); ret = MESA_htable_set_opt(htable, MHO_CBFUN_DATA_FREE, - (void *)free, sizeof(&free)); + (void*)free_func[i], sizeof(free_func[i])); ret = MESA_htable_mature(htable); assert(ret == 0); @@ -243,5 +279,10 @@ void ssl_service_cache_destroy(struct ssl_service_cache* cache) free(cache); return; } +void ssl_service_cache_stat(struct ssl_service_cache* svc_cache, struct ssl_service_cache_statistics* result) +{ + *result=svc_cache->stat; + return; +} diff --git a/platform/src/ssl_stream.cpp b/platform/src/ssl_stream.cpp index de934e0..3261e35 100644 --- a/platform/src/ssl_stream.cpp +++ b/platform/src/ssl_stream.cpp @@ -99,7 +99,11 @@ enum ssl_stream_stat KEY_KEEPER_ASK, KEY_KEEPER_ISSUE, - + SSL_SVC_PINNING, + SSL_SVC_MAUTH, + SSL_SVC_CT_CERT, + SSL_SVC_EV_CERT, + SSL_STAT_MAX }; struct session_ticket_key @@ -182,7 +186,7 @@ struct ssl_upstream_parts char block_fake_cert; struct ssl_service_status svc_status; enum ssl_stream_action action; - + int keyring_id; struct ssl_chello * client_hello; int is_server_cert_verify_passed; }; @@ -325,6 +329,14 @@ ssl_stream_gc_cb(evutil_socket_t fd, short what, void * arg) mgr->stat_val[KEY_KEEPER_ISSUE]=keeper_stat.new_issue; mgr->stat_val[KEY_KEEPER_CACHE_SIZE]=keeper_stat.cached_num; + struct ssl_service_cache_statistics svc_stat; + memset(&svc_stat, 0, sizeof(svc_stat)); + ssl_service_cache_stat(mgr->svc_cache, &svc_stat); + mgr->stat_val[SSL_SVC_PINNING]=svc_stat.pinning_cli_cnt; + mgr->stat_val[SSL_SVC_MAUTH]=svc_stat.mutual_auth_cli_cnt; + mgr->stat_val[SSL_SVC_CT_CERT]=svc_stat.ct_srv_cnt; + mgr->stat_val[SSL_SVC_EV_CERT]=svc_stat.ev_srv_cnt; + for(i=0;ifs_handle, mgr->fs_id[i], 0, FS_OP_SET, ATOMIC_READ(&(mgr->stat_val[i]))); @@ -376,6 +388,12 @@ void ssl_stat_init(struct ssl_mgr * mgr) spec[KEY_KEEPER_ISSUE]="kyr_new"; spec[KEY_KEEPER_CACHE_SIZE]="kyr_cache"; + spec[SSL_SVC_PINNING]="ssl_pinning"; + spec[SSL_SVC_MAUTH]="ssl_mauth"; + spec[SSL_SVC_CT_CERT]="ssl_ct_crt"; + spec[SSL_SVC_EV_CERT]="ssl_ev_crt"; + + for(i=0;idir == CONN_DIR_UPSTREAM); const char* sni=NULL; struct ssl_connect_client_ctx * ctx = ALLOC(struct ssl_connect_client_ctx, 1); - ctx->keyring_id = keyring_id; + ctx->keyring_id = upstream->up_parts.keyring_id; ctx->ssl_mgr = mgr; ctx->fd_downstream = fd_downstream; ctx->thread_id = thread_id; @@ -1766,7 +1784,7 @@ void ssl_async_downstream_create(struct future * f, struct ssl_mgr * mgr, struct ctx->f_ask_keyring = future_create("ask_kyr",ask_keyring_on_succ, ask_keyring_on_fail, p); ctx->is_origin_crt_verify_passed = upstream->up_parts.is_server_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, + key_keeper_async_ask(ctx->f_ask_keyring, mgr->key_keeper, sni, ctx->keyring_id, ctx->origin_crt, ctx->is_origin_crt_verify_passed, evbase, dnsbase); return; } @@ -1965,6 +1983,9 @@ int ssl_stream_set_integer_opt(struct ssl_stream *upstream, enum SSL_STREAM_OPT case SSL_STREAM_OPT_PROTOCOL_MAX_VERSION: upstream->ssl_max_version=opt_val; break; + case SSL_STREAM_OPT_KEYRING_ID: + upstream->up_parts.keyring_id=opt_val; + break; default: assert(0); return 0; diff --git a/platform/src/tcp_stream.cpp b/platform/src/tcp_stream.cpp index cfce50d..e47f339 100644 --- a/platform/src/tcp_stream.cpp +++ b/platform/src/tcp_stream.cpp @@ -942,7 +942,7 @@ void ssl_upstream_create_on_success(future_result_t * result, void * user) 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); + _stream->ssl_upstream, _stream->defer_fd_downstream, _stream->thread_ref->thread_id); } future_destroy(_stream->future_upstream_create); _stream->future_upstream_create = NULL; diff --git a/plugin/business/ssl-policy/src/ssl_policy.cpp b/plugin/business/ssl-policy/src/ssl_policy.cpp index dcbb12b..17c2d08 100644 --- a/plugin/business/ssl-policy/src/ssl_policy.cpp +++ b/plugin/business/ssl-policy/src/ssl_policy.cpp @@ -136,9 +136,8 @@ void intercept_param_free_cb(int table_id, MAAT_PLUGIN_EX_DATA* ad, long argl, v param->ref_cnt--; if(param->ref_cnt==0) { + TFE_LOG_INFO(enforcer->logger, "Del intercept policy %d", param->policy_id);\ free(param); - TFE_LOG_INFO(enforcer->logger, "Del intercept policy %d", param->policy_id); - free(*ad); *ad=NULL; } } @@ -193,6 +192,8 @@ enum ssl_stream_action ssl_policy_enforce(struct ssl_stream *upstream, void* u_p { ret=ssl_stream_set_integer_opt(upstream, SSL_STREAM_OPT_BLOCK_FAKE_CERT, 1); } + ret=ssl_stream_set_integer_opt(upstream, SSL_STREAM_OPT_KEYRING_ID, param->keyring); + 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); @@ -200,7 +201,7 @@ enum ssl_stream_action ssl_policy_enforce(struct ssl_stream *upstream, void* u_p ret=ssl_stream_get_integer_opt(upstream, SSL_STREAM_OPT_IS_MUTUAL_AUTH, &is_mauth); ret=ssl_stream_get_integer_opt(upstream, SSL_STREAM_OPT_IS_CT_CERT, &is_ct); assert(ret=1); - if( (pinning_staus>1 && param->bypass_pinning) || + if( (pinning_staus==1 && param->bypass_pinning) || (is_mauth && param->bypass_mutual_auth) || (is_ev && param->bypass_ev_cert) || (is_ct && param->bypass_ct_cert) )