changeset 8634:831d1960826f quic

QUIC: generate default stateless reset token key. Previously, if quic_stateless_reset_token_key was empty or unspecified, initial stateless reset token was not generated. However subsequent tokens were generated with empty key, which resulted in error with certain SSL libraries, for example OpenSSL. Now a random 32-byte stateless reset token key is generated if none is specified in the configuration. As a result, stateless reset tokens are now generated for all server ids.
author Roman Arutyunyan <arut@nginx.com>
date Wed, 11 Nov 2020 21:08:48 +0000
parents d8b01c2b8931
children ef83990f0e25
files src/event/ngx_event_quic.c src/event/ngx_event_quic.h src/event/ngx_event_quic_transport.c src/http/modules/ngx_http_quic_module.c src/stream/ngx_stream_quic_module.c
diffstat 5 files changed, 42 insertions(+), 28 deletions(-) [+]
line wrap: on
line diff
--- a/src/event/ngx_event_quic.c
+++ b/src/event/ngx_event_quic.c
@@ -1133,10 +1133,6 @@ ngx_quic_send_stateless_reset(ngx_connec
     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
                    "quic handle stateless reset output");
 
-    if (conf->sr_token_key.len == 0) {
-        return NGX_DECLINED;
-    }
-
     if (pkt->len <= NGX_QUIC_MIN_PKT_LEN) {
         return NGX_DECLINED;
     }
@@ -1573,19 +1569,15 @@ ngx_quic_init_connection(ngx_connection_
     }
 #endif
 
-    if (qc->conf->sr_token_key.len) {
-        qc->tp.sr_enabled = 1;
-
-        if (ngx_quic_new_sr_token(c, &qc->dcid, &qc->conf->sr_token_key,
-                                  qc->tp.sr_token)
-            != NGX_OK)
-        {
-            return NGX_ERROR;
-        }
-
-        ngx_quic_hexdump(c->log, "quic stateless reset token",
-                         qc->tp.sr_token, (size_t) NGX_QUIC_SR_TOKEN_LEN);
-    }
+    if (ngx_quic_new_sr_token(c, &qc->dcid, &qc->conf->sr_token_key,
+                              qc->tp.sr_token)
+        != NGX_OK)
+    {
+        return NGX_ERROR;
+    }
+
+    ngx_quic_hexdump(c->log, "quic stateless reset token",
+                     qc->tp.sr_token, (size_t) NGX_QUIC_SR_TOKEN_LEN);
 
     len = ngx_quic_create_transport_params(NULL, NULL, &qc->tp, &clen);
     /* always succeeds */
--- a/src/event/ngx_event_quic.h
+++ b/src/event/ngx_event_quic.h
@@ -27,6 +27,7 @@
 
 #define NGX_QUIC_DEFAULT_ACK_DELAY_EXPONENT  3
 #define NGX_QUIC_DEFAULT_MAX_ACK_DELAY       25
+#define NGX_QUIC_DEFAULT_SRT_KEY_LEN         32
 
 #define NGX_QUIC_RETRY_TIMEOUT               3000
 #define NGX_QUIC_RETRY_LIFETIME              30000
@@ -82,7 +83,6 @@ typedef struct {
     ngx_str_t                  initial_scid;
     ngx_str_t                  retry_scid;
     u_char                     sr_token[NGX_QUIC_SR_TOKEN_LEN];
-    ngx_uint_t                 sr_enabled;
 
     /* TODO */
     void                      *preferred_address;
--- a/src/event/ngx_event_quic_transport.c
+++ b/src/event/ngx_event_quic_transport.c
@@ -1883,11 +1883,9 @@ ngx_quic_create_transport_params(u_char 
     }
 #endif
 
-    if (tp->sr_enabled) {
-        len += ngx_quic_varint_len(NGX_QUIC_TP_SR_TOKEN);
-        len += ngx_quic_varint_len(NGX_QUIC_SR_TOKEN_LEN);
-        len += NGX_QUIC_SR_TOKEN_LEN;
-    }
+    len += ngx_quic_varint_len(NGX_QUIC_TP_SR_TOKEN);
+    len += ngx_quic_varint_len(NGX_QUIC_SR_TOKEN_LEN);
+    len += NGX_QUIC_SR_TOKEN_LEN;
 
     if (pos == NULL) {
         return len;
@@ -1935,11 +1933,9 @@ ngx_quic_create_transport_params(u_char 
     }
 #endif
 
-    if (tp->sr_enabled) {
-        ngx_quic_build_int(&p, NGX_QUIC_TP_SR_TOKEN);
-        ngx_quic_build_int(&p, NGX_QUIC_SR_TOKEN_LEN);
-        p = ngx_cpymem(p, tp->sr_token, NGX_QUIC_SR_TOKEN_LEN);
-    }
+    ngx_quic_build_int(&p, NGX_QUIC_TP_SR_TOKEN);
+    ngx_quic_build_int(&p, NGX_QUIC_SR_TOKEN_LEN);
+    p = ngx_cpymem(p, tp->sr_token, NGX_QUIC_SR_TOKEN_LEN);
 
     return p - pos;
 }
--- a/src/http/modules/ngx_http_quic_module.c
+++ b/src/http/modules/ngx_http_quic_module.c
@@ -317,6 +317,19 @@ ngx_http_quic_merge_srv_conf(ngx_conf_t 
 
     ngx_conf_merge_str_value(conf->sr_token_key, prev->sr_token_key, "");
 
+    if (conf->sr_token_key.len == 0) {
+        conf->sr_token_key.len = NGX_QUIC_DEFAULT_SRT_KEY_LEN;
+
+        conf->sr_token_key.data = ngx_pnalloc(cf->pool, conf->sr_token_key.len);
+        if (conf->sr_token_key.data == NULL) {
+            return NGX_CONF_ERROR;
+        }
+
+        if (RAND_bytes(conf->sr_token_key.data, conf->sr_token_key.len) <= 0) {
+            return NGX_CONF_ERROR;
+        }
+    }
+
     sscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_ssl_module);
     conf->ssl = &sscf->ssl;
 
--- a/src/stream/ngx_stream_quic_module.c
+++ b/src/stream/ngx_stream_quic_module.c
@@ -313,6 +313,19 @@ ngx_stream_quic_merge_srv_conf(ngx_conf_
 
     ngx_conf_merge_str_value(conf->sr_token_key, prev->sr_token_key, "");
 
+    if (conf->sr_token_key.len == 0) {
+        conf->sr_token_key.len = NGX_QUIC_DEFAULT_SRT_KEY_LEN;
+
+        conf->sr_token_key.data = ngx_pnalloc(cf->pool, conf->sr_token_key.len);
+        if (conf->sr_token_key.data == NULL) {
+            return NGX_CONF_ERROR;
+        }
+
+        if (RAND_bytes(conf->sr_token_key.data, conf->sr_token_key.len) <= 0) {
+            return NGX_CONF_ERROR;
+        }
+    }
+
     scf = ngx_stream_conf_get_module_srv_conf(cf, ngx_stream_ssl_module);
     conf->ssl = &scf->ssl;