BUG/MINOR: h2/mux-h2: Reject 101 responses with a PROTOCOL_ERROR h2s error

As stated in the RFC7540, section 8.1.1, the HTTP/2 removes support for the
101 informational status code. Thus a PROTOCOL_ERROR is now returned to the
server if a 101-switching-protocols response is received. Thus, the server
connection is aborted.

This patch may be backported as far as 2.0.
This commit is contained in:
Christopher Faulet 2020-12-07 18:24:43 +01:00
parent 6e6c7b1284
commit 8989942cfc
2 changed files with 28 additions and 24 deletions

View File

@ -517,7 +517,7 @@ int h2_make_htx_request(struct http_hdr *list, struct htx *htx, unsigned int *ms
*/
static struct htx_sl *h2_prepare_htx_stsline(uint32_t fields, struct ist *phdr, struct htx *htx, unsigned int *msgf)
{
unsigned int flags = HTX_SL_F_NONE;
unsigned int status, flags = HTX_SL_F_NONE;
struct htx_sl *sl;
unsigned char h, t, u;
@ -528,6 +528,25 @@ static struct htx_sl *h2_prepare_htx_stsline(uint32_t fields, struct ist *phdr,
if (phdr[H2_PHDR_IDX_STAT].len != 3)
goto fail;
h = phdr[H2_PHDR_IDX_STAT].ptr[0] - '0';
t = phdr[H2_PHDR_IDX_STAT].ptr[1] - '0';
u = phdr[H2_PHDR_IDX_STAT].ptr[2] - '0';
if (h > 9 || t > 9 || u > 9)
goto fail;
status = h * 100 + t * 10 + u;
/* 101 responses are not supported in H2, so return a error.
* On 1xx responses there is no ES on the HEADERS frame but there is no
* body. So remove the flag H2_MSGF_BODY and add H2_MSGF_RSP_1XX to
* notify the decoder another HEADERS frame is expected.
*/
if (status == 101)
goto fail;
else if (status < 200) {
*msgf |= H2_MSGF_RSP_1XX;
*msgf &= ~H2_MSGF_BODY;
}
/* Set HTX start-line flags */
flags |= HTX_SL_F_VER_11; // V2 in fact
flags |= HTX_SL_F_XFER_LEN; // xfer len always known with H2
@ -535,26 +554,7 @@ static struct htx_sl *h2_prepare_htx_stsline(uint32_t fields, struct ist *phdr,
sl = htx_add_stline(htx, HTX_BLK_RES_SL, flags, ist("HTTP/2.0"), phdr[H2_PHDR_IDX_STAT], ist(""));
if (!sl)
goto fail;
h = phdr[H2_PHDR_IDX_STAT].ptr[0] - '0';
t = phdr[H2_PHDR_IDX_STAT].ptr[1] - '0';
u = phdr[H2_PHDR_IDX_STAT].ptr[2] - '0';
if (h > 9 || t > 9 || u > 9)
goto fail;
sl->info.res.status = h * 100 + t * 10 + u;
/* On 1xx responses (except 101) there is no ES on the HEADERS frame but
* there is no body. So remove the flag H2_MSGF_BODY and add
* H2_MSGF_RSP_1XX to notify the decoder another HEADERS frame is
* expected.
*/
if (sl->info.res.status < 200 &&
(sl->info.res.status == 100 || sl->info.res.status >= 102)) {
*msgf |= H2_MSGF_RSP_1XX;
*msgf &= ~H2_MSGF_BODY;
}
sl->info.res.status = status;
return sl;
fail:
return NULL;

View File

@ -4892,6 +4892,11 @@ static size_t h2s_frt_make_resp_headers(struct h2s *h2s, struct htx *htx)
TRACE_ERROR("will not encode an invalid status code", H2_EV_TX_FRAME|H2_EV_TX_HDR|H2_EV_H2S_ERR, h2c->conn, h2s);
goto fail;
}
else if (h2s->status == 101) {
/* 101 responses are not supported in H2, so return a error (RFC7540#8.1.1) */
TRACE_ERROR("will not encode an invalid status code", H2_EV_TX_FRAME|H2_EV_TX_HDR|H2_EV_H2S_ERR, h2c->conn, h2s);
goto fail;
}
/* and the rest of the headers, that we dump starting at header 0 */
hdr = 0;
@ -5000,8 +5005,7 @@ static size_t h2s_frt_make_resp_headers(struct h2s *h2s, struct htx *htx)
* FIXME: we should also set it when we know for sure that the
* content-length is zero as well as on 204/304
*/
if (blk_end && htx_get_blk_type(blk_end) == HTX_BLK_EOM &&
(h2s->status >= 200 || h2s->status == 101))
if (blk_end && htx_get_blk_type(blk_end) == HTX_BLK_EOM && h2s->status >= 200)
es_now = 1;
if (!h2s->cs || h2s->cs->flags & CS_FL_SHW)
@ -5017,7 +5021,7 @@ static size_t h2s_frt_make_resp_headers(struct h2s *h2s, struct htx *htx)
/* indicates the HEADERS frame was sent, except for 1xx responses. For
* 1xx responses, another HEADERS frame is expected.
*/
if (h2s->status >= 200 || h2s->status == 101)
if (h2s->status >= 200)
h2s->flags |= H2_SF_HEADERS_SENT;
if (es_now) {