diff --git a/platform/include/internal/ssl_stream_core.h b/platform/include/internal/ssl_stream_core.h index c72c145..222c1af 100644 --- a/platform/include/internal/ssl_stream_core.h +++ b/platform/include/internal/ssl_stream_core.h @@ -43,7 +43,7 @@ void ssl_async_downstream_create(struct future * f, struct ssl_mgr * mgr, struct evutil_socket_t fd_downstream, struct tfe_stream* tcp_stream); -void ssl_stream_free_and_close_fd(struct ssl_stream * stream, struct event_base * evbase, evutil_socket_t fd); +void ssl_stream_free_and_close_fd(struct ssl_stream * s_stream, struct event_base * evbase, struct bufferevent * bev); const char* ssl_stream_dump_info(struct ssl_stream *stream, char* buffer, size_t sz); //Follow functions are allowed to call during runtime. int ssl_manager_add_trust_ca(struct ssl_mgr* mgr, const char* pem_file); diff --git a/platform/src/ssl_stream.cpp b/platform/src/ssl_stream.cpp index b23ba21..fb912e4 100644 --- a/platform/src/ssl_stream.cpp +++ b/platform/src/ssl_stream.cpp @@ -290,23 +290,24 @@ 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 (!strcasecmp(version_str, "ssl3")||!strcasecmp(version_str, "SSLv3")) { sslversion = SSL3_VERSION; } - else if (!strcmp(version_str, "tls10") || !strcmp(version_str, "tls1")) + else if (!strcasecmp(version_str, "tls10") || !strcasecmp(version_str, "tls1") || + !strcasecmp(version_str, "TLSv1.0") || !strcasecmp(version_str, "TLSv1")) { sslversion = TLS1_VERSION; } - else if (!strcmp(version_str, "tls11")) + else if (!strcasecmp(version_str, "tls11")||!strcasecmp(version_str, "TLSv1.1")) { sslversion = TLS1_1_VERSION; } - else if (!strcmp(version_str, "tls12")) + else if (!strcasecmp(version_str, "tls12")||!strcasecmp(version_str, "TLSv1.2")) { sslversion = TLS1_2_VERSION; } - else if (!strcmp(version_str, "tls13")) + else if (!strcasecmp(version_str, "tls13")||!strcasecmp(version_str, "TLSv1.3")) { sslversion = TLS1_3_VERSION; } @@ -1021,6 +1022,21 @@ const char* ssl_stream_dump_info(struct ssl_stream *stream, char* buffer, size_t stream->dir==CONN_DIR_UPSTREAM ? stream->up_parts.client_hello->sni:NULL); return buffer; } +static void ssl_stream_set_cmsg_string(struct ssl_stream* stream, enum tfe_cmsg_tlv_type type, const char* value_str) +{ + struct tfe_cmsg* cmsg=tfe_stream_get0_cmsg(stream->tcp_stream); + int ret=tfe_cmsg_set(cmsg, type, (const unsigned char*)value_str, (uint16_t)strlen(value_str)); + assert(ret==0); + return; +} +static void ssl_stream_set_cmsg_integer(struct ssl_stream* stream, enum tfe_cmsg_tlv_type type, uint64_t value_int) +{ + struct tfe_cmsg* cmsg=tfe_stream_get0_cmsg(stream->tcp_stream); + int ret=tfe_cmsg_set(cmsg, type, (const unsigned char*)&value_int, (uint16_t)sizeof(value_int)); + assert(ret==0); + return; +} + unsigned long ssl_stream_log_error(struct bufferevent * bev, enum tfe_conn_dir dir, struct ssl_mgr* mgr) { unsigned long sslerr=0, ret_sslerr=0; @@ -1133,21 +1149,40 @@ unsigned long ssl_stream_log_error(struct bufferevent * bev, enum tfe_conn_dir d free(addr_string); return ret_sslerr; } +void ssl_stream_process_error(struct ssl_stream * s_stream, unsigned long sslerr, struct ssl_mgr* mgr) +{ + struct ssl_upstream_parts* s_upstream=NULL; + assert(sslerr); + switch(s_stream->dir) + { + case CONN_DIR_DOWNSTREAM: + s_upstream= &(s_stream->peer->up_parts); + if(sslerr==SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN && + s_upstream->is_server_cert_verify_passed && + s_upstream->verify_result.is_hostmatched) + { + s_upstream->svc_status.pinning_status=PINNING_ST_PINNING; + ssl_stream_set_cmsg_integer(s_stream, TFE_CMSG_SSL_PINNING_STATE, PINNING_ST_PINNING); + ssl_service_cache_write(mgr->svc_cache, s_upstream->client_hello, s_stream->tcp_stream->addr, &s_upstream->svc_status); + } + else if(sslerr>0 && sslerr!=SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN) + { + s_upstream->svc_status.has_protocol_errors=1; + ssl_service_cache_write(mgr->svc_cache, s_upstream->client_hello, s_stream->tcp_stream->addr, &s_upstream->svc_status); + } + break; + case CONN_DIR_UPSTREAM: + s_upstream=&(s_stream->up_parts); + s_upstream->svc_status.has_protocol_errors=1; + ssl_service_cache_write(mgr->svc_cache, s_stream->up_parts.client_hello, s_stream->tcp_stream->addr, &(s_stream->up_parts.svc_status)); + break; + default: + assert(0); + } + return; +} + -static void ssl_stream_set_cmsg_string(struct ssl_stream* stream, enum tfe_cmsg_tlv_type type, const char* value_str) -{ - struct tfe_cmsg* cmsg=tfe_stream_get0_cmsg(stream->tcp_stream); - int ret=tfe_cmsg_set(cmsg, type, (const unsigned char*)value_str, (uint16_t)strlen(value_str)); - assert(ret==0); - return; -} -static void ssl_stream_set_cmsg_integer(struct ssl_stream* stream, enum tfe_cmsg_tlv_type type, uint64_t value_int) -{ - struct tfe_cmsg* cmsg=tfe_stream_get0_cmsg(stream->tcp_stream); - int ret=tfe_cmsg_set(cmsg, type, (const unsigned char*)&value_int, (uint16_t)sizeof(value_int)); - assert(ret==0); - return; -} /* * Callback for meta events on the up- and downstream connection bufferevents. @@ -1173,8 +1208,7 @@ static void ssl_server_connected_eventcb(struct bufferevent * bev, short events, sslerr=ssl_stream_log_error(bev, CONN_DIR_UPSTREAM, ctx->mgr); if(sslerr) { - s_upstream->svc_status.has_protocol_errors=1; - ssl_service_cache_write(mgr->svc_cache, s_stream->up_parts.client_hello, s_stream->tcp_stream->addr, &(s_stream->up_parts.svc_status)); + ssl_stream_process_error(s_stream, sslerr, mgr); } s_stream->error=SSL_STREAM_R_SERVER_PROTOCOL_ERROR; } @@ -1294,6 +1328,7 @@ static void peek_chello_on_succ(future_result_t * result, void * user) struct event_base* evbase=tfe_proxy_get_work_thread_evbase(ctx->tcp_stream->thread_id); struct ssl_stream* s_stream=NULL; struct ssl_chello* chello = ssl_peek_result_release_chello(result);//chello has been saved in ssl_stream. + char* addr_string=NULL; if(chello->sni==NULL) { ATOMIC_INC(&(ctx->mgr->stat_val[SSL_NO_SNI])); @@ -1306,13 +1341,17 @@ static void peek_chello_on_succ(future_result_t * result, void * user) ret=ssl_service_cache_read(ctx->mgr->svc_cache, chello, s_stream->tcp_stream->addr, svc_status); if(ret==1) { - TFE_LOG_DEBUG(ctx->mgr->logger, "SNI: %s service status pinning:%d, mauth:%d, err:%d, ct:%d, ev:%d", + addr_string=tfe_stream_addr_to_str(s_stream->tcp_stream->addr); + TFE_LOG_DEBUG(ctx->mgr->logger, "%s %s service status pinning:%d, mauth:%d, err:%d, ct:%d, ev:%d", + addr_string, chello->sni, svc_status->pinning_status, svc_status->is_mutual_auth, svc_status->has_protocol_errors, svc_status->is_ct, svc_status->is_ev); + free(addr_string); + addr_string=NULL; } ssl_stream_set_cmsg_integer(s_stream, TFE_CMSG_SSL_PINNING_STATE, svc_status->pinning_status); if(ctx->mgr->on_new_upstream_cb) @@ -1740,6 +1779,7 @@ struct bufferevent * ssl_downstream_create_result_release_bev(future_result_t * ctx->bev_down = NULL; return ret; } + static void ssl_client_connected_eventcb(struct bufferevent * bev, short events, void * arg) { struct promise * p = (struct promise *) arg; @@ -1756,18 +1796,9 @@ static void ssl_client_connected_eventcb(struct bufferevent * bev, short events, { ATOMIC_INC(&(mgr->stat_val[SSL_DOWN_ERR])); sslerr=ssl_stream_log_error(bev, CONN_DIR_DOWNSTREAM, mgr); - if(sslerr==SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN && - s_upstream->is_server_cert_verify_passed && - s_upstream->verify_result.is_hostmatched) + if(sslerr) { - s_upstream->svc_status.pinning_status=PINNING_ST_PINNING; - ssl_stream_set_cmsg_integer(s_stream, TFE_CMSG_SSL_PINNING_STATE, PINNING_ST_PINNING); - ssl_service_cache_write(mgr->svc_cache, s_upstream->client_hello, s_stream->tcp_stream->addr, &s_upstream->svc_status); - } - else if(sslerr>0 && sslerr!=SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN) - { - s_upstream->svc_status.has_protocol_errors=1; - ssl_service_cache_write(mgr->svc_cache, s_upstream->client_hello, s_stream->tcp_stream->addr, &s_upstream->svc_status); + ssl_stream_process_error(s_stream, sslerr, mgr); } s_stream->error=SSL_STREAM_R_CLIENT_PROTOCOL_ERROR; } @@ -2028,10 +2059,21 @@ complete: * Guarantees that SSL and the corresponding SSL_CTX are freed and the * socket is closed, eventually, or in the case of fatal errors, immediately. */ -void ssl_stream_free_and_close_fd(struct ssl_stream * s_stream, struct event_base * evbase, evutil_socket_t fd) +void ssl_stream_free_and_close_fd(struct ssl_stream * s_stream, struct event_base * evbase, struct bufferevent * bev) { struct ssl_shutdown_ctx * sslshutctx = NULL; + evutil_socket_t fd=-1; + fd=bufferevent_getfd(bev); assert(fd==s_stream->_do_not_use.fd); + unsigned long sslerr=0; + if(errno) + { + sslerr=ssl_stream_log_error(bev, s_stream->dir, s_stream->mgr); + if(sslerr) + { + ssl_stream_process_error(s_stream, sslerr, s_stream->mgr); + } + } sslshutctx = ssl_shutdown_ctx_new(s_stream, evbase); pxy_ssl_shutdown_cb(fd, 0, sslshutctx); } diff --git a/platform/src/tcp_stream.cpp b/platform/src/tcp_stream.cpp index 6fa362c..07a9d64 100644 --- a/platform/src/tcp_stream.cpp +++ b/platform/src/tcp_stream.cpp @@ -380,8 +380,7 @@ static void __conn_private_destory_with_ssl(struct event_base * ev_base, struct tfe_conn_private * conn, struct ssl_stream * ssl_stream) { if (ssl_stream == NULL) return __conn_private_destory(conn); - evutil_socket_t __to_closed_fd = __conn_private_release_fd(conn); - ssl_stream_free_and_close_fd(ssl_stream, ev_base, __to_closed_fd); + ssl_stream_free_and_close_fd(ssl_stream, ev_base, conn->bev); return __conn_private_destory(conn); } @@ -1046,14 +1045,12 @@ void tfe_stream_destory(struct tfe_stream_private * stream) if (__is_ssl(stream) && stream->ssl_upstream) { - evutil_socket_t __to_closed_fd = __conn_private_release_fd(stream->conn_upstream); - ssl_stream_free_and_close_fd(stream->ssl_upstream, ev_base, __to_closed_fd); + ssl_stream_free_and_close_fd(stream->ssl_upstream, ev_base, stream->conn_upstream->bev); } if (__is_ssl(stream) && stream->ssl_downstream) { - evutil_socket_t __to_closed_fd = __conn_private_release_fd(stream->conn_downstream); - ssl_stream_free_and_close_fd(stream->ssl_downstream, ev_base, __to_closed_fd); + ssl_stream_free_and_close_fd(stream->ssl_downstream, ev_base, stream->conn_downstream->bev); } if (stream->conn_upstream) diff --git a/plugin/business/ssl-policy/src/ssl_policy.cpp b/plugin/business/ssl-policy/src/ssl_policy.cpp index dbc5a6e..0448fd8 100644 --- a/plugin/business/ssl-policy/src/ssl_policy.cpp +++ b/plugin/business/ssl-policy/src/ssl_policy.cpp @@ -132,6 +132,11 @@ void intercept_param_new_cb(int table_id, const char* key, const char* table_lin if(item && item->type==cJSON_String) param->ssl_min_version=sslver_str2num(item->valuestring); item=cJSON_GetObjectItem(ssl_ver, "max"); if(item && item->type==cJSON_String) param->ssl_max_version=sslver_str2num(item->valuestring); + if(param->ssl_min_version<0||param->ssl_max_version<0) + { + param->mirror_client_version=1; + TFE_LOG_ERROR(enforcer->logger, "Invalid intercept parameter: ssl version = %s", item->valuestring); + } } item=cJSON_GetObjectItem(ssl_ver, "allow_http2"); if(item && item->type==cJSON_Number) param->allow_http2=item->valueint;