https://bz.apache.org/bugzilla/show_bug.cgi?id=70195
Bug ID: 70195
Summary: mod_http2 rejects asterisk-form "OPTIONS *" with 400
since 2.4.55
Product: Apache httpd-2
Version: 2.4.68
Hardware: Other
OS: Linux
Status: NEW
Severity: normal
Priority: P2
Component: mod_http2
Assignee: [email protected]
Reporter: [email protected]
Target Milestone: ---
Symptom:
The server answers 400 to "OPTIONS *" over HTTP/2, but succeeds over HTTP/1.1.
The problem occurs both with default tls h2 and with h2c.
This violates RFC 9113 for HTTP/2, ยง8.3.1, fourth bullet point: " A request in
asterisk form (for OPTIONS) includes the value '*' for the ":path"
pseudo-header field."
The server correctly replies 200 from 2.4.23 (at least) to 2.4.54 included, and
started failing with 2.4.55 including 58, 66, 67, 68. The same versions all
pass over HTTP/1.1
On a related version note, Ubuntu 22.04's apache2 2.4.52-1ubuntu4.23 carries
the version number of a working release but backports the change: a stock
container of it, with only "Protocols h2c http/1.1" added, answers 200 over
HTTP/1.1 and 400 over h2.
Diagnosis - created by Claude Opus 5, verified manually by me
tl;dr: Root cause is
https://github.com/apache/httpd/commit/b90220157d4ef25d2ecbbb96ee8b2e99b661f8d5#diff-560c73821ce0f1f56db0567922f8c3227a929f646c1cd4e1abf1bf0f83ae2fd6R780-R852
-----
Introduced by r1897940 (trunk, 2022-02-10), first released in 2.4.55.
Its log message reads "Checks on combinations of pseudo-headers
values/absence have been added as described in RFC 7540", fixing
https://github.com/icing/mod_h2/issues/230. It added to
modules/http2/h2_stream.c:
if (req->scheme && (req->path && req->path[0] != '/')) {
... APLOGNO(10379) ...
set_error_response(stream, HTTP_BAD_REQUEST);
goto cleanup;
}
For "OPTIONS *" the path is "*", so path[0] != '/' holds and the stream is
failed. The same check is present unchanged in trunk.
The same commit documents the rule this breaks, roughly twenty lines
above the check, quoting RFC 7540 section 8.1.2.3:
This [:path] pseudo-header field MUST NOT be empty for "http" or
"https" URIs; "http" or "https" URIs that do not contain a path
component MUST include a value of '/'. The exception to this rule is
an OPTIONS request for an "http" or "https" URI that does not include
a path component; these MUST include a ":path" pseudo-header field
with a value of '*'
So the asterisk exception appears to have been documented but not
implemented.
Suggested fix
-------------
Exempt a path of exactly "*" when the method is OPTIONS, before the
absolute-URL check, mirroring what ap_parse_request_line() already does
for HTTP/1.1:
r->method_number != M_OPTIONS || strcmp(r->parsed_uri.path, "*") != 0
References
----------
r1897940 https://svn.apache.org/r1897940
git mirror
https://github.com/apache/httpd/commit/b90220157d4ef25d2ecbbb96ee8b2e99b661f8d5
issue it fixed https://github.com/icing/mod_h2/issues/230
Related
-------
bz 66499 reports a different regression from the same commit (":scheme"
mismatch behind a TLS-terminating proxy) and is currently REOPENED.
icing/mod_h2 #271 reported another (REQUEST_URI carrying an absolute URL)
and was fixed in 2.4.58. This report concerns ":path" rather than
":scheme", and I found no existing report of it.
--
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]