]> git.kaiwu.me - nginx.git/commitdiff
HTTP/3: generate more H3_FRAME_UNEXPECTED.
authorRoman Arutyunyan <arut@nginx.com>
Fri, 11 Jun 2021 09:11:08 +0000 (12:11 +0300)
committerRoman Arutyunyan <arut@nginx.com>
Fri, 11 Jun 2021 09:11:08 +0000 (12:11 +0300)
As per quic-http-34, these are the cases when this error should be generated:

   If an endpoint receives a second SETTINGS frame
   on the control stream, the endpoint MUST respond with a connection
   error of type H3_FRAME_UNEXPECTED

   SETTINGS frames MUST NOT be sent on any stream other than the control
   stream.  If an endpoint receives a SETTINGS frame on a different
   stream, the endpoint MUST respond with a connection error of type
   H3_FRAME_UNEXPECTED.

   A client MUST NOT send a PUSH_PROMISE frame.  A server MUST treat the
   receipt of a PUSH_PROMISE frame as a connection error of type
   H3_FRAME_UNEXPECTED; see Section 8.

   The MAX_PUSH_ID frame is always sent on the control stream.  Receipt
   of a MAX_PUSH_ID frame on any other stream MUST be treated as a
   connection error of type H3_FRAME_UNEXPECTED.

   Receipt of an invalid sequence of frames MUST be treated as a
   connection error of type H3_FRAME_UNEXPECTED; see Section 8.  In
   particular, a DATA frame before any HEADERS frame, or a HEADERS or
   DATA frame after the trailing HEADERS frame, is considered invalid.

   A CANCEL_PUSH frame is sent on the control stream.  Receiving a
   CANCEL_PUSH frame on a stream other than the control stream MUST be
   treated as a connection error of type H3_FRAME_UNEXPECTED.

   The GOAWAY frame is always sent on the control stream.

src/http/v3/ngx_http_v3_parse.c

index bd528963185950f324ec0d6884499f98ebea2b08..7bd9e6327c7d2ad85e2d6b05238a0b49023716b2 100644 (file)
@@ -224,7 +224,14 @@ ngx_http_v3_parse_headers(ngx_connection_t *c, ngx_http_v3_parse_headers_t *st,
 
         st->type = st->vlint.value;
 
-        if (ngx_http_v3_is_v2_frame(st->type)) {
+        if (ngx_http_v3_is_v2_frame(st->type)
+            || st->type == NGX_HTTP_V3_FRAME_DATA
+            || st->type == NGX_HTTP_V3_FRAME_GOAWAY
+            || st->type == NGX_HTTP_V3_FRAME_SETTINGS
+            || st->type == NGX_HTTP_V3_FRAME_MAX_PUSH_ID
+            || st->type == NGX_HTTP_V3_FRAME_CANCEL_PUSH
+            || st->type == NGX_HTTP_V3_FRAME_PUSH_PROMISE)
+        {
             return NGX_HTTP_V3_ERR_FRAME_UNEXPECTED;
         }
 
@@ -1037,9 +1044,16 @@ ngx_http_v3_parse_control(ngx_connection_t *c, ngx_http_v3_parse_control_t *st,
             return NGX_HTTP_V3_ERR_MISSING_SETTINGS;
         }
 
+        if (st->state != sw_first_type
+            && st->type == NGX_HTTP_V3_FRAME_SETTINGS)
+        {
+            return NGX_HTTP_V3_ERR_FRAME_UNEXPECTED;
+        }
+
         if (ngx_http_v3_is_v2_frame(st->type)
             || st->type == NGX_HTTP_V3_FRAME_DATA
-            || st->type == NGX_HTTP_V3_FRAME_HEADERS)
+            || st->type == NGX_HTTP_V3_FRAME_HEADERS
+            || st->type == NGX_HTTP_V3_FRAME_PUSH_PROMISE)
         {
             return NGX_HTTP_V3_ERR_FRAME_UNEXPECTED;
         }
@@ -1633,7 +1647,13 @@ ngx_http_v3_parse_data(ngx_connection_t *c, ngx_http_v3_parse_data_t *st,
             goto done;
         }
 
-        if (ngx_http_v3_is_v2_frame(st->type)) {
+        if (ngx_http_v3_is_v2_frame(st->type)
+            || st->type == NGX_HTTP_V3_FRAME_GOAWAY
+            || st->type == NGX_HTTP_V3_FRAME_SETTINGS
+            || st->type == NGX_HTTP_V3_FRAME_MAX_PUSH_ID
+            || st->type == NGX_HTTP_V3_FRAME_CANCEL_PUSH
+            || st->type == NGX_HTTP_V3_FRAME_PUSH_PROMISE)
+        {
             return NGX_HTTP_V3_ERR_FRAME_UNEXPECTED;
         }