diff --git a/platform/include/internal/ssl_policy.h b/platform/include/internal/ssl_policy.h index a380555..186077c 100644 --- a/platform/include/internal/ssl_policy.h +++ b/platform/include/internal/ssl_policy.h @@ -3,7 +3,6 @@ #include struct ssl_policy_enforcer; -struct ssl_policy_enforcer* ssl_policy_enforcer_create(void); -void ssl_policy_enforcer_init(struct ssl_policy_enforcer* enforcer, Maat_feather_t maat, void* logger); +struct ssl_policy_enforcer* ssl_policy_enforcer_create(Maat_feather_t maat, void* logger); enum ssl_stream_action ssl_policy_enforce(struct ssl_stream *upstream, void* u_para); diff --git a/platform/include/internal/ssl_stream.h b/platform/include/internal/ssl_stream.h index 1fb2044..fabfc2b 100644 --- a/platform/include/internal/ssl_stream.h +++ b/platform/include/internal/ssl_stream.h @@ -19,7 +19,8 @@ enum ssl_stream_action 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 * logger); +void ssl_manager_set_new_upstream_cb(struct ssl_mgr * mgr, ssl_stream_new_hook* new_upstream_cb, 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); @@ -55,7 +56,7 @@ enum SSL_STREAM_OPT 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_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 }; diff --git a/platform/src/proxy.cpp b/platform/src/proxy.cpp index df67fa7..684527a 100644 --- a/platform/src/proxy.cpp +++ b/platform/src/proxy.cpp @@ -385,9 +385,7 @@ int main(int argc, char * argv[]) /* SSL INIT */ - g_default_proxy->ssl_ply_enforcer = ssl_policy_enforcer_create(); - g_default_proxy->ssl_mgr_handler = ssl_manager_init(main_profile, "ssl", g_default_proxy->evbase, g_default_logger, - ssl_policy_enforce, g_default_proxy->ssl_ply_enforcer); + g_default_proxy->ssl_mgr_handler = ssl_manager_init(main_profile, "ssl", g_default_proxy->evbase, g_default_logger); 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++) @@ -418,7 +416,9 @@ int main(int argc, char * argv[]) TFE_LOG_INFO(g_default_logger, "Plugin %s initialized. ", plugin_iter->symbol); } //ugly here. g_business_maat is available after plugin initiate. - ssl_policy_enforcer_init(g_default_proxy->ssl_ply_enforcer, g_business_maat, g_default_logger); + + g_default_proxy->ssl_ply_enforcer=ssl_policy_enforcer_create(g_business_maat, g_default_logger); + ssl_manager_set_new_upstream_cb(g_default_proxy->ssl_mgr_handler, ssl_policy_enforce, g_default_proxy->ssl_ply_enforcer); ret = tfe_proxy_work_thread_run(g_default_proxy); CHECK_OR_EXIT(ret == 0, "Failed at creating thread. Exit."); diff --git a/platform/src/ssl_policy.cpp b/platform/src/ssl_policy.cpp index cf23366..1cd1bf5 100644 --- a/platform/src/ssl_policy.cpp +++ b/platform/src/ssl_policy.cpp @@ -8,7 +8,7 @@ struct ssl_policy_enforcer { Maat_feather_t maat; - int compile_table_id; + int table_id; void* logger; }; struct intercept_param @@ -27,24 +27,19 @@ struct intercept_param int block_fake_cert; int ssl_min_version; int ssl_max_version; - int mirror_client; + int mirror_client_version; int decrypt_mirror_enabled; int mirror_profile_id; }; -struct ssl_policy_enforcer* ssl_policy_enforcer_create(void) -{ - struct ssl_policy_enforcer* enforcer=ALLOC(struct ssl_policy_enforcer, 1); - return enforcer; -} -void intercept_policy_dup_cb(int table_id, MAAT_PLUGIN_EX_DATA* to, MAAT_PLUGIN_EX_DATA* from, long argl, void* argp) +void intercept_param_dup_cb(int table_id, MAAT_PLUGIN_EX_DATA* to, MAAT_PLUGIN_EX_DATA* from, long argl, void* argp) { struct intercept_param* param= (struct intercept_param*) *from; param->ref_cnt++; *to = param; return; } -void intercept_policy_new_cb(int table_id, const char* key, const char* table_line, MAAT_PLUGIN_EX_DATA* ad, long argl, void* argp) +void intercept_param_new_cb(int table_id, const char* key, const char* table_line, MAAT_PLUGIN_EX_DATA* ad, long argl, void* argp) { int ret=0; size_t intercept_user_region_offset=0, len=0; @@ -116,11 +111,14 @@ void intercept_policy_new_cb(int table_id, const char* key, const char* table_li if(ssl_ver) { item=cJSON_GetObjectItem(ssl_ver, "mirror_client"); - if(item && item->type==cJSON_String) param->mirror_client=item->valueint; - item=cJSON_GetObjectItem(ssl_ver, "min"); - if(item && item->type==cJSON_String) param->ssl_min_version=sslver_str2num(item->string); - item=cJSON_GetObjectItem(ssl_ver, "max"); - if(item && item->type==cJSON_String) param->ssl_max_version=sslver_str2num(item->string); + if(item && item->type==cJSON_String) param->mirror_client_version=item->valueint; + if(!param->mirror_client_version) + { + item=cJSON_GetObjectItem(ssl_ver, "min"); + if(item && item->type==cJSON_String) param->ssl_min_version=sslver_str2num(item->string); + item=cJSON_GetObjectItem(ssl_ver, "max"); + if(item && item->type==cJSON_String) param->ssl_max_version=sslver_str2num(item->string); + } } *ad=param; TFE_LOG_INFO(enforcer->logger, "Add intercept policy: %d", param->policy_id); @@ -129,7 +127,7 @@ error_out: free(json_str); return; } -void intercept_policy_free_cb(int table_id, MAAT_PLUGIN_EX_DATA* ad, long argl, void* argp) +void intercept_param_free_cb(int table_id, MAAT_PLUGIN_EX_DATA* ad, long argl, void* argp) { struct ssl_policy_enforcer* enforcer=(struct ssl_policy_enforcer*)argp; struct intercept_param* param= (struct intercept_param*) *ad; @@ -142,45 +140,77 @@ void intercept_policy_free_cb(int table_id, MAAT_PLUGIN_EX_DATA* ad, long argl, *ad=NULL; } } - -void ssl_policy_enforcer_init(struct ssl_policy_enforcer* enforcer, Maat_feather_t maat, void* logger) +void intercept_param_free(struct intercept_param* param) { + intercept_param_free_cb(0, (void**)¶m, 0, NULL); + return; +} +struct ssl_policy_enforcer* ssl_policy_enforcer_create(Maat_feather_t maat, void* logger) +{ + struct ssl_policy_enforcer* enforcer=ALLOC(struct ssl_policy_enforcer, 1); enforcer->maat=maat; enforcer->logger=logger; - enforcer->compile_table_id=Maat_table_register(enforcer->maat, "PXY_INTERCEPT_COMPILE"); + enforcer->table_id=Maat_table_register(enforcer->maat, "PXY_INTERCEPT_COMPILE"); int ret=Maat_plugin_EX_register(enforcer->maat, - enforcer->compile_table_id, - intercept_policy_new_cb, - intercept_policy_free_cb, - intercept_policy_dup_cb, + enforcer->table_id, + intercept_param_new_cb, + intercept_param_free_cb, + intercept_param_dup_cb, NULL, 0, enforcer); assert(ret==1); - return; + return enforcer; } 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; + struct intercept_param *param=NULL; + enum ssl_stream_action action=SSL_ACTION_PASSTHROUGH; UNUSED int ret=0; - int pinning_staus=0, is_ev=0, is_mauth=0; + int policy_id=0; + char policy_id_str[16]={0}; + snprintf(policy_id_str, sizeof(policy_id_str), "%d", policy_id); + param=(struct intercept_param *)Maat_plugin_get_EX_data(enforcer->maat, enforcer->table_id, policy_id_str); + if(param==NULL) + { + TFE_LOG_INFO(enforcer->logger, "Failed to get intercept parameter of policy %d.", param->policy_id); + return SSL_ACTION_PASSTHROUGH; + } + int pinning_staus=0, is_ev=0, is_ct=0, is_mauth=0; + if(!param->mirror_client_version) + { + ret=ssl_stream_set_integer_opt(upstream, SSL_STREAM_OPT_PROTOCOL_MIN_VERSION, SSL3_VERSION); + ret=ssl_stream_set_integer_opt(upstream, SSL_STREAM_OPT_PROTOCOL_MIN_VERSION, TLS1_3_VERSION); + } + ssl_stream_set_integer_opt(upstream, SSL_STREAM_OPT_NO_VERIFY_COMMON_NAME, param->no_verify_cn); + ssl_stream_set_integer_opt(upstream, SSL_STREAM_OPT_NO_VERIFY_ISSUER, param->no_verify_issuer); + ssl_stream_set_integer_opt(upstream, SSL_STREAM_OPT_NO_VERIFY_SELF_SIGNED, param->no_verify_self_signed); + ssl_stream_set_integer_opt(upstream, SSL_STREAM_OPT_NO_VERIFY_EXPIRY_DATE, param->no_verify_expry_date); + if(param->block_fake_cert) + { + ret=ssl_stream_set_integer_opt(upstream, SSL_STREAM_OPT_BLOCK_FAKE_CERT, 1); + } 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); ret=ssl_stream_get_integer_opt(upstream, SSL_STREAM_OPT_IS_MUTUAL_AUTH, &is_mauth); - - ret=ssl_stream_set_integer_opt(upstream, SSL_STREAM_OPT_NO_VERIFY_EXPIRY_DATE, 1); - ret=ssl_stream_set_integer_opt(upstream, SSL_STREAM_OPT_PROTOCOL_MIN_VERSION, SSL3_VERSION); - ret=ssl_stream_set_integer_opt(upstream, SSL_STREAM_OPT_PROTOCOL_MIN_VERSION, TLS1_3_VERSION); + ret=ssl_stream_get_integer_opt(upstream, SSL_STREAM_OPT_IS_CT_CERT, &is_ct); assert(ret=1); - if(pinning_staus>0||is_ev||is_mauth) + 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) ) { - return SSL_ACTION_PASSTHROUGH; + action=SSL_ACTION_PASSTHROUGH; } else { - return SSL_ACTION_INTERCEPT; + action=SSL_ACTION_INTERCEPT; } + intercept_param_free(param); + param=NULL; + return action; } diff --git a/platform/src/ssl_stream.cpp b/platform/src/ssl_stream.cpp index 79ca316..9ba6b0b 100644 --- a/platform/src/ssl_stream.cpp +++ b/platform/src/ssl_stream.cpp @@ -134,8 +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; + ssl_stream_new_hook* on_new_upstream_cb; + void* upstream_cb_param; struct session_ticket_key ticket_key; char default_ciphers[TFE_SYMBOL_MAX]; @@ -526,7 +526,7 @@ 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, ssl_stream_new_hook* hook_func, void* hook_u_para) + struct event_base * ev_base_gc, void * logger) { 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 @@ -595,8 +595,7 @@ 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. @@ -647,6 +646,12 @@ error_out: ssl_manager_destroy(mgr); return NULL; } +void ssl_manager_set_new_upstream_cb(struct ssl_mgr * mgr, ssl_stream_new_hook* new_upstream_cb, void* u_para) +{ + mgr->on_new_upstream_cb=new_upstream_cb; + mgr->upstream_cb_param=u_para; + return; +} void peek_client_hello_ctx_free(struct peek_client_hello_ctx * _ctx) { @@ -1174,7 +1179,14 @@ static void peek_chello_on_succ(future_result_t * result, void * user) svc_status->is_ct, svc_status->is_ev); } - s_stream->up_parts.action=ctx->mgr->on_new_hook_func(s_stream, ctx->mgr->hook_u_para); + if(ctx->mgr->on_new_upstream_cb) + { + s_stream->up_parts.action=ctx->mgr->on_new_upstream_cb(s_stream, ctx->mgr->upstream_cb_param); + } + else + { + s_stream->up_parts.action=SSL_ACTION_INTERCEPT; + } ctx->s_stream = s_stream; if(s_stream->up_parts.action==SSL_ACTION_PASSTHROUGH) { @@ -1905,7 +1917,7 @@ int ssl_stream_set_integer_opt(struct ssl_stream *upstream, enum SSL_STREAM_OPT case SSL_STREAM_OPT_NO_VERIFY_EXPIRY_DATE: verify_param->no_verify_expiry_date=opt_val; break; - case SST_STREAM_OPT_VERIFY_FAIL_ACTION: + case SSL_STREAM_OPT_BLOCK_FAKE_CERT: upstream->up_parts.block_fake_cert=opt_val; break; case SSL_STREAM_OPT_PROTOCOL_MIN_VERSION: @@ -1915,6 +1927,7 @@ int ssl_stream_set_integer_opt(struct ssl_stream *upstream, enum SSL_STREAM_OPT upstream->ssl_max_version=opt_val; break; default: + assert(0); return 0; }