summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGlenn Strauss <gstrauss@gluelogic.com>2021-09-15 05:11:54 -0400
committerGlenn Strauss <gstrauss@gluelogic.com>2021-09-15 05:11:54 -0400
commita407636eae3d63732373de7b63b3d7a1104625f9 (patch)
tree5a02e5de7813ead5ccccff39a810dd5c730fad7c
parentaf96e52be9e8d939d5cb7d83c0ee3474b80cabfe (diff)
downloadlighttpd-git-a407636eae3d63732373de7b63b3d7a1104625f9.tar.gz
[core] reject HTTP/2 pseudo-header in trailers (#3102)
(detect if client erroneously reuses stream id for a different request) x-ref: "Chrome gives random net::ERR_HTTP2_PROTOCOL_ERROR" https://redmine.lighttpd.net/issues/3102
-rw-r--r--src/h2.c13
-rw-r--r--src/request.c3
2 files changed, 11 insertions, 5 deletions
diff --git a/src/h2.c b/src/h2.c
index 7b89998f..01cc8d9c 100644
--- a/src/h2.c
+++ b/src/h2.c
@@ -1220,7 +1220,7 @@ h2_parse_headers_frame (request_st * const restrict r, const unsigned char *psrc
const unsigned char * const endp = psrc + plen;
http_header_parse_ctx hpctx;
hpctx.hlen = 0;
- hpctx.pseudo = 1;
+ hpctx.pseudo = 1; /*(XXX: should be !trailers if handling trailers)*/
hpctx.scheme = 0;
hpctx.trailers = trailers;
hpctx.max_request_field_size = r->conf.max_request_field_size;
@@ -1252,7 +1252,7 @@ h2_parse_headers_frame (request_st * const restrict r, const unsigned char *psrc
rc = lshpack_dec_decode(decoder, &psrc, endp, &lsx);
if (0 == lsx.name_len)
rc = LSHPACK_ERR_BAD_DATA;
- if (rc == LSHPACK_OK) {
+ if (__builtin_expect( (rc == LSHPACK_OK), 1)) {
hpctx.k = lsx.buf+lsx.name_offset;
hpctx.v = lsx.buf+lsx.val_offset;
hpctx.klen = lsx.name_len;
@@ -1265,9 +1265,12 @@ h2_parse_headers_frame (request_st * const restrict r, const unsigned char *psrc
"fd:%d id:%u rqst: %.*s: %.*s", r->con->fd, r->h2id,
(int)hpctx.klen, hpctx.k, (int)hpctx.vlen, hpctx.v);
- r->http_status = http_request_parse_header(r, &hpctx);
- if (0 != r->http_status)
+ const int http_status = http_request_parse_header(r, &hpctx);
+ if (__builtin_expect( (0 != http_status), 0)) {
+ if (r->http_status == 0) /*might be set if processing trailers*/
+ r->http_status = http_status;
break;
+ }
}
#if 0 /*(see catch-all below)*/
/* Send GOAWAY (further below) (decoder state not maintained on error)
@@ -1319,7 +1322,7 @@ h2_parse_headers_frame (request_st * const restrict r, const unsigned char *psrc
rq->bytes_in += (off_t)hpctx.hlen;
rq->bytes_out += (off_t)hpctx.hlen;
- if (0 == r->http_status && LSHPACK_OK == rc) {
+ if (0 == r->http_status && LSHPACK_OK == rc && !trailers) {
if (hpctx.pseudo)
r->http_status =
http_request_validate_pseudohdrs(r, hpctx.scheme,
diff --git a/src/request.c b/src/request.c
index 8366986c..ed2e5310 100644
--- a/src/request.c
+++ b/src/request.c
@@ -749,6 +749,9 @@ http_request_parse_header (request_st * const restrict r, http_header_parse_ctx
}
}
else { /*(trailers)*/
+ if (*k == ':')
+ return http_request_header_line_invalid(r, 400,
+ "invalid pseudo-header in trailers -> 400");
/* ignore trailers (after required HPACK decoding) if streaming
* request body to backend since headers have already been sent
* to backend via Common Gateway Interface (CGI) (CGI, FastCGI,