From: Willy Tarreau Date: Thu, 19 Aug 2021 21:06:58 +0000 (+0200) Subject: BUG/MEDIUM: h2: match absolute-path not path-absolute for :path X-Git-Tag: v2.5-dev5~60 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=46b7dff8f08cb6c5c3004d8874d6c5bc689a4c51;p=thirdparty%2Fhaproxy.git BUG/MEDIUM: h2: match absolute-path not path-absolute for :path RFC7540 states that :path follows RFC3986's path-absolute. However that was a bug introduced in the spec between draft 04 and draft 05 of the spec, which implicitly causes paths starting with "//" to be forbidden. HTTP/1 (and now HTTP core semantics) made it explicit that the request-target in origin-form follows a purposely defined absolute-path defined as 1*(/ segment) to explicitly allow "//". http2bis now fixes this by relying on absolute-path so that "//" becomes valid and matches other versions. Full discussion here: https://lists.w3.org/Archives/Public/ietf-http-wg/2021JulSep/0245.html This issue appeared in haproxy with commit 4b8852c70 ("BUG/MAJOR: h2: verify that :path starts with a '/' before concatenating it") when making the checks on :path fully comply with the spec, and was backported as far as 2.0, so this fix must be backported there as well to allow "//" in H2 again. --- diff --git a/src/h2.c b/src/h2.c index bbc5853bfa..dd1f7d9b67 100644 --- a/src/h2.c +++ b/src/h2.c @@ -279,6 +279,9 @@ static struct htx_sl *h2_prepare_htx_reqline(uint32_t fields, struct ist *phdr, /* 7540#8.1.2.3: :path must not be empty, and must be either * '*' or an RFC3986 "path-absolute" starting with a "/" but * not with "//". + * However, this "path-absolute" was a mistake which was + * later fixed in http2bis as "absolute-path" to match + * HTTP/1, thus also allowing "//". */ if (unlikely(!phdr[H2_PHDR_IDX_PATH].len)) goto fail; @@ -286,9 +289,6 @@ static struct htx_sl *h2_prepare_htx_reqline(uint32_t fields, struct ist *phdr, if (!isteq(phdr[H2_PHDR_IDX_PATH], ist("*"))) goto fail; } - else if (phdr[H2_PHDR_IDX_PATH].len > 1 && - phdr[H2_PHDR_IDX_PATH].ptr[1] == '/') - goto fail; } if (!(flags & HTX_SL_F_HAS_SCHM)) {