# HG changeset patch # User Maxim Dounin <mdou...@mdounin.ru> # Date 1741442050 -10800 # Sat Mar 08 16:54:10 2025 +0300 # Node ID 48cff1a93a0e8ed50699e9201a805d5e14aab84d # Parent 1996ea0bc55d2bc950297f9d7990a5b07948f5e2 SSL: added trusted certificates into session id context.
This ensures that sessions cannot be incorrectly restored between servers with identical certificates and client certificates, but with different trusted certificates. Note that with BoringSSL this applies to SNI-based virtual servers, since with BoringSSL session resumption happens after the TLS servername callback, and session id context of the selected virtual server is used to decide whether the session can be resumed or not. diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c @@ -131,6 +131,7 @@ int ngx_ssl_server_conf_index; int ngx_ssl_session_cache_index; int ngx_ssl_ticket_keys_index; int ngx_ssl_ocsp_index; +int ngx_ssl_trusted_list_index; int ngx_ssl_certificate_index; int ngx_ssl_next_certificate_index; int ngx_ssl_certificate_name_index; @@ -258,6 +259,14 @@ ngx_ssl_init(ngx_log_t *log) return NGX_ERROR; } + ngx_ssl_trusted_list_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, + NULL); + if (ngx_ssl_trusted_list_index == -1) { + ngx_ssl_error(NGX_LOG_ALERT, log, 0, + "SSL_CTX_get_ex_new_index() failed"); + return NGX_ERROR; + } + ngx_ssl_certificate_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL); if (ngx_ssl_certificate_index == -1) { @@ -951,6 +960,8 @@ ngx_int_t ngx_ssl_trusted_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert, ngx_int_t depth) { + STACK_OF(X509_NAME) *list; + SSL_CTX_set_verify(ssl->ctx, SSL_CTX_get_verify_mode(ssl->ctx), ngx_ssl_verify_callback); @@ -980,6 +991,24 @@ ngx_ssl_trusted_certificate(ngx_conf_t * ERR_clear_error(); + if (SSL_CTX_get_verify_mode(ssl->ctx) != SSL_VERIFY_PEER) { + return NGX_OK; + } + + list = SSL_load_client_CA_file((char *) cert->data); + + if (list == NULL) { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, + "SSL_load_client_CA_file(\"%s\") failed", cert->data); + return NGX_ERROR; + } + + if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_trusted_list_index, list) == 0) { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, + "SSL_CTX_set_ex_data() failed"); + return NGX_ERROR; + } + return NGX_OK; } @@ -3857,6 +3886,28 @@ ngx_ssl_session_id_context(ngx_ssl_t *ss } } + list = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_trusted_list_index); + + if (list != NULL) { + n = sk_X509_NAME_num(list); + + for (i = 0; i < n; i++) { + name = sk_X509_NAME_value(list, i); + + if (X509_NAME_digest(name, EVP_sha1(), buf, &len) == 0) { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, + "X509_NAME_digest() failed"); + goto failed; + } + + if (EVP_DigestUpdate(md, buf, len) == 0) { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, + "EVP_DigestUpdate() failed"); + goto failed; + } + } + } + if (EVP_DigestFinal_ex(md, buf, &len) == 0) { ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "EVP_DigestFinal_ex() failed"); @@ -4826,7 +4877,8 @@ ngx_ssl_cleanup_ctx(void *data) { ngx_ssl_t *ssl = data; - X509 *cert, *next; + X509 *cert, *next; + STACK_OF(X509_NAME) *list; cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index); @@ -4836,6 +4888,12 @@ ngx_ssl_cleanup_ctx(void *data) cert = next; } + list = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_trusted_list_index); + + if (list) { + sk_X509_NAME_pop_free(list, X509_NAME_free); + } + SSL_CTX_free(ssl->ctx); } diff --git a/src/event/ngx_event_openssl.h b/src/event/ngx_event_openssl.h --- a/src/event/ngx_event_openssl.h +++ b/src/event/ngx_event_openssl.h @@ -332,6 +332,7 @@ extern int ngx_ssl_server_conf_index; extern int ngx_ssl_session_cache_index; extern int ngx_ssl_ticket_keys_index; extern int ngx_ssl_ocsp_index; +extern int ngx_ssl_trusted_list_index; extern int ngx_ssl_certificate_index; extern int ngx_ssl_next_certificate_index; extern int ngx_ssl_certificate_name_index;