[nginx] SSL: added trusted certificates into session id context.

Maxim Dounin mdounin at mdounin.ru
Mon Mar 24 00:51:06 UTC 2025


details:   http://freenginx.org/hg/nginx/rev/48cff1a93a0e
branches:  
changeset: 9334:48cff1a93a0e
user:      Maxim Dounin <mdounin at mdounin.ru>
date:      Sat Mar 08 16:54:10 2025 +0300
description:
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.

diffstat:

 src/event/ngx_event_openssl.c |  60 ++++++++++++++++++++++++++++++++++++++++++-
 src/event/ngx_event_openssl.h |   1 +
 2 files changed, 60 insertions(+), 1 deletions(-)

diffs (123 lines):

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;


More information about the nginx-devel mailing list