changeset 8454:032cb35ce758 quic

HTTP/3: http3_max_field_size directive to limit string size. Client streams may send literal strings which are now limited in size by the new directive. The default value is 4096. The directive is similar to HTTP/2 directive http2_max_field_size.
author Roman Arutyunyan <arut@nginx.com>
date Mon, 29 Jun 2020 15:56:14 +0300
parents c8cabb5d45f5
children b0e81f49d7c0
files src/http/v3/ngx_http_v3.h src/http/v3/ngx_http_v3_module.c src/http/v3/ngx_http_v3_parse.c
diffstat 3 files changed, 25 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/src/http/v3/ngx_http_v3.h
+++ b/src/http/v3/ngx_http_v3.h
@@ -47,9 +47,12 @@
 #define NGX_HTTP_V3_STREAM_SERVER_DECODER          5
 #define NGX_HTTP_V3_MAX_KNOWN_STREAM               6
 
+#define NGX_HTTP_V3_DEFAULT_MAX_FIELD_SIZE         4096
+
 
 typedef struct {
     ngx_quic_tp_t           quic;
+    size_t                  max_field_size;
 } ngx_http_v3_srv_conf_t;
 
 
--- a/src/http/v3/ngx_http_v3_module.c
+++ b/src/http/v3/ngx_http_v3_module.c
@@ -118,6 +118,13 @@ static ngx_command_t  ngx_http_v3_comman
       offsetof(ngx_http_v3_srv_conf_t, quic.retry),
       NULL },
 
+    { ngx_string("http3_max_field_size"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
+      ngx_conf_set_size_slot,
+      NGX_HTTP_SRV_CONF_OFFSET,
+      offsetof(ngx_http_v3_srv_conf_t, max_field_size),
+      NULL },
+
       ngx_null_command
 };
 
@@ -268,6 +275,8 @@ ngx_http_v3_create_srv_conf(ngx_conf_t *
 
     v3cf->quic.retry = NGX_CONF_UNSET;
 
+    v3cf->max_field_size = NGX_CONF_UNSET_SIZE;
+
     return v3cf;
 }
 
@@ -329,6 +338,9 @@ ngx_http_v3_merge_srv_conf(ngx_conf_t *c
         }
     }
 
+    ngx_conf_merge_size_value(conf->max_field_size,
+                              prev->max_field_size,
+                              NGX_HTTP_V3_DEFAULT_MAX_FIELD_SIZE);
 
     return NGX_CONF_OK;
 }
--- a/src/http/v3/ngx_http_v3_parse.c
+++ b/src/http/v3/ngx_http_v3_parse.c
@@ -399,7 +399,8 @@ ngx_int_t
 ngx_http_v3_parse_literal(ngx_connection_t *c, ngx_http_v3_parse_literal_t *st,
     u_char ch)
 {
-    ngx_uint_t  n;
+    ngx_uint_t               n;
+    ngx_http_v3_srv_conf_t  *v3cf;
     enum {
         sw_start = 0,
         sw_value
@@ -415,6 +416,14 @@ ngx_http_v3_parse_literal(ngx_connection
 
         n = st->length;
 
+        v3cf = ngx_http_v3_get_module_srv_conf(c, ngx_http_v3_module);
+
+        if (n > v3cf->max_field_size) {
+            ngx_log_error(NGX_LOG_ERR, c->log, 0,
+                          "client exceeded http3_max_field_size limit");
+            return NGX_ERROR;
+        }
+
         if (st->huffman) {
             n = n * 8 / 5;
             st->huffstate = 0;