mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2024-12-18 01:14:38 +00:00
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:
parent
6e6c7b1284
commit
8989942cfc
42
src/h2.c
42
src/h2.c
@ -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;
|
||||
|
10
src/mux_h2.c
10
src/mux_h2.c
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user