]> git.kaiwu.me - haproxy.git/commitdiff
BUG/MEDIUM: h1: Enforce the authority validation during H1 request parsing
authorChristopher Faulet <cfaulet@haproxy.com>
Tue, 28 Apr 2026 09:20:59 +0000 (11:20 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Wed, 29 Apr 2026 08:03:39 +0000 (10:03 +0200)
When a H1 request was parsed, only a light validation was performed on the
URI, mainly because there was no distinction between the different parts of
the URI. So only characters in the range [0x21, 0x7e], excluding the "#" was
allowed.

To be consistant with the H2 and H3 parser, the authority is now validated,
using http_authority_has_forbidden_char() function.

This patch should be backported as far as 2.8. For previous verions,
http_authority_has_forbidden_char() function does not exist.

src/h1.c

index 1ad5ac19fb6e9a58a24554fd3d8eb09addf9ea69..7fb78804f2fb3d45659946bfa782a453841bb439 100644 (file)
--- a/src/h1.c
+++ b/src/h1.c
@@ -1073,6 +1073,22 @@ int h1_headers_to_hdr_list(char *start, const char *stop,
 
                        case URI_PARSER_FORMAT_ABSURI_OR_AUTHORITY:
                                scheme = http_parse_scheme(&parser);
+                               authority = http_parse_authority(&parser, 1);
+                               if (http_authority_has_forbidden_char(authority)) {
+                                       if (h1m->err_pos < -1) {
+                                               state = H1_MSG_LAST_LF;
+                                               /* WT: gcc seems to see a path where sl.rq.u.ptr was used
+                                                * uninitialized, but it doesn't know that the function is
+                                                * called with initial states making this impossible.
+                                                */
+                                               ALREADY_CHECKED(sl.rq.u.ptr);
+                                               ptr = sl.rq.u.ptr; /* Set ptr on the error */
+                                               goto http_msg_invalid;
+                                       }
+                                       if (h1m->err_pos == -1) /* capture the error pointer */
+                                               h1m->err_pos = sl.rq.u.ptr - start + skip; /* >= 0 now */
+                               }
+
                                if (!isttest(scheme)) { /* scheme not found: MUST be an authority */
                                        struct ist *host = NULL;
 
@@ -1082,7 +1098,6 @@ int h1_headers_to_hdr_list(char *start, const char *stop,
                                        }
                                        if (host_idx != -1)
                                                host = &hdr[host_idx].v;
-                                       authority = http_parse_authority(&parser, 1);
                                        ret = h1_validate_connect_authority(scheme, authority, host);
                                        if (ret < 0) {
                                                if (h1m->err_pos < -1) {
@@ -1109,7 +1124,6 @@ int h1_headers_to_hdr_list(char *start, const char *stop,
 
                                        if (host_idx != -1)
                                                host = hdr[host_idx].v;
-                                       authority = http_parse_authority(&parser, 1);
                                        /* For non-CONNECT method, the authority must match the host header value */
                                        if (isttest(host) && !isteqi(authority, host)) {
                                                ret = h1_validate_mismatch_authority(scheme, authority, host);