]> git.kaiwu.me - nginx.git/commitdiff
SNI: support for early ClientHello callback with BoringSSL.
authorSergey Kandaurov <pluknet@nginx.com>
Mon, 22 Sep 2025 15:55:16 +0000 (19:55 +0400)
committerpluknet <pluknet@nginx.com>
Thu, 25 Sep 2025 15:25:08 +0000 (19:25 +0400)
This brings feature parity with OpenSSL after the previous change,
making it possible to set SSL protocols per virtual server.

src/event/ngx_event_openssl.c
src/event/ngx_event_openssl.h
src/http/ngx_http_request.c
src/stream/ngx_stream_ssl_module.c

index d9abcd082a6dd4c13da309abe49f922e3f7d5ae9..375d58be61a225127fa4736ac01cb2d256f68f09 100644 (file)
@@ -1663,6 +1663,11 @@ ngx_ssl_set_client_hello_callback(SSL_CTX *ssl_ctx,
     SSL_CTX_set_client_hello_cb(ssl_ctx, ngx_ssl_client_hello_callback, NULL);
     SSL_CTX_set_ex_data(ssl_ctx, ngx_ssl_client_hello_arg_index, cb);
 
+#elif defined OPENSSL_IS_BORINGSSL
+
+    SSL_CTX_set_select_certificate_cb(ssl_ctx, ngx_ssl_select_certificate);
+    SSL_CTX_set_ex_data(ssl_ctx, ngx_ssl_client_hello_arg_index, cb);
+
 #endif
 }
 
@@ -1727,6 +1732,37 @@ done:
     return SSL_CLIENT_HELLO_SUCCESS;
 }
 
+#elif defined OPENSSL_IS_BORINGSSL
+
+enum ssl_select_cert_result_t ngx_ssl_select_certificate(
+    const SSL_CLIENT_HELLO *client_hello)
+{
+    int                        ad;
+    ngx_int_t                  rc;
+    ngx_ssl_conn_t            *ssl_conn;
+    ngx_connection_t          *c;
+    ngx_ssl_client_hello_arg  *cb;
+
+    ssl_conn = client_hello->ssl;
+    c = ngx_ssl_get_connection(ssl_conn);
+    cb = SSL_CTX_get_ex_data(c->ssl->session_ctx,
+                             ngx_ssl_client_hello_arg_index);
+
+    /*
+     * BoringSSL sends a hardcoded "handshake_failure" alert on errors,
+     * we use it to map SSL_AD_INTERNAL_ERROR.  To preserve other alert
+     * values, error handling is postponed to the servername callback.
+     */
+
+    rc = cb->servername(ssl_conn, &ad, NULL);
+
+    if (rc == SSL_TLSEXT_ERR_ALERT_FATAL && ad == SSL_AD_INTERNAL_ERROR) {
+        return ssl_select_cert_error;
+    }
+
+    return ssl_select_cert_success;
+}
+
 #endif
 
 
index 544703f611b25abb68d256eefbea793b1865bff8..9943ee43054f078a2975035f93b343c81a47ca17 100644 (file)
@@ -298,6 +298,9 @@ void ngx_ssl_set_client_hello_callback(SSL_CTX *ssl_ctx,
     ngx_ssl_client_hello_arg *cb);
 #ifdef SSL_CLIENT_HELLO_SUCCESS
 int ngx_ssl_client_hello_callback(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg);
+#elif defined OPENSSL_IS_BORINGSSL
+enum ssl_select_cert_result_t ngx_ssl_select_certificate(
+    const SSL_CLIENT_HELLO *client_hello);
 #endif
 
 ngx_int_t ngx_ssl_create_connection(ngx_ssl_t *ssl, ngx_connection_t *c,
index 6f6e975b70873ffd38a2108bae93a51bc0fdfdb9..16d79c490d752311e601257c26e6217fae8e0655 100644 (file)
@@ -895,6 +895,11 @@ ngx_http_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg)
         return SSL_TLSEXT_ERR_OK;
     }
 
+    if (c->ssl->handshake_rejected) {
+        *ad = SSL_AD_UNRECOGNIZED_NAME;
+        return SSL_TLSEXT_ERR_ALERT_FATAL;
+    }
+
     hc = c->data;
 
     if (arg != NULL) {
index 7bf6304e4d8e979dc39e5762fa44b36b42c9c41b..75938b0a2bfbe47992f2ed3a41ee20beecf4b8a3 100644 (file)
@@ -559,6 +559,11 @@ ngx_stream_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg)
         return SSL_TLSEXT_ERR_OK;
     }
 
+    if (c->ssl->handshake_rejected) {
+        *ad = SSL_AD_UNRECOGNIZED_NAME;
+        return SSL_TLSEXT_ERR_ALERT_FATAL;
+    }
+
     s = c->data;
 
     if (arg) {