changeset 9060:5fd628b89bb7 quic

HTTP/3: fixed OpenSSL compatibility layer initialization. SSL context is not present if the default server has neither certificates nor ssl_reject_handshake enabled. Previously, this led to null pointer dereference before it would be caught with configuration checks. Additionally, non-default servers with distinct SSL contexts need to initialize compatibility layer in order to complete a QUIC handshake.
author Sergey Kandaurov <pluknet@nginx.com>
date Fri, 24 Mar 2023 19:49:50 +0400
parents f4279edda9fd
children efd91f6afa8d
files src/http/modules/ngx_http_ssl_module.c
diffstat 1 files changed, 36 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/src/http/modules/ngx_http_ssl_module.c
+++ b/src/http/modules/ngx_http_ssl_module.c
@@ -56,6 +56,10 @@ static char *ngx_http_ssl_conf_command_c
     void *data);
 
 static ngx_int_t ngx_http_ssl_init(ngx_conf_t *cf);
+#if (NGX_QUIC_OPENSSL_COMPAT)
+static ngx_int_t ngx_http_ssl_quic_compat_init(ngx_conf_t *cf,
+    ngx_http_conf_addr_t *addr);
+#endif
 
 
 static ngx_conf_bitmask_t  ngx_http_ssl_protocols[] = {
@@ -1328,14 +1332,11 @@ ngx_http_ssl_init(ngx_conf_t *cf)
                 continue;
             }
 
-            cscf = addr[a].default_server;
-            sscf = cscf->ctx->srv_conf[ngx_http_ssl_module.ctx_index];
-
             if (addr[a].opt.quic) {
                 name = "quic";
 
 #if (NGX_QUIC_OPENSSL_COMPAT)
-                if (ngx_quic_compat_init(cf, sscf->ssl.ctx) != NGX_OK) {
+                if (ngx_http_ssl_quic_compat_init(cf, &addr[a]) != NGX_OK) {
                     return NGX_ERROR;
                 }
 #endif
@@ -1344,6 +1345,9 @@ ngx_http_ssl_init(ngx_conf_t *cf)
                 name = "ssl";
             }
 
+            cscf = addr[a].default_server;
+            sscf = cscf->ctx->srv_conf[ngx_http_ssl_module.ctx_index];
+
             if (sscf->certificates) {
 
                 if (addr[a].opt.quic && !(sscf->protocols & NGX_SSL_TLSv1_3)) {
@@ -1391,3 +1395,31 @@ ngx_http_ssl_init(ngx_conf_t *cf)
 
     return NGX_OK;
 }
+
+
+#if (NGX_QUIC_OPENSSL_COMPAT)
+
+static ngx_int_t
+ngx_http_ssl_quic_compat_init(ngx_conf_t *cf, ngx_http_conf_addr_t *addr)
+{
+    ngx_uint_t                  s;
+    ngx_http_ssl_srv_conf_t    *sscf;
+    ngx_http_core_srv_conf_t  **cscfp, *cscf;
+
+    cscfp = addr->servers.elts;
+    for (s = 0; s < addr->servers.nelts; s++) {
+
+        cscf = cscfp[s];
+        sscf = cscf->ctx->srv_conf[ngx_http_ssl_module.ctx_index];
+
+        if (sscf->certificates || sscf->reject_handshake) {
+            if (ngx_quic_compat_init(cf, sscf->ssl.ctx) != NGX_OK) {
+                return NGX_ERROR;
+            }
+        }
+    }
+
+    return NGX_OK;
+}
+
+#endif