# HG changeset patch # User Roman Arutyunyan # Date 1623402668 -10800 # Node ID 278ab0ed24f2cf9a8fc7fe740aadfad0901fc6e1 # Parent ba5977b38b2e6a79d4e652dd9d9a197740c45a21 HTTP/3: generate more H3_FRAME_UNEXPECTED. 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. diff --git a/src/http/v3/ngx_http_v3_parse.c b/src/http/v3/ngx_http_v3_parse.c --- a/src/http/v3/ngx_http_v3_parse.c +++ b/src/http/v3/ngx_http_v3_parse.c @@ -224,7 +224,14 @@ ngx_http_v3_parse_headers(ngx_connection 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 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 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; }