Compare commits

..

No commits in common. "c9s" and "c8" have entirely different histories.
c9s ... c8

28 changed files with 814 additions and 1157 deletions

2
.gitignore vendored
View File

@ -1 +1 @@
haproxy-*.tar.gz
SOURCES/haproxy-1.8.27.tar.gz

1
.haproxy.metadata Normal file
View File

@ -0,0 +1 @@
5a8a12d07da986d2ecba5f57a07a9e68fe597bfd SOURCES/haproxy-1.8.27.tar.gz

View File

@ -1,76 +0,0 @@
From f86e994f5fb5851cd6e4f7f6b366e37765014b9f Mon Sep 17 00:00:00 2001
From: Willy Tarreau <w@1wt.eu>
Date: Tue, 8 Aug 2023 15:38:28 +0200
Subject: [PATCH] MINOR: h2: pass accept-invalid-http-request down the request
parser
We're adding a new argument "relaxed" to h2_make_htx_request() so that
we can control its level of acceptance of certain invalid requests at
the proxy level with "option accept-invalid-http-request". The goal
will be to add deactivable checks that are still desirable to have by
default. For now no test is subject to it.
(cherry picked from commit d93a00861d714313faa0395ff9e2acb14b0a2fca)
[ad: backported for following fix : BUG/MINOR: h2: reject more chars
from the :path pseudo header]
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit b6be1a4f858eb6602490c192235114c1a163fef9)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit 26fa3a285df0748fc79e73e552161268b66fb527)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit 014945a1508f43e88ac4e89950fa9037e4fb0679)
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
include/haproxy/h2.h | 2 +-
src/h2.c | 6 +++++-
src/mux_h2.c | 3 ++-
3 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/include/haproxy/h2.h b/include/haproxy/h2.h
index 8d2aa9511..4f872b99d 100644
--- a/include/haproxy/h2.h
+++ b/include/haproxy/h2.h
@@ -207,7 +207,7 @@ extern struct h2_frame_definition h2_frame_definition[H2_FT_ENTRIES];
/* various protocol processing functions */
int h2_parse_cont_len_header(unsigned int *msgf, struct ist *value, unsigned long long *body_len);
-int h2_make_htx_request(struct http_hdr *list, struct htx *htx, unsigned int *msgf, unsigned long long *body_len);
+int h2_make_htx_request(struct http_hdr *list, struct htx *htx, unsigned int *msgf, unsigned long long *body_len, int relaxed);
int h2_make_htx_response(struct http_hdr *list, struct htx *htx, unsigned int *msgf, unsigned long long *body_len, char *upgrade_protocol);
int h2_make_htx_trailers(struct http_hdr *list, struct htx *htx);
diff --git a/src/h2.c b/src/h2.c
index e1554642e..94c384111 100644
--- a/src/h2.c
+++ b/src/h2.c
@@ -399,8 +399,12 @@ static struct htx_sl *h2_prepare_htx_reqline(uint32_t fields, struct ist *phdr,
*
* The Cookie header will be reassembled at the end, and for this, the <list>
* will be used to create a linked list, so its contents may be destroyed.
+ *
+ * When <relaxed> is non-nul, some non-dangerous checks will be ignored. This
+ * is in order to satisfy "option accept-invalid-http-request" for
+ * interoperability purposes.
*/
-int h2_make_htx_request(struct http_hdr *list, struct htx *htx, unsigned int *msgf, unsigned long long *body_len)
+int h2_make_htx_request(struct http_hdr *list, struct htx *htx, unsigned int *msgf, unsigned long long *body_len, int relaxed)
{
struct ist phdr_val[H2_PHDR_NUM_ENTRIES];
uint32_t fields; /* bit mask of H2_PHDR_FND_* */
diff --git a/src/mux_h2.c b/src/mux_h2.c
index 0ab86534c..61fd1a4d2 100644
--- a/src/mux_h2.c
+++ b/src/mux_h2.c
@@ -4917,7 +4917,8 @@ static int h2c_decode_headers(struct h2c *h2c, struct buffer *rxbuf, uint32_t *f
if (h2c->flags & H2_CF_IS_BACK)
outlen = h2_make_htx_response(list, htx, &msgf, body_len, upgrade_protocol);
else
- outlen = h2_make_htx_request(list, htx, &msgf, body_len);
+ outlen = h2_make_htx_request(list, htx, &msgf, body_len,
+ !!(((const struct session *)h2c->conn->owner)->fe->options2 & PR_O2_REQBUG_OK));
if (outlen < 0 || htx_free_space(htx) < global.tune.maxrewrite) {
/* too large headers? this is a stream error only */
--
2.43.0

View File

@ -1,46 +0,0 @@
From c7492154ef07d6c08aa1eb52502697bbc3f42a69 Mon Sep 17 00:00:00 2001
From: Willy Tarreau <w@1wt.eu>
Date: Tue, 8 Aug 2023 19:52:45 +0200
Subject: [PATCH] REGTESTS: http-rules: add accept-invalid-http-request for
normalize-uri tests
We'll soon block the '#' by default so let's prepare the test to continue
to work.
(cherry picked from commit 069d0e221e58a46119d7c049bb07fa4bcb8d0075)
[ad: backported for following fix : BUG/MINOR: h2: reject more chars
from the :path pseudo header]
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit 1660481fab69856a39ac44cf88b76cdbcc0ea954)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit 90d0300cea6cda18a4e20369f4dc0b4c4783d6c9)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit 65849396fd6f192d9f14e81702c6c3851e580345)
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
reg-tests/http-rules/normalize_uri.vtc | 2 ++
1 file changed, 2 insertions(+)
diff --git a/reg-tests/http-rules/normalize_uri.vtc b/reg-tests/http-rules/normalize_uri.vtc
index 6a1dc31dc..56acf2cef 100644
--- a/reg-tests/http-rules/normalize_uri.vtc
+++ b/reg-tests/http-rules/normalize_uri.vtc
@@ -127,6 +127,7 @@ haproxy h1 -conf {
frontend fe_fragment_strip
bind "fd@${fe_fragment_strip}"
+ option accept-invalid-http-request
http-request set-var(txn.before) url
http-request normalize-uri fragment-strip
@@ -139,6 +140,7 @@ haproxy h1 -conf {
frontend fe_fragment_encode
bind "fd@${fe_fragment_encode}"
+ option accept-invalid-http-request
http-request set-var(txn.before) url
http-request normalize-uri fragment-encode
--
2.43.0

View File

@ -1,275 +0,0 @@
From ba9afd2774c03e434165475b537d0462801f49bb Mon Sep 17 00:00:00 2001
From: Willy Tarreau <w@1wt.eu>
Date: Wed, 9 Aug 2023 08:32:48 +0200
Subject: [PATCH] BUG/MAJOR: http: reject any empty content-length header value
The content-length header parser has its dedicated function, in order
to take extreme care about invalid, unparsable, or conflicting values.
But there's a corner case in it, by which it stops comparing values
when reaching the end of the header. This has for a side effect that
an empty value or a value that ends with a comma does not deserve
further analysis, and it acts as if the header was absent.
While this is not necessarily a problem for the value ending with a
comma as it will be cause a header folding and will disappear, it is a
problem for the first isolated empty header because this one will not
be recontructed when next ones are seen, and will be passed as-is to the
backend server. A vulnerable HTTP/1 server hosted behind haproxy that
would just use this first value as "0" and ignore the valid one would
then not be protected by haproxy and could be attacked this way, taking
the payload for an extra request.
In field the risk depends on the server. Most commonly used servers
already have safe content-length parsers, but users relying on haproxy
to protect a known-vulnerable server might be at risk (and the risk of
a bug even in a reputable server should never be dismissed).
A configuration-based work-around consists in adding the following rule
in the frontend, to explicitly reject requests featuring an empty
content-length header that would have not be folded into an existing
one:
http-request deny if { hdr_len(content-length) 0 }
The real fix consists in adjusting the parser so that it always expects a
value at the beginning of the header or after a comma. It will now reject
requests and responses having empty values anywhere in the C-L header.
This needs to be backported to all supported versions. Note that the
modification was made to functions h1_parse_cont_len_header() and
http_parse_cont_len_header(). Prior to 2.8 the latter was in
h2_parse_cont_len_header(). One day the two should be refused but the
former is also used by Lua.
The HTTP messaging reg-tests were completed to test these cases.
Thanks to Ben Kallus of Dartmouth College and Narf Industries for
reporting this! (this is in GH #2237).
(cherry picked from commit 6492f1f29d738457ea9f382aca54537f35f9d856)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit a32f99f6f991d123ea3e307bf8aa63220836d365)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit 65921ee12d88e9fb1fa9f6cd8198fd64b3a3f37f)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit d17c50010d591d1c070e1cb0567a06032d8869e9)
[wt: applied to h2_parse_cont_len_header() in src/h2.c instead]
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
reg-tests/http-messaging/h1_to_h1.vtc | 26 ++++++++++++
reg-tests/http-messaging/h2_to_h1.vtc | 60 +++++++++++++++++++++++++++
src/h1.c | 20 +++++++--
src/h2.c | 20 +++++++--
4 files changed, 120 insertions(+), 6 deletions(-)
diff --git a/reg-tests/http-messaging/h1_to_h1.vtc b/reg-tests/http-messaging/h1_to_h1.vtc
index c7d00858e..603c03210 100644
--- a/reg-tests/http-messaging/h1_to_h1.vtc
+++ b/reg-tests/http-messaging/h1_to_h1.vtc
@@ -275,3 +275,29 @@ client c3h1 -connect ${h1_feh1_sock} {
# arrive here.
expect_close
} -run
+
+client c4h1 -connect ${h1_feh1_sock} {
+ # this request is invalid and advertises an invalid C-L ending with an
+ # empty value, which results in a stream error.
+ txreq \
+ -req "GET" \
+ -url "/test31.html" \
+ -hdr "content-length: 0," \
+ -hdr "connection: close"
+ rxresp
+ expect resp.status == 400
+ expect_close
+} -run
+
+client c5h1 -connect ${h1_feh1_sock} {
+ # this request is invalid and advertises an empty C-L, which results
+ # in a stream error.
+ txreq \
+ -req "GET" \
+ -url "/test41.html" \
+ -hdr "content-length:" \
+ -hdr "connection: close"
+ rxresp
+ expect resp.status == 400
+ expect_close
+} -run
diff --git a/reg-tests/http-messaging/h2_to_h1.vtc b/reg-tests/http-messaging/h2_to_h1.vtc
index 0d2b1e5f2..ec7a7c123 100644
--- a/reg-tests/http-messaging/h2_to_h1.vtc
+++ b/reg-tests/http-messaging/h2_to_h1.vtc
@@ -10,6 +10,8 @@ barrier b1 cond 2 -cyclic
barrier b2 cond 2 -cyclic
barrier b3 cond 2 -cyclic
barrier b4 cond 2 -cyclic
+barrier b5 cond 2 -cyclic
+barrier b6 cond 2 -cyclic
server s1 {
rxreq
@@ -31,6 +33,12 @@ server s1 {
barrier b4 sync
# the next request is never received
+
+ barrier b5 sync
+ # the next request is never received
+
+ barrier b6 sync
+ # the next request is never received
} -repeat 2 -start
haproxy h1 -conf {
@@ -121,6 +129,32 @@ client c1h2 -connect ${h1_feh2_sock} {
txdata -data "this is sent and ignored"
rxrst
} -run
+
+ # fifth request is invalid and advertises an invalid C-L ending with an
+ # empty value, which results in a stream error.
+ stream 9 {
+ barrier b5 sync
+ txreq \
+ -req "GET" \
+ -scheme "https" \
+ -url "/test5.html" \
+ -hdr "content-length" "0," \
+ -nostrend
+ rxrst
+ } -run
+
+ # sixth request is invalid and advertises an empty C-L, which results
+ # in a stream error.
+ stream 11 {
+ barrier b6 sync
+ txreq \
+ -req "GET" \
+ -scheme "https" \
+ -url "/test6.html" \
+ -hdr "content-length" "" \
+ -nostrend
+ rxrst
+ } -run
} -run
# HEAD requests : don't work well yet
@@ -263,4 +297,30 @@ client c3h2 -connect ${h1_feh2_sock} {
txdata -data "this is sent and ignored"
rxrst
} -run
+
+ # fifth request is invalid and advertises invalid C-L ending with an
+ # empty value, which results in a stream error.
+ stream 9 {
+ barrier b5 sync
+ txreq \
+ -req "POST" \
+ -scheme "https" \
+ -url "/test25.html" \
+ -hdr "content-length" "0," \
+ -nostrend
+ rxrst
+ } -run
+
+ # sixth request is invalid and advertises an empty C-L, which results
+ # in a stream error.
+ stream 11 {
+ barrier b6 sync
+ txreq \
+ -req "POST" \
+ -scheme "https" \
+ -url "/test26.html" \
+ -hdr "content-length" "" \
+ -nostrend
+ rxrst
+ } -run
} -run
diff --git a/src/h1.c b/src/h1.c
index 73de48be0..eeda311b7 100644
--- a/src/h1.c
+++ b/src/h1.c
@@ -34,13 +34,20 @@ int h1_parse_cont_len_header(struct h1m *h1m, struct ist *value)
int not_first = !!(h1m->flags & H1_MF_CLEN);
struct ist word;
- word.ptr = value->ptr - 1; // -1 for next loop's pre-increment
+ word.ptr = value->ptr;
e = value->ptr + value->len;
- while (++word.ptr < e) {
+ while (1) {
+ if (word.ptr >= e) {
+ /* empty header or empty value */
+ goto fail;
+ }
+
/* skip leading delimiter and blanks */
- if (unlikely(HTTP_IS_LWS(*word.ptr)))
+ if (unlikely(HTTP_IS_LWS(*word.ptr))) {
+ word.ptr++;
continue;
+ }
/* digits only now */
for (cl = 0, n = word.ptr; n < e; n++) {
@@ -79,6 +86,13 @@ int h1_parse_cont_len_header(struct h1m *h1m, struct ist *value)
h1m->flags |= H1_MF_CLEN;
h1m->curr_len = h1m->body_len = cl;
*value = word;
+
+ /* Now either n==e and we're done, or n points to the comma,
+ * and we skip it and continue.
+ */
+ if (n++ == e)
+ break;
+
word.ptr = n;
}
/* here we've reached the end with a single value or a series of
diff --git a/src/h2.c b/src/h2.c
index dd1f7d9b6..e1554642e 100644
--- a/src/h2.c
+++ b/src/h2.c
@@ -80,13 +80,20 @@ int h2_parse_cont_len_header(unsigned int *msgf, struct ist *value, unsigned lon
int not_first = !!(*msgf & H2_MSGF_BODY_CL);
struct ist word;
- word.ptr = value->ptr - 1; // -1 for next loop's pre-increment
+ word.ptr = value->ptr;
e = value->ptr + value->len;
- while (++word.ptr < e) {
+ while (1) {
+ if (word.ptr >= e) {
+ /* empty header or empty value */
+ goto fail;
+ }
+
/* skip leading delimiter and blanks */
- if (unlikely(HTTP_IS_LWS(*word.ptr)))
+ if (unlikely(HTTP_IS_LWS(*word.ptr))) {
+ word.ptr++;
continue;
+ }
/* digits only now */
for (cl = 0, n = word.ptr; n < e; n++) {
@@ -125,6 +132,13 @@ int h2_parse_cont_len_header(unsigned int *msgf, struct ist *value, unsigned lon
*msgf |= H2_MSGF_BODY_CL;
*body_len = cl;
*value = word;
+
+ /* Now either n==e and we're done, or n points to the comma,
+ * and we skip it and continue.
+ */
+ if (n++ == e)
+ break;
+
word.ptr = n;
}
/* here we've reached the end with a single value or a series of
--
2.43.0

View File

@ -1,59 +1,68 @@
From 0f57ac20b046b70275192651d7b6c978032e6a36 Mon Sep 17 00:00:00 2001
From: Willy Tarreau <w@1wt.eu>
Date: Tue, 8 Aug 2023 15:24:54 +0200
Subject: [PATCH] MINOR: http: add new function http_path_has_forbidden_char()
As its name implies, this function checks if a path component has any
forbidden headers starting at the designated location. The goal is to
seek from the result of a successful ist_find_range() for more precise
chars. Here we're focusing on 0x00-0x1F, 0x20 and 0x23 to make sure
we're not too strict at this point.
(cherry picked from commit 30f58f4217d585efeac3d85cb1b695ba53b7760b)
[ad: backported for following fix : BUG/MINOR: h2: reject more chars
from the :path pseudo header]
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit b491940181a88bb6c69ab2afc24b93a50adfa67c)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit f7666e5e43ce63e804ebffdf224d92cfd3367282)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit c699bb17b7e334c9d56e829422e29e5a204615ec)
[wt: adj minor ctx in http.h]
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
include/haproxy/http.h | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/include/haproxy/http.h b/include/haproxy/http.h
index 8a86cb6e9..e8c5b850f 100644
--- a/include/haproxy/http.h
+++ b/include/haproxy/http.h
@@ -134,6 +134,25 @@ static inline enum http_etag_type http_get_etag_type(const struct ist etag)
return ETAG_INVALID;
}
+/* Looks into <ist> for forbidden characters for :path values (0x00..0x1F,
+ * 0x20, 0x23), starting at pointer <start> which must be within <ist>.
+ * Returns non-zero if such a character is found, 0 otherwise. When run on
+ * unlikely header match, it's recommended to first check for the presence
+ * of control chars using ist_find_ctl().
+ */
+static inline int http_path_has_forbidden_char(const struct ist ist, const char *start)
+{
+ do {
+ if ((uint8_t)*start <= 0x23) {
+ if ((uint8_t)*start < 0x20)
+ return 1;
+ if ((1U << ((uint8_t)*start & 0x1F)) & ((1<<3) | (1<<0)))
+ return 1;
+ }
+ start++;
+ } while (start < istend(ist));
+ return 0;
+}
#endif /* _HAPROXY_HTTP_H */
--
2.43.0
From 1d5e49737cf815f3a65d677c26bbf7ce56112458 Mon Sep 17 00:00:00 2001
From: Willy Tarreau <w@1wt.eu>
Date: Tue, 8 Aug 2023 15:24:54 +0200
Subject: MINOR: http: add new function http_path_has_forbidden_char()
As its name implies, this function checks if a path component has any
forbidden headers starting at the designated location. The goal is to
seek from the result of a successful ist_find_range() for more precise
chars. Here we're focusing on 0x00-0x1F, 0x20 and 0x23 to make sure
we're not too strict at this point.
(cherry picked from commit 30f58f4217d585efeac3d85cb1b695ba53b7760b)
[ad: backported for following fix : BUG/MINOR: h2: reject more chars
from the :path pseudo header]
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit b491940181a88bb6c69ab2afc24b93a50adfa67c)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit f7666e5e43ce63e804ebffdf224d92cfd3367282)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit c699bb17b7e334c9d56e829422e29e5a204615ec)
[wt: adj minor ctx in http.h]
Signed-off-by: Willy Tarreau <w@1wt.eu>
(cherry picked from commit 0f57ac20b046b70275192651d7b6c978032e6a36)
[wt: adj minor ctx in http.h]
Signed-off-by: Willy Tarreau <w@1wt.eu>
(cherry picked from commit 921f79588c6180c406e88236228a5be1c5c67c55)
[wt: applied to h2.c like has_forbidden_char since it will be used there]
Signed-off-by: Willy Tarreau <w@1wt.eu>
(cherry picked from commit cedfa791d1a5fd03ec6b77bfa495341af37a26c3)
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
src/h2.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/src/h2.c b/src/h2.c
index e5351d72e..014e40212 100644
--- a/src/h2.c
+++ b/src/h2.c
@@ -49,6 +49,26 @@ static int has_forbidden_char(const struct ist ist, const char *start)
return 0;
}
+/* Looks into <ist> for forbidden characters for :path values (0x00..0x1F,
+ * 0x20, 0x23), starting at pointer <start> which must be within <ist>.
+ * Returns non-zero if such a character is found, 0 otherwise. When run on
+ * unlikely header match, it's recommended to first check for the presence
+ * of control chars using ist_find_ctl().
+ */
+static inline int http_path_has_forbidden_char(const struct ist ist, const char *start)
+{
+ do {
+ if ((uint8_t)*start <= 0x23) {
+ if ((uint8_t)*start < 0x20)
+ return 1;
+ if ((1U << ((uint8_t)*start & 0x1F)) & ((1<<3) | (1<<0)))
+ return 1;
+ }
+ start++;
+ } while (start < istend(ist));
+ return 0;
+}
+
/* Prepare the request line into <*ptr> (stopping at <end>) from pseudo headers
* stored in <phdr[]>. <fields> indicates what was found so far. This should be
* called once at the detection of the first general header field or at the end
--
2.35.3

View File

@ -1,86 +1,92 @@
From edcff741698c9519dc44f3aa13de421baad7ff43 Mon Sep 17 00:00:00 2001
From: Willy Tarreau <w@1wt.eu>
Date: Tue, 8 Aug 2023 15:23:19 +0200
Subject: [PATCH] MINOR: ist: add new function ist_find_range() to find a
character range
This looks up the character range <min>..<max> in the input string and
returns a pointer to the first one found. It's essentially the equivalent
of ist_find_ctl() in that it searches by 32 or 64 bits at once, but deals
with a range.
(cherry picked from commit 197668de975e495f0c0f0e4ff51b96203fa9842d)
[ad: backported for following fix : BUG/MINOR: h2: reject more chars
from the :path pseudo header]
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit 451ac6628acc4b9eed3260501a49c60d4e4d4e55)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit 3468f7f8e04c9c5ca5c985c7511e05e78fe1eded)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit b375df60341c7f7a4904c2d8041a09c66115c754)
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
include/import/ist.h | 47 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 47 insertions(+)
diff --git a/include/import/ist.h b/include/import/ist.h
index 539a27d26..31566b105 100644
--- a/include/import/ist.h
+++ b/include/import/ist.h
@@ -746,6 +746,53 @@ static inline const char *ist_find_ctl(const struct ist ist)
return NULL;
}
+/* Returns a pointer to the first character found <ist> that belongs to the
+ * range [min:max] inclusive, or NULL if none is present. The function is
+ * optimized for strings having no such chars by processing up to sizeof(long)
+ * bytes at once on architectures supporting efficient unaligned accesses.
+ * Despite this it is not very fast (~0.43 byte/cycle) and should mostly be
+ * used on low match probability when it can save a call to a much slower
+ * function. Will not work for characters 0x80 and above. It's optimized for
+ * min and max to be known at build time.
+ */
+static inline const char *ist_find_range(const struct ist ist, unsigned char min, unsigned char max)
+{
+ const union { unsigned long v; } __attribute__((packed)) *u;
+ const char *curr = (void *)ist.ptr - sizeof(long);
+ const char *last = curr + ist.len;
+ unsigned long l1, l2;
+
+ /* easier with an exclusive boundary */
+ max++;
+
+ do {
+ curr += sizeof(long);
+ if (curr > last)
+ break;
+ u = (void *)curr;
+ /* add 0x<min><min><min><min>..<min> then subtract
+ * 0x<max><max><max><max>..<max> to the value to generate a
+ * carry in the lower byte if the byte contains a lower value.
+ * If we generate a bit 7 that was not there, it means the byte
+ * was min..max.
+ */
+ l2 = u->v;
+ l1 = ~l2 & ((~0UL / 255) * 0x80); /* 0x808080...80 */
+ l2 += (~0UL / 255) * min; /* 0x<min><min>..<min> */
+ l2 -= (~0UL / 255) * max; /* 0x<max><max>..<max> */
+ } while ((l1 & l2) == 0);
+
+ last += sizeof(long);
+ if (__builtin_expect(curr < last, 0)) {
+ do {
+ if ((unsigned char)(*curr - min) < (unsigned char)(max - min))
+ return curr;
+ curr++;
+ } while (curr < last);
+ }
+ return NULL;
+}
+
/* looks for first occurrence of character <chr> in string <ist> and returns
* the tail of the string starting with this character, or (ist.end,0) if not
* found.
--
2.43.0
From e55c2ade33b74ccf636e18feae0d158683bc1b34 Mon Sep 17 00:00:00 2001
From: Willy Tarreau <w@1wt.eu>
Date: Tue, 8 Aug 2023 15:23:19 +0200
Subject: MINOR: ist: add new function ist_find_range() to find a character
range
This looks up the character range <min>..<max> in the input string and
returns a pointer to the first one found. It's essentially the equivalent
of ist_find_ctl() in that it searches by 32 or 64 bits at once, but deals
with a range.
(cherry picked from commit 197668de975e495f0c0f0e4ff51b96203fa9842d)
[ad: backported for following fix : BUG/MINOR: h2: reject more chars
from the :path pseudo header]
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit 451ac6628acc4b9eed3260501a49c60d4e4d4e55)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit 3468f7f8e04c9c5ca5c985c7511e05e78fe1eded)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit b375df60341c7f7a4904c2d8041a09c66115c754)
Signed-off-by: Willy Tarreau <w@1wt.eu>
(cherry picked from commit edcff741698c9519dc44f3aa13de421baad7ff43)
Signed-off-by: Willy Tarreau <w@1wt.eu>
(cherry picked from commit cbac8632582d82a1452ccb3fe3c38196e8ad9f45)
Signed-off-by: Willy Tarreau <w@1wt.eu>
(cherry picked from commit 77c014ea018b80095329402264ae8887398ef4e8)
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
include/common/ist.h | 47 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 47 insertions(+)
diff --git a/include/common/ist.h b/include/common/ist.h
index 986e1df9f..5eb8bf23b 100644
--- a/include/common/ist.h
+++ b/include/common/ist.h
@@ -407,6 +407,53 @@ static inline const char *ist_find_ctl(const struct ist ist)
return NULL;
}
+/* Returns a pointer to the first character found <ist> that belongs to the
+ * range [min:max] inclusive, or NULL if none is present. The function is
+ * optimized for strings having no such chars by processing up to sizeof(long)
+ * bytes at once on architectures supporting efficient unaligned accesses.
+ * Despite this it is not very fast (~0.43 byte/cycle) and should mostly be
+ * used on low match probability when it can save a call to a much slower
+ * function. Will not work for characters 0x80 and above. It's optimized for
+ * min and max to be known at build time.
+ */
+static inline const char *ist_find_range(const struct ist ist, unsigned char min, unsigned char max)
+{
+ const union { unsigned long v; } __attribute__((packed)) *u;
+ const char *curr = (void *)ist.ptr - sizeof(long);
+ const char *last = curr + ist.len;
+ unsigned long l1, l2;
+
+ /* easier with an exclusive boundary */
+ max++;
+
+ do {
+ curr += sizeof(long);
+ if (curr > last)
+ break;
+ u = (void *)curr;
+ /* add 0x<min><min><min><min>..<min> then subtract
+ * 0x<max><max><max><max>..<max> to the value to generate a
+ * carry in the lower byte if the byte contains a lower value.
+ * If we generate a bit 7 that was not there, it means the byte
+ * was min..max.
+ */
+ l2 = u->v;
+ l1 = ~l2 & ((~0UL / 255) * 0x80); /* 0x808080...80 */
+ l2 += (~0UL / 255) * min; /* 0x<min><min>..<min> */
+ l2 -= (~0UL / 255) * max; /* 0x<max><max>..<max> */
+ } while ((l1 & l2) == 0);
+
+ last += sizeof(long);
+ if (__builtin_expect(curr < last, 0)) {
+ do {
+ if ((unsigned char)(*curr - min) < (unsigned char)(max - min))
+ return curr;
+ curr++;
+ } while (curr < last);
+ }
+ return NULL;
+}
+
/* looks for first occurrence of character <chr> in string <ist> and returns
* the tail of the string starting with this character, or (ist.end,0) if not
* found.
--
2.35.3

View File

@ -0,0 +1,39 @@
From 7a18c6a2887b542896a2a0242189e7035155f0d5 Mon Sep 17 00:00:00 2001
From: Christopher Faulet <cfaulet@haproxy.com>
Date: Thu, 22 Oct 2020 14:37:12 +0200
Subject: MINOR: ist: Add istend() function to return a pointer to the end of
the string
istend() is a shortcut to istptr() + istlen().
(cherry picked from commit cf26623780bdd66f4fff4154d0e5081082aff89b)
[wt: needed for next fix]
Signed-off-by: Willy Tarreau <w@1wt.eu>
(cherry picked from commit b12ab9c04a896a90383dbaf5c808a6d9a26cde98)
Signed-off-by: Willy Tarreau <w@1wt.eu>
(cherry picked from commit 7a62a17abd2cc6f14a3cca47043db0061e2f6664)
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
include/common/ist.h | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/include/common/ist.h b/include/common/ist.h
index 5eb8bf23b..fbbfcbef7 100644
--- a/include/common/ist.h
+++ b/include/common/ist.h
@@ -119,6 +119,12 @@ static inline size_t istlen(const struct ist ist)
return ist.len;
}
+/* returns the pointer to the end the string */
+static inline char *istend(const struct ist ist)
+{
+ return (ist.ptr + ist.len);
+}
+
/* skips to next character in the string, always stops at the end */
static inline struct ist istnext(const struct ist ist)
{
--
2.35.3

View File

@ -0,0 +1,87 @@
From 379a330ad8a56f6cf1031ff2cd3a093ead7e8585 Mon Sep 17 00:00:00 2001
From: Willy Tarreau <w@1wt.eu>
Date: Tue, 8 Aug 2023 19:35:25 +0200
Subject: DOC: clarify the handling of URL fragments in requests
We indicate in path/pathq/url that they may contain '#' if the frontend
is configured with "option accept-invalid-http-request", and that option
mentions the fragment as well.
(cherry picked from commit 7ab4949ef107a7088777f954de800fe8cf727796)
[ad: backported as a companion to BUG/MINOR: h1: do not accept '#' as
part of the URI component]
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit 965fb74eb180ab4f275ef907e018128e7eee0e69)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit e9903d6073ce9ff0ed8b304700e9d2b435ed8050)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit c47814a58ec153a526e8e9e822cda6e66cef5cc2)
[wt: minor ctx adj]
Signed-off-by: Willy Tarreau <w@1wt.eu>
(cherry picked from commit 3706e1754b925e56951b604cce63f3bb290ed838)
Signed-off-by: Willy Tarreau <w@1wt.eu>
(cherry picked from commit b5062da485e78f4448a617a0f8b67dc5b23065d5)
[wt: dropped pathq]
Signed-off-by: Willy Tarreau <w@1wt.eu>
(cherry picked from commit 1ee98d04314d35b694206195b8399c501776afc5)
[wt: allow to run with version 1.8]
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
doc/configuration.txt | 15 ++++++++++++---
reg-tests/http-rules/fragment_in_uri.vtc | 2 +-
2 files changed, 13 insertions(+), 4 deletions(-)
diff --git a/doc/configuration.txt b/doc/configuration.txt
index b30aaa9fb..c0607519a 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -5433,7 +5433,8 @@ no option accept-invalid-http-request
remaining ones are blocked by default unless this option is enabled. This
option also relaxes the test on the HTTP version, it allows HTTP/0.9 requests
to pass through (no version specified) and multiple digits for both the major
- and the minor version.
+ and the minor version. Finally, this option also allows incoming URLs to
+ contain fragment references ('#' after the path).
This option should never be enabled by default as it hides application bugs
and open security breaches. It should only be deployed after a problem has
@@ -15328,7 +15329,11 @@ path : string
information from databases and keep them in caches. Note that with outgoing
caches, it would be wiser to use "url" instead. With ACLs, it's typically
used to match exact file names (e.g. "/login.php"), or directory parts using
- the derivative forms. See also the "url" and "base" fetch methods.
+ the derivative forms. See also the "url" and "base" fetch methods. Please
+ note that any fragment reference in the URI ('#' after the path) is strictly
+ forbidden by the HTTP standard and will be rejected. However, if the frontend
+ receiving the request has "option accept-invalid-http-request", then this
+ fragment part will be accepted and will also appear in the path.
ACL derivatives :
path : exact string match
@@ -15502,7 +15507,11 @@ url : string
"path" is preferred over using "url", because clients may send a full URL as
is normally done with proxies. The only real use is to match "*" which does
not match in "path", and for which there is already a predefined ACL. See
- also "path" and "base".
+ also "path" and "base". Please note that any fragment reference in the URI
+ ('#' after the path) is strictly forbidden by the HTTP standard and will be
+ rejected. However, if the frontend receiving the request has "option
+ accept-invalid-http-request", then this fragment part will be accepted and
+ will also appear in the url.
ACL derivatives :
url : exact string match
diff --git a/reg-tests/http-rules/fragment_in_uri.vtc b/reg-tests/http-rules/fragment_in_uri.vtc
index 621751356..8de0adeb2 100644
--- a/reg-tests/http-rules/fragment_in_uri.vtc
+++ b/reg-tests/http-rules/fragment_in_uri.vtc
@@ -1,5 +1,5 @@
varnishtest "check for fragments in URL"
-#REQUIRE_VERSION=2.0
+#REQUIRE_VERSION=1.8
# This reg-test checks that '#' is properly blocked in requests
--
2.35.3

View File

@ -0,0 +1,84 @@
From 5f9b9c909399b51498ddabb39341416381fc06a2 Mon Sep 17 00:00:00 2001
From: Willy Tarreau <w@1wt.eu>
Date: Tue, 8 Aug 2023 15:38:28 +0200
Subject: MINOR: h2: pass accept-invalid-http-request down the request parser
We're adding a new argument "relaxed" to h2_make_htx_request() so that
we can control its level of acceptance of certain invalid requests at
the proxy level with "option accept-invalid-http-request". The goal
will be to add deactivable checks that are still desirable to have by
default. For now no test is subject to it.
(cherry picked from commit d93a00861d714313faa0395ff9e2acb14b0a2fca)
[ad: backported for following fix : BUG/MINOR: h2: reject more chars
from the :path pseudo header]
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit b6be1a4f858eb6602490c192235114c1a163fef9)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit 26fa3a285df0748fc79e73e552161268b66fb527)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit 014945a1508f43e88ac4e89950fa9037e4fb0679)
Signed-off-by: Willy Tarreau <w@1wt.eu>
(cherry picked from commit f86e994f5fb5851cd6e4f7f6b366e37765014b9f)
[wt: adjusted ctx in h2.h]
Signed-off-by: Willy Tarreau <w@1wt.eu>
(cherry picked from commit d87aeb80c45cc504274188f0e5048148f3c4f2ff)
[wt: extended to h2_make_h1_request() as well for legacy mode]
Signed-off-by: Willy Tarreau <w@1wt.eu>
(cherry picked from commit f2436eab7d21bab3d85cb750023a1770411f716e)
[wt: only kept the legacy mode part (h2-to-h1)]
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
include/common/h2.h | 2 +-
src/h2.c | 6 +++++-
src/mux_h2.c | 3 ++-
3 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/include/common/h2.h b/include/common/h2.h
index 0cecc2d4e..ef15f3cda 100644
--- a/include/common/h2.h
+++ b/include/common/h2.h
@@ -180,7 +180,7 @@ enum h2_err {
/* various protocol processing functions */
-int h2_make_h1_request(struct http_hdr *list, char *out, int osize, unsigned int *msgf);
+int h2_make_h1_request(struct http_hdr *list, char *out, int osize, unsigned int *msgf, int relaxed);
/*
* Some helpful debugging functions.
diff --git a/src/h2.c b/src/h2.c
index 014e40212..cb40b2e1b 100644
--- a/src/h2.c
+++ b/src/h2.c
@@ -166,8 +166,12 @@ static int h2_prepare_h1_reqline(uint32_t fields, struct ist *phdr, char **ptr,
*
* The Cookie header will be reassembled at the end, and for this, the <list>
* will be used to create a linked list, so its contents may be destroyed.
+ *
+ * When <relaxed> is non-nul, some non-dangerous checks will be ignored. This
+ * is in order to satisfy "option accept-invalid-http-request" for
+ * interoperability purposes.
*/
-int h2_make_h1_request(struct http_hdr *list, char *out, int osize, unsigned int *msgf)
+int h2_make_h1_request(struct http_hdr *list, char *out, int osize, unsigned int *msgf, int relaxed)
{
struct ist phdr_val[H2_PHDR_NUM_ENTRIES];
char *out_end = out + osize;
diff --git a/src/mux_h2.c b/src/mux_h2.c
index 79e70f60b..ecd9c59f8 100644
--- a/src/mux_h2.c
+++ b/src/mux_h2.c
@@ -2844,7 +2844,8 @@ static int h2_frt_decode_headers(struct h2s *h2s, struct buffer *buf, int count)
/* OK now we have our header list in <list> */
msgf = (h2c->dff & H2_F_DATA_END_STREAM) ? 0 : H2_MSGF_BODY;
- outlen = h2_make_h1_request(list, bi_end(buf), try, &msgf);
+ outlen = h2_make_h1_request(list, bi_end(buf), try, &msgf,
+ !!(((const struct session *)h2c->conn->owner)->fe->options2 & PR_O2_REQBUG_OK));
if (outlen < 0) {
h2c_error(h2c, H2_ERR_COMPRESSION_ERROR);
--
2.35.3

View File

@ -0,0 +1,77 @@
From 2d848a09fb7a1fb661a418cc07c59496d7eb6b3e Mon Sep 17 00:00:00 2001
From: Willy Tarreau <w@1wt.eu>
Date: Tue, 8 Aug 2023 19:53:51 +0200
Subject: REGTESTS: http-rules: verify that we block '#' by default for
normalize-uri
Since we now block fragments by default, let's add an extra test there
to confirm that it's blocked even when stripping it.
(cherry picked from commit 4d0175b54b2b4eeb01aa6e31282b0a5b0d7d8ace)
[ad: backported to test conformance of BUG/MINOR: h1: do not accept '#'
as part of the URI component]
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit b3f26043df74c661155566a0abd56103e8116078)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit 41d161ccbbfa846b4b17ed0166ff08f6bf0c3ea1)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit b6b330eb117d520a890e5b3cd623eaa73479db1b)
Signed-off-by: Willy Tarreau <w@1wt.eu>
(cherry picked from commit 73b9b13ac2654ef5384789685e3d65ca5f2f880a)
[wt: rewrote the test for 2.2 without normalize-uri and called it
fragments-in-uri]
Signed-off-by: Willy Tarreau <w@1wt.eu>
(cherry picked from commit dbf47600f63ffe161ce08d2f0faef7e0deb32b6e)
[wt: removed tune.idle-pool.shared from global section]
Signed-off-by: Willy Tarreau <w@1wt.eu>
(cherry picked from commit f04fec9f3efe7f8b70fbe72d6a4473f01699728c)
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
reg-tests/http-rules/fragment_in_uri.vtc | 35 ++++++++++++++++++++++++
1 file changed, 35 insertions(+)
create mode 100644 reg-tests/http-rules/fragment_in_uri.vtc
diff --git a/reg-tests/http-rules/fragment_in_uri.vtc b/reg-tests/http-rules/fragment_in_uri.vtc
new file mode 100644
index 000000000..621751356
--- /dev/null
+++ b/reg-tests/http-rules/fragment_in_uri.vtc
@@ -0,0 +1,35 @@
+varnishtest "check for fragments in URL"
+#REQUIRE_VERSION=2.0
+
+# This reg-test checks that '#' is properly blocked in requests
+
+feature ignore_unknown_macro
+
+server s1 {
+ rxreq
+ txresp -hdr "connection: close"
+} -start
+
+haproxy h1 -conf {
+ global
+
+ defaults
+ mode http
+ timeout connect 1s
+ timeout client 1s
+ timeout server 1s
+
+ frontend fe_fragment_block
+ bind "fd@${fe_fragment_block}"
+ default_backend be
+
+ backend be
+ server s1 ${s1_addr}:${s1_port}
+
+} -start
+
+client c11 -connect ${h1_fe_fragment_block_sock} {
+ txreq -url "/#foo"
+ rxresp
+ expect resp.status == 400
+} -run
--
2.35.3

View File

@ -1,71 +1,76 @@
From af232e47e6264122bed3681210b054ff38ec8de8 Mon Sep 17 00:00:00 2001
From: Willy Tarreau <w@1wt.eu>
Date: Tue, 8 Aug 2023 15:40:49 +0200
Subject: [PATCH] BUG/MINOR: h2: reject more chars from the :path pseudo header
This is the h2 version of this previous fix:
BUG/MINOR: h1: do not accept '#' as part of the URI component
In addition to the current NUL/CR/LF, this will also reject all other
control chars, the space and '#' from the :path pseudo-header, to avoid
taking the '#' for a part of the path. It's still possible to fall back
to the previous behavior using "option accept-invalid-http-request".
This patch modifies the request parser to change the ":path" pseudo header
validation function with a new one that rejects 0x00-0x1F (control chars),
space and '#'. This way such chars will be dropped early in the chain, and
the search for '#' doesn't incur a second pass over the header's value.
This should be progressively backported to stable versions, along with the
following commits it relies on:
REGTESTS: http-rules: add accept-invalid-http-request for normalize-uri tests
REORG: http: move has_forbidden_char() from h2.c to http.h
MINOR: ist: add new function ist_find_range() to find a character range
MINOR: http: add new function http_path_has_forbidden_char()
MINOR: h2: pass accept-invalid-http-request down the request parser
(cherry picked from commit b3119d4fb4588087e2483a80b01d322683719e29)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit 462a8600ce9e478573a957e046b446a7dcffd286)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit 648e59e30723b8fd4e71aab02cb679f6ea7446e7)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit c8e07f2fd8b5462527f102f7145d6027c0d041da)
[wt: minor ctx adjustments]
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
src/h2.c | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
diff --git a/src/h2.c b/src/h2.c
index 94c384111..e190c52b5 100644
--- a/src/h2.c
+++ b/src/h2.c
@@ -440,11 +440,18 @@ int h2_make_htx_request(struct http_hdr *list, struct htx *htx, unsigned int *ms
}
/* RFC7540#10.3: intermediaries forwarding to HTTP/1 must take care of
- * rejecting NUL, CR and LF characters.
+ * rejecting NUL, CR and LF characters. For :path we reject all CTL
+ * chars, spaces, and '#'.
*/
- ctl = ist_find_ctl(list[idx].v);
- if (unlikely(ctl) && has_forbidden_char(list[idx].v, ctl))
- goto fail;
+ if (phdr == H2_PHDR_IDX_PATH && !relaxed) {
+ ctl = ist_find_range(list[idx].v, 0, '#');
+ if (unlikely(ctl) && http_path_has_forbidden_char(list[idx].v, ctl))
+ goto fail;
+ } else {
+ ctl = ist_find_ctl(list[idx].v);
+ if (unlikely(ctl) && has_forbidden_char(list[idx].v, ctl))
+ goto fail;
+ }
if (phdr > 0 && phdr < H2_PHDR_NUM_ENTRIES) {
/* insert a pseudo header by its index (in phdr) and value (in value) */
--
2.43.0
From d81b4c952dae3468e73f4df701c62ac3a8644ba0 Mon Sep 17 00:00:00 2001
From: Willy Tarreau <w@1wt.eu>
Date: Tue, 8 Aug 2023 15:40:49 +0200
Subject: BUG/MINOR: h2: reject more chars from the :path pseudo header
This is the h2 version of this previous fix:
BUG/MINOR: h1: do not accept '#' as part of the URI component
In addition to the current NUL/CR/LF, this will also reject all other
control chars, the space and '#' from the :path pseudo-header, to avoid
taking the '#' for a part of the path. It's still possible to fall back
to the previous behavior using "option accept-invalid-http-request".
This patch modifies the request parser to change the ":path" pseudo header
validation function with a new one that rejects 0x00-0x1F (control chars),
space and '#'. This way such chars will be dropped early in the chain, and
the search for '#' doesn't incur a second pass over the header's value.
This should be progressively backported to stable versions, along with the
following commits it relies on:
REGTESTS: http-rules: add accept-invalid-http-request for normalize-uri tests
REORG: http: move has_forbidden_char() from h2.c to http.h
MINOR: ist: add new function ist_find_range() to find a character range
MINOR: http: add new function http_path_has_forbidden_char()
MINOR: h2: pass accept-invalid-http-request down the request parser
(cherry picked from commit b3119d4fb4588087e2483a80b01d322683719e29)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit 462a8600ce9e478573a957e046b446a7dcffd286)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit 648e59e30723b8fd4e71aab02cb679f6ea7446e7)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit c8e07f2fd8b5462527f102f7145d6027c0d041da)
[wt: minor ctx adjustments]
Signed-off-by: Willy Tarreau <w@1wt.eu>
(cherry picked from commit af232e47e6264122bed3681210b054ff38ec8de8)
Signed-off-by: Willy Tarreau <w@1wt.eu>
(cherry picked from commit e0c9008874b89621449f7ff3e9bc6db4e94fac6d)
[wt: note: added as well for legacy mode, though since h2 is turned
to h1 in this mode, this will be rejected anyway]
Signed-off-by: Willy Tarreau <w@1wt.eu>
(cherry picked from commit ad05bf865cdc77e1c48d2e608ef8c39bd6c08c31)
[wt: dropped the htx part]
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
src/h2.c | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/src/h2.c b/src/h2.c
index cb40b2e1b..ff8ae4572 100644
--- a/src/h2.c
+++ b/src/h2.c
@@ -208,9 +208,15 @@ int h2_make_h1_request(struct http_hdr *list, char *out, int osize, unsigned int
/* RFC7540#10.3: intermediaries forwarding to HTTP/1 must take care of
* rejecting NUL, CR and LF characters.
*/
- ctl = ist_find_ctl(list[idx].v);
- if (unlikely(ctl) && has_forbidden_char(list[idx].v, ctl))
- goto fail;
+ if (phdr == H2_PHDR_IDX_PATH && !relaxed) {
+ ctl = ist_find_range(list[idx].v, 0, '#');
+ if (unlikely(ctl) && http_path_has_forbidden_char(list[idx].v, ctl))
+ goto fail;
+ } else {
+ ctl = ist_find_ctl(list[idx].v);
+ if (unlikely(ctl) && has_forbidden_char(list[idx].v, ctl))
+ goto fail;
+ }
if (phdr > 0 && phdr < H2_PHDR_NUM_ENTRIES) {
/* insert a pseudo header by its index (in phdr) and value (in value) */
--
2.35.3

View File

@ -1,119 +1,124 @@
From e5a741f94977840c58775b38f8ed830207f7e4d0 Mon Sep 17 00:00:00 2001
From: Willy Tarreau <w@1wt.eu>
Date: Tue, 8 Aug 2023 16:17:22 +0200
Subject: [PATCH] BUG/MINOR: h1: do not accept '#' as part of the URI component
Seth Manesse and Paul Plasil reported that the "path" sample fetch
function incorrectly accepts '#' as part of the path component. This
can in some cases lead to misrouted requests for rules that would apply
on the suffix:
use_backend static if { path_end .png .jpg .gif .css .js }
Note that this behavior can be selectively configured using
"normalize-uri fragment-encode" and "normalize-uri fragment-strip".
The problem is that while the RFC says that this '#' must never be
emitted, as often it doesn't suggest how servers should handle it. A
diminishing number of servers still do accept it and trim it silently,
while others are rejecting it, as indicated in the conversation below
with other implementers:
https://lists.w3.org/Archives/Public/ietf-http-wg/2023JulSep/0070.html
Looking at logs from publicly exposed servers, such requests appear at
a rate of roughly 1 per million and only come from attacks or poorly
written web crawlers incorrectly following links found on various pages.
Thus it looks like the best solution to this problem is to simply reject
such ambiguous requests by default, and include this in the list of
controls that can be disabled using "option accept-invalid-http-request".
We're already rejecting URIs containing any control char anyway, so we
should also reject '#'.
In the H1 parser for the H1_MSG_RQURI state, there is an accelerated
parser for bytes 0x21..0x7e that has been tightened to 0x24..0x7e (it
should not impact perf since 0x21..0x23 are not supposed to appear in
a URI anyway). This way '#' falls through the fine-grained filter and
we can add the special case for it also conditionned by a check on the
proxy's option "accept-invalid-http-request", with no overhead for the
vast majority of valid URIs. Here this information is available through
h1m->err_pos that's set to -2 when the option is here (so we don't need
to change the API to expose the proxy). Example with a trivial GET
through netcat:
[08/Aug/2023:16:16:52.651] frontend layer1 (#2): invalid request
backend <NONE> (#-1), server <NONE> (#-1), event #0, src 127.0.0.1:50812
buffer starts at 0 (including 0 out), 16361 free,
len 23, wraps at 16336, error at position 7
H1 connection flags 0x00000000, H1 stream flags 0x00000810
H1 msg state MSG_RQURI(4), H1 msg flags 0x00001400
H1 chunk len 0 bytes, H1 body len 0 bytes :
00000 GET /aa#bb HTTP/1.0\r\n
00021 \r\n
This should be progressively backported to all stable versions along with
the following patch:
REGTESTS: http-rules: add accept-invalid-http-request for normalize-uri tests
Similar fixes for h2 and h3 will come in followup patches.
Thanks to Seth Manesse and Paul Plasil for reporting this problem with
detailed explanations.
(cherry picked from commit 2eab6d354322932cfec2ed54de261e4347eca9a6)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit 9bf75c8e22a8f2537f27c557854a8803087046d0)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit 9facd01c9ac85fe9bcb331594b80fa08e7406552)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit 832b672eee54866c7a42a1d46078cc9ae0d544d9)
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
src/h1.c | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
diff --git a/src/h1.c b/src/h1.c
index eeda311b7..91d3dc47a 100644
--- a/src/h1.c
+++ b/src/h1.c
@@ -480,13 +480,13 @@ int h1_headers_to_hdr_list(char *start, const char *stop,
case H1_MSG_RQURI:
http_msg_rquri:
#ifdef HA_UNALIGNED_LE
- /* speedup: skip bytes not between 0x21 and 0x7e inclusive */
+ /* speedup: skip bytes not between 0x24 and 0x7e inclusive */
while (ptr <= end - sizeof(int)) {
- int x = *(int *)ptr - 0x21212121;
+ int x = *(int *)ptr - 0x24242424;
if (x & 0x80808080)
break;
- x -= 0x5e5e5e5e;
+ x -= 0x5b5b5b5b;
if (!(x & 0x80808080))
break;
@@ -498,8 +498,15 @@ int h1_headers_to_hdr_list(char *start, const char *stop,
goto http_msg_ood;
}
http_msg_rquri2:
- if (likely((unsigned char)(*ptr - 33) <= 93)) /* 33 to 126 included */
+ if (likely((unsigned char)(*ptr - 33) <= 93)) { /* 33 to 126 included */
+ if (*ptr == '#') {
+ if (h1m->err_pos < -1) /* PR_O2_REQBUG_OK not set */
+ goto invalid_char;
+ if (h1m->err_pos == -1) /* PR_O2_REQBUG_OK set: just log */
+ h1m->err_pos = ptr - start + skip;
+ }
EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_rquri2, http_msg_ood, state, H1_MSG_RQURI);
+ }
if (likely(HTTP_IS_SPHT(*ptr))) {
sl.rq.u.len = ptr - sl.rq.u.ptr;
--
2.43.0
From 4e98c0c1d36104ed426d3b198a176e1a5df814fa Mon Sep 17 00:00:00 2001
From: Willy Tarreau <w@1wt.eu>
Date: Tue, 8 Aug 2023 16:17:22 +0200
Subject: BUG/MINOR: h1: do not accept '#' as part of the URI component
Seth Manesse and Paul Plasil reported that the "path" sample fetch
function incorrectly accepts '#' as part of the path component. This
can in some cases lead to misrouted requests for rules that would apply
on the suffix:
use_backend static if { path_end .png .jpg .gif .css .js }
Note that this behavior can be selectively configured using
"normalize-uri fragment-encode" and "normalize-uri fragment-strip".
The problem is that while the RFC says that this '#' must never be
emitted, as often it doesn't suggest how servers should handle it. A
diminishing number of servers still do accept it and trim it silently,
while others are rejecting it, as indicated in the conversation below
with other implementers:
https://lists.w3.org/Archives/Public/ietf-http-wg/2023JulSep/0070.html
Looking at logs from publicly exposed servers, such requests appear at
a rate of roughly 1 per million and only come from attacks or poorly
written web crawlers incorrectly following links found on various pages.
Thus it looks like the best solution to this problem is to simply reject
such ambiguous requests by default, and include this in the list of
controls that can be disabled using "option accept-invalid-http-request".
We're already rejecting URIs containing any control char anyway, so we
should also reject '#'.
In the H1 parser for the H1_MSG_RQURI state, there is an accelerated
parser for bytes 0x21..0x7e that has been tightened to 0x24..0x7e (it
should not impact perf since 0x21..0x23 are not supposed to appear in
a URI anyway). This way '#' falls through the fine-grained filter and
we can add the special case for it also conditionned by a check on the
proxy's option "accept-invalid-http-request", with no overhead for the
vast majority of valid URIs. Here this information is available through
h1m->err_pos that's set to -2 when the option is here (so we don't need
to change the API to expose the proxy). Example with a trivial GET
through netcat:
[08/Aug/2023:16:16:52.651] frontend layer1 (#2): invalid request
backend <NONE> (#-1), server <NONE> (#-1), event #0, src 127.0.0.1:50812
buffer starts at 0 (including 0 out), 16361 free,
len 23, wraps at 16336, error at position 7
H1 connection flags 0x00000000, H1 stream flags 0x00000810
H1 msg state MSG_RQURI(4), H1 msg flags 0x00001400
H1 chunk len 0 bytes, H1 body len 0 bytes :
00000 GET /aa#bb HTTP/1.0\r\n
00021 \r\n
This should be progressively backported to all stable versions along with
the following patch:
REGTESTS: http-rules: add accept-invalid-http-request for normalize-uri tests
Similar fixes for h2 and h3 will come in followup patches.
Thanks to Seth Manesse and Paul Plasil for reporting this problem with
detailed explanations.
(cherry picked from commit 2eab6d354322932cfec2ed54de261e4347eca9a6)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit 9bf75c8e22a8f2537f27c557854a8803087046d0)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit 9facd01c9ac85fe9bcb331594b80fa08e7406552)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit 832b672eee54866c7a42a1d46078cc9ae0d544d9)
Signed-off-by: Willy Tarreau <w@1wt.eu>
(cherry picked from commit e5a741f94977840c58775b38f8ed830207f7e4d0)
Signed-off-by: Willy Tarreau <w@1wt.eu>
(cherry picked from commit 178cea76b1c9d9413afa6961b6a4576fcb5b26fa)
[wt: applied the same to http_parse_reqline() in http_msg.c]
Signed-off-by: Willy Tarreau <w@1wt.eu>
(cherry picked from commit 4ad6fd9eeb3078685fffdc58f1c6d4eb97e05d98)
[wt: dropped the HTX part, adapted the legacy one in http_msg.c]
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
src/h1.c | 13 ++++++++++---
1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/src/h1.c b/src/h1.c
index d3a20c2ed..57be42f31 100644
--- a/src/h1.c
+++ b/src/h1.c
@@ -341,11 +341,11 @@ const char *http_parse_reqline(struct http_msg *msg,
defined(__ARM_ARCH_7A__)
/* speedup: skip bytes not between 0x21 and 0x7e inclusive */
while (ptr <= end - sizeof(int)) {
- int x = *(int *)ptr - 0x21212121;
+ int x = *(int *)ptr - 0x24242424;
if (x & 0x80808080)
break;
- x -= 0x5e5e5e5e;
+ x -= 0x5b5b5b5b;
if (!(x & 0x80808080))
break;
@@ -357,8 +357,15 @@ const char *http_parse_reqline(struct http_msg *msg,
goto http_msg_ood;
}
http_msg_rquri2:
- if (likely((unsigned char)(*ptr - 33) <= 93)) /* 33 to 126 included */
+ if (likely((unsigned char)(*ptr - 33) <= 93)) { /* 33 to 126 included */
+ if (*ptr == '#') {
+ if (msg->err_pos < -1) /* PR_O2_REQBUG_OK not set */
+ goto invalid_char;
+ if (msg->err_pos == -1) /* PR_O2_REQBUG_OK set: just log */
+ msg->err_pos = ptr - msg_start;
+ }
EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_rquri2, http_msg_ood, state, HTTP_MSG_RQURI);
+ }
if (likely(HTTP_IS_SPHT(*ptr))) {
msg->sl.rq.u_l = ptr - msg_start - msg->sl.rq.u;
--
2.35.3

View File

@ -4,14 +4,14 @@ After=network-online.target
Wants=network-online.target
[Service]
EnvironmentFile=-/etc/sysconfig/haproxy
Environment="CONFIG=/etc/haproxy/haproxy.cfg" "PIDFILE=/run/haproxy.pid" "CFGDIR=/etc/haproxy/conf.d"
EnvironmentFile=/etc/sysconfig/haproxy
ExecStartPre=/usr/sbin/haproxy -f $CONFIG -f $CFGDIR -c -q $OPTIONS
ExecStart=/usr/sbin/haproxy -Ws -f $CONFIG -f $CFGDIR -p $PIDFILE $OPTIONS
ExecReload=/usr/sbin/haproxy -f $CONFIG -f $CFGDIR -c -q $OPTIONS
ExecReload=/bin/kill -USR2 $MAINPID
KillMode=mixed
SuccessExitStatus=143
KillMode=mixed
Type=notify
[Install]

View File

@ -0,0 +1,45 @@
From 58b3d8676bbef52bc76dd79ecfcf74582c34ec97 Mon Sep 17 00:00:00 2001
From: William Lallemand <wlallemand@haproxy.org>
Date: Thu, 17 Dec 2020 18:48:06 +0100
Subject: [PATCH] BUG/MEDIUM: mworker: fix again copy_argv()
When backporting patch df6c5a8 ("BUG/MEDIUM: mworker: fix the copy of
options in copy_argv()") part of the patch was removed by mistake.
Letting the bug #644 unfixed.
This patch fixes the problem by reintroducing the missing part.
1.8 only, no backport needed.
---
src/haproxy.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/src/haproxy.c b/src/haproxy.c
index 5ddf4d05..3947505b 100644
--- a/src/haproxy.c
+++ b/src/haproxy.c
@@ -1328,6 +1328,21 @@ static char **copy_argv(int argc, char **argv)
}
break;
+ case 'C':
+ case 'n':
+ case 'm':
+ case 'N':
+ case 'L':
+ case 'f':
+ case 'p':
+ /* these options have only 1 parameter which must be copied and can start with a '-' */
+ *newargv++ = *argv++;
+ argc--;
+ if (argc == 0)
+ goto error;
+ *newargv++ = *argv++;
+ argc--;
+ break;
default:
/* for other options just copy them without parameters, this is also done
* for options like "--foo", but this will fail in the argument parser.
--
2.26.2

View File

@ -0,0 +1,25 @@
From eaf1d768085a924a5322cfc77439ba5a4945bbae Mon Sep 17 00:00:00 2001
From: Ryan O'Hara <rohara@redhat.com>
Date: Thu, 14 Oct 2021 14:08:39 -0500
Subject: [PATCH] Fix short HTTP responses to client
---
src/raw_sock.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/raw_sock.c b/src/raw_sock.c
index ad0210105..fbf20ae35 100644
--- a/src/raw_sock.c
+++ b/src/raw_sock.c
@@ -302,7 +302,7 @@ static int raw_sock_to_buf(struct connection *conn, struct buffer *buf, int coun
if (ret > 0) {
buf->i += ret;
done += ret;
- if (ret < try) {
+ if (0 && ret < try) {
/* unfortunately, on level-triggered events, POLL_HUP
* is generally delivered AFTER the system buffer is
* empty, unless the poller supports POLL_RDHUP. If
--
2.31.1

View File

@ -7,40 +7,43 @@
%global _hardened_build 1
Name: haproxy
Version: 2.4.22
Release: 3%{?dist}
Version: 1.8.27
Release: 5%{?dist}.1
Summary: HAProxy reverse proxy for high availability environments
Group: System Environment/Daemons
License: GPLv2+
URL: http://www.haproxy.org/
Source0: %{url}/download/2.4/src/haproxy-%{version}.tar.gz
Source0: http://www.haproxy.org/download/1.8/src/haproxy-%{version}.tar.gz
Source1: %{name}.service
Source2: %{name}.cfg
Source3: %{name}.logrotate
Source4: %{name}.sysconfig
Source5: %{name}.sysusers
Source6: halog.1
Source5: halog.1
Patch0: RHEL-7736_http-reject-empty-content-length-header.patch
Patch1: RHEL-18169_h1-reject-special-char-URI-path-component.patch
Patch2: RHEL-18169_h2-pass-accept-invalid-http-request-request-parser.patch
Patch3: RHEL-18169_h2-reject-special-char-from-pseudo-path-header.patch
Patch4: RHEL-18169_http-add-new-function-http_path_has_forbidden_char.patch
Patch5: RHEL-18169_ist-add-new-function-ist_find_range.patch
Patch6: RHEL-18169_regtest-add-accept-invalid-http-request.patch
Patch0: rhbz1838319-mworker-fix-again-copy_argv.patch
Patch1: rhbz1941446-fix-short-http-responses.patch
Patch2: CVE-2023-45539-reject-pound-char-URI-component.patch
Patch3: CVE-2023-45539-regtest-verify-pound-char-URI.patch
Patch4: CVE-2023-45539-doc-clarify-URL-fragment-handling.patch
Patch5: CVE-2023-45539-add-ist_find_range-function.patch
Patch6: CVE-2023-45539-add-istend-function.patch
Patch7: CVE-2023-45539-add-http_path_forbidden_char-function.patch
Patch8: CVE-2023-45539-pass-accept-invalid-http-request-parser.patch
Patch9: CVE-2023-45539-reject-chars-from-path-pseudo-header.patch
BuildRequires: gcc
BuildRequires: lua-devel
BuildRequires: pcre2-devel
BuildRequires: pcre-devel
BuildRequires: zlib-devel
BuildRequires: openssl-devel
BuildRequires: systemd-devel
BuildRequires: systemd
BuildRequires: systemd-rpm-macros
BuildRequires: make
BuildRequires: systemd-units
Requires(pre): shadow-utils
%{?systemd_requires}
Requires(pre): shadow-utils
Requires(post): systemd
Requires(preun): systemd
Requires(postun): systemd
%description
HAProxy is a TCP/HTTP reverse proxy which is particularly suited for high
@ -58,13 +61,16 @@ availability environments. Indeed, it can:
%prep
%setup -q
%patch -P0 -p1
%patch -P1 -p1
%patch -P2 -p1
%patch -P3 -p1
%patch -P4 -p1
%patch -P5 -p1
%patch -P6 -p1
%patch0 -p1
%patch1 -p1
%patch2 -p1
%patch3 -p1
%patch4 -p1
%patch5 -p1
%patch6 -p1
%patch7 -p1
%patch8 -p1
%patch9 -p1
%build
regparm_opts=
@ -72,12 +78,14 @@ regparm_opts=
regparm_opts="USE_REGPARM=1"
%endif
%{__make} %{?_smp_mflags} CPU="generic" TARGET="linux-glibc" USE_OPENSSL=1 USE_PCRE2=1 USE_SLZ=1 USE_LUA=1 USE_CRYPT_H=1 USE_SYSTEMD=1 USE_LINUX_TPROXY=1 USE_GETADDRINFO=1 USE_PROMEX=1 ${regparm_opts} ADDINC="%{build_cflags}" ADDLIB="%{build_ldflags}"
%{__make} %{?_smp_mflags} CPU="generic" TARGET="linux2628" USE_OPENSSL=1 USE_PCRE=1 USE_ZLIB=1 USE_LUA=1 USE_CRYPT_H=1 USE_SYSTEMD=1 USE_LINUX_TPROXY=1 USE_GETADDRINFO=1 ${regparm_opts} ADDINC="%{optflags}" ADDLIB="%{__global_ldflags}"
%{__make} admin/halog/halog ADDINC="%{build_cflags}" ADDLIB="%{build_ldflags}"
pushd contrib/halog
%{__make} ${halog} OPTIMIZE="%{optflags} %{build_ldflags}" LDFLAGS=
popd
pushd admin/iprange
%{__make} OPTIMIZE="%{build_cflags}" LDFLAGS="%{build_ldflags}"
pushd contrib/iprange
%{__make} ${iprange} OPTIMIZE="%{optflags} %{build_ldflags}" LDFLAGS=
popd
%install
@ -88,15 +96,14 @@ popd
%{__install} -p -D -m 0644 %{SOURCE2} %{buildroot}%{haproxy_confdir}/%{name}.cfg
%{__install} -p -D -m 0644 %{SOURCE3} %{buildroot}%{_sysconfdir}/logrotate.d/%{name}
%{__install} -p -D -m 0644 %{SOURCE4} %{buildroot}%{_sysconfdir}/sysconfig/%{name}
%{__install} -p -D -m 0644 %{SOURCE5} %{buildroot}%{_sysusersdir}/%{name}.conf
%{__install} -p -D -m 0644 %{SOURCE6} %{buildroot}%{_mandir}/man1/halog.1
%{__install} -p -D -m 0644 %{SOURCE5} %{buildroot}%{_mandir}/man1/halog.1
%{__install} -d -m 0755 %{buildroot}%{haproxy_homedir}
%{__install} -d -m 0755 %{buildroot}%{haproxy_datadir}
%{__install} -d -m 0755 %{buildroot}%{haproxy_confdir}/conf.d
%{__install} -d -m 0755 %{buildroot}%{_bindir}
%{__install} -p -m 0755 ./admin/halog/halog %{buildroot}%{_bindir}/halog
%{__install} -p -m 0755 ./admin/iprange/iprange %{buildroot}%{_bindir}/iprange
%{__install} -p -m 0755 ./admin/iprange/ip6range %{buildroot}%{_bindir}/ip6range
%{__install} -p -m 0755 ./contrib/halog/halog %{buildroot}%{_bindir}/halog
%{__install} -p -m 0755 ./contrib/iprange/iprange %{buildroot}%{_bindir}/iprange
%{__install} -p -m 0644 ./examples/errorfiles/* %{buildroot}%{haproxy_datadir}
for httpfile in $(find ./examples/errorfiles/ -type f)
do
@ -115,7 +122,12 @@ do
done
%pre
%sysusers_create_compat %{SOURCE5}
getent group %{haproxy_group} >/dev/null || \
groupadd -r %{haproxy_group}
getent passwd %{haproxy_user} >/dev/null || \
useradd -r -g %{haproxy_user} -d %{haproxy_homedir} \
-s /sbin/nologin -c "haproxy" %{haproxy_user}
exit 0
%post
%systemd_post %{name}.service
@ -127,6 +139,7 @@ done
%systemd_postun_with_restart %{name}.service
%files
%defattr(-,root,root,-)
%doc doc/* examples/*
%doc CHANGELOG README ROADMAP VERSION
%license LICENSE
@ -142,233 +155,73 @@ done
%{_sbindir}/%{name}
%{_bindir}/halog
%{_bindir}/iprange
%{_bindir}/ip6range
%{_mandir}/man1/*
%{_sysusersdir}/%{name}.conf
%changelog
* Tue Jan 23 2024 Ryan O'Hara <rohara@redhat.com> - 2.4.22-3
- Reject "#" as part of URI path component (CVE-2023-45539, RHEL-18169)
* Thu Sep 05 2024 Ryan O'Hara <rohara@redhat.com> - 1.8.27-5.1
- Reject "#" as part of URI path component (CVE-2023-45539, RHEL-18168)
* Wed Jan 17 2024 Ryan O'Hara <rohara@redhat.com> - 2.4.22-2
- Reject any empty content-length header value (CVE-2023-40225, RHEL-7736)
* Fri Jun 03 2022 Ryan O'Hara <rohara@redhat.com> - 1.8.27-5
- Add configuration directory and update systemd unit file (#1943869)
* Tue Jun 06 2023 Ryan O'Hara <rohara@redhat.com> - 2.4.22-1
- Update to 2.4.22 (#2196530)
* Tue Jan 18 2022 Ryan O'Hara <rohara@redhat.com> - 1.8.27-4
- Apply patch (#1941446)
* Tue May 02 2023 Ryan O'Hara <rohara@redhat.com> - 2.4.17-7
- Fix uninitizalized resevered bytes (CVE-2023-0836, #2180861)
* Fri Oct 15 2021 Ryan O'Hara <rohara@redhat.com> - 1.8.27-3
- Fix short HTTP responses (#1941446)
* Mon Feb 27 2023 Ryan O'Hara <rohara@redhat.com> - 2.4.17-6
- Reject empty http header field names (CVE-2023-25725, #2169510)
* Thu Dec 17 2020 Ryan O'Hara <rohara@redhat.com> - 1.8.27-2
- Fix copy_argv for arguments that begin with hypen (#1838319)
* Mon Feb 27 2023 Ryan O'Hara <rohara@redhat.com> - 2.4.17-5
- Refuse interim responses with end-stream flag set (CVE-2023-0056, #2161140)
* Thu Dec 10 2020 Ryan O'Hara <rohara@redhat.com> - 1.8.27-1
- Update to 1.8.27 (#1905663, #1838319)
* Wed Nov 30 2022 Ryan O'Hara <rohara@redhat.com> - 2.4.17-4
- Use systemd-sysusers for user/group creation (#2095422)
* Thu Jun 18 2020 Ryan O'Hara <rohara@redhat.com> - 1.8.23-5
- Use OPTIONS from systemd EnvironmentFile (#1845611)
* Mon Jul 25 2022 Ryan O'Hara <rohara@redhat.com> - 2.4.17-3
- Fix changelog and rebuild
* Wed Jun 17 2020 Ryan O'Hara <rohara@redhat.com> - 1.8.23-4
- Wait for network to be online before starting (#1756714)
* Wed Jun 08 2022 Ryan O'Hara <rohara@redhat.com> - 2.4.17-2
- Add configuration directory and update systemd unit file (#2093482)
* Wed Apr 01 2020 Ryan O'Hara <rohara@redhat.com> - 1.8.23-3
- Fix hapack zero byte input causing overwrite (CVE-2020-11100, #1819519)
* Wed May 25 2022 Ryan O'Hara <rohara@redhat.com> - 2.4.17-1
- Update to 2.4.17 #(2088532)
- Fix unbound loop when Set-Cookie2 header is present (#2070448)
* Fri Dec 13 2019 Ryan O'Hara <rohara@redhat.com> - 1.8.23-2
- Consider exist status 143 as success (#1778844)
* Wed Oct 13 2021 Ryan O'Hara <rohara@redhat.com> - 2.4.7-1
- Update to 2.4.7 (#1966688)
- Fix domain parts in :scheme and :path fields (CVE-2021-39240, #1998196)
- Fix spaces in the :method field (CVE-2021-39241, #1998198)
- Fix mismatch between :authority and Host fields (CVE-2021-39242, #1998200)
- Fix request smuggling attack or response splitting (CVE-2021-40346, #2000621)
* Mon Dec 02 2019 Ryan O'Hara <rohara@redhat.com> - 1.8.23-1
- Update to 1.8.23 (#1774745)
* Tue Aug 17 2021 Ryan O'Hara <rohara@redhat.com> - 2.4.3-1
- Update to 2.4.3 (#1966688)
* Fri Jul 19 2019 Ryan O'Hara <rohara@redhat.com> - 1.8.15-6
- Add gating tests (#1682106)
* Tue Aug 10 2021 Ryan O'Hara <rohara@redhat.com> - 2.4.2-8
- Add gating tests (#1966688)
* Wed Jan 09 2019 Ryan O'Hara <rohara@redhat.com> - 1.8.15-5
- Resolve CVE-2018-20615 (#1664533)
* Mon Aug 09 2021 Mohan Boddu <mboddu@redhat.com> - 2.4.2-7
- Rebuilt for IMA sigs, glibc 2.34, aarch64 flags
Related: rhbz#1991688
* Sun Dec 16 2018 Ryan O'Hara <rohara@redhat.com> - 1.8.15-4
- Use empty LDFLAGS to prevent stripping, maintain hardened build
* Sat Aug 07 2021 Ryan O'Hara <rohara@redhat.com> - 2.4.2-6
- Ignore badfuncs error in rpminspect (#1966688)
* Sat Dec 15 2018 Ryan O'Hara <rohara@redhat.com> - 1.8.15-3
- Use LDFLAGS when building contib tools to prevent binary stripping
* Wed Aug 04 2021 Lukas Javorsky <ljavorsk@redhat.com> - 2.4.2-5
- Second rebuild against pcre2-10.37 (bug #1970765)
* Tue Aug 03 2021 Ryan O'Hara <rohara@redhat.com> - 2.4.2-4
- Apply patch to fix OpenSSL 3.0 build (#1984786)
* Mon Aug 02 2021 Ryan O'Hara <rohara@redhat.com> - 2.4.2-3
- Fix OpenSSL 3.0 build (#1984786)
* Wed Jul 28 2021 Lukas Javorsky <ljavorsk@redhat.com> - 2.4.2-2
- Rebuild against pcre2-10.37 (bug #1970765)
* Mon Jul 12 2021 Ryan O'Hara <rohara@redhat.com> - 2.4.2-1
- Update to 2.4.2 (#1966688)
* Wed Jun 16 2021 Mohan Boddu <mboddu@redhat.com> - 2.4.0-3
- Rebuilt for RHEL 9 BETA for openssl 3.0
Related: rhbz#1971065
* Thu Jun 03 2021 Ryan O'Hara <rohara@redhat.com> - 2.4.0-2
- Fix hardened builds (#1966688)
* Tue Jun 01 2021 Ryan O'Hara <rohara@redhat.com> - 2.4.0-1
- Update to 2.4.0 (#1966688)
* Fri Apr 16 2021 Mohan Boddu <mboddu@redhat.com> - 2.3.4-3
- Rebuilt for RHEL 9 BETA on Apr 15th 2021. Related: rhbz#1947937
* Tue Jan 26 2021 Fedora Release Engineering <releng@fedoraproject.org> - 2.3.4-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild
* Thu Jan 14 2021 Ryan O'Hara <rohara@redhat.com> - 2.3.4-1
- Update to 2.3.4 (#1914447)
* Tue Dec 08 2020 Ryan O'Hara <rohara@redhat.com> - 2.3.2-1
- Update to 2.3.2 (#1894994)
* Thu Oct 01 2020 Ryan O'Hara <rohara@redhat.com> - 2.2.4-1
- Update to 2.2.4 (#1883742)
* Thu Sep 17 2020 Ryan O'Hara <rohara@redhat.com> - 2.2.3-2
- Fix build for late loading of libgcc_s
* Mon Sep 14 2020 Ryan O'Hara <rohara@redhat.com> - 2.2.3-1
- Update to 2.2.3 (#1876932)
* Fri Jul 31 2020 Ryan O'Hara <rohara@redhat.com> - 2.2.2-1
- Update to 2.2.2 (#1862400)
* Mon Jul 27 2020 Ryan O'Hara <rohara@redhat.com> - 2.2.1-1
- Update to 2.2.1 (#1859846)
* Wed Jul 15 2020 Ryan O'Hara <rohara@redhat.com> - 2.2.0-3
- Update systemd service file
* Fri Jul 10 2020 Tom Callaway <spot@fedoraproject.org> - 2.2.0-2
- Fix build against lua 5.4
* Thu Jul 09 2020 Ryan O'Hara <rohara@redhat.com> - 2.2.0-1
- Update to 2.2.0 (#1854519)
* Mon Jun 15 2020 Ryan O'Hara <rohara@redhat.com> - 2.1.7-1
- Update to 2.1.7 (#1845001)
* Mon Jun 08 2020 Ryan O'Hara <rohara@redhat.com> - 2.1.6-1
- Update to 2.1.6 (#1845001)
* Mon Jun 01 2020 Ryan O'Hara <rohara@redhat.com> - 2.1.5-1
- Update to 2.1.5 (#1841837)
* Thu Apr 02 2020 Ryan O'Hara <rohara@redhat.com> - 2.1.4-1
- Update to 2.1.4 (CVE-2010-11100, #1820200)
* Mon Mar 16 2020 Ryan O'Hara <rohara@redhat.com> - 2.1.3-2
- Fix invalid element address calculation (#1801109)
* Wed Feb 12 2020 Ryan O'Hara <rohara@redhat.com> - 2.1.3-1
- Update to 2.1.3 (#1802233)
* Wed Jan 29 2020 Fedora Release Engineering <releng@fedoraproject.org> - 2.1.2-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild
* Thu Jan 02 2020 Ryan O'Hara <rohara@redhat.com> - 2.1.2-1
- Update to 2.1.2 (#1782472)
* Mon Nov 25 2019 Ryan O'Hara <rohara@redhat.com> - 2.0.10-1
- Update to 2.0.10 (#1772961)
* Wed Nov 06 2019 Ryan O'Hara <rohara@redhat.com> - 2.0.8-1
- Update to 2.0.8 (#1764483)
* Mon Oct 21 2019 Ryan O'Hara <rohara@redhat.com> - 2.0.7-2
- Build with Prometheus exporter service (#1755839)
* Mon Oct 21 2019 Ryan O'Hara <rohara@redhat.com> - 2.0.7-1
- Update to 2.0.7 (#1742544)
* Fri Sep 13 2019 Ryan O'Hara <rohara@redhat.com> - 2.0.6-1
- Update to 2.0.6 (#1742544)
* Mon Aug 19 2019 Ryan O'Hara <rohara@redhat.com> - 2.0.5-1
- Update to 2.0.5 (#1742544)
* Tue Jul 30 2019 Ryan O'Hara <rohara@redhat.com> - 2.0.3-1
- Update to 2.0.3 (#1690492)
* Tue Jul 30 2019 Ryan O'Hara <rohara@redhat.com> - 1.8.20-3
- Build with PCRE2 (#1669217)
* Thu Jul 25 2019 Fedora Release Engineering <releng@fedoraproject.org> - 1.8.20-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild
* Fri May 17 2019 Ryan O'Hara <rohara@redhat.com> - 1.8.20-1
- Update to 1.8.20
* Wed Feb 13 2019 Ryan O'Hara <rohara@redhat.com> - 1.8.19-1
- Update to 1.8.19
* Fri Feb 01 2019 Fedora Release Engineering <releng@fedoraproject.org> - 1.8.17-4
- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild
* Thu Jan 24 2019 Petr Pisar <ppisar@redhat.com> - 1.8.17-3
- Rebuild against patched libpcreposix library (bug #1667614)
* Mon Jan 14 2019 Björn Esser <besser82@fedoraproject.org> - 1.8.17-2
- Rebuilt for libcrypt.so.2 (#1666033)
* Wed Jan 09 2019 Ryan O'Hara <rohara@redhat.com> - 1.8.17-1
- Update to 1.8.17
- Fix handling of priority flag in HEADERS frame in HTTP/2 decoder (CVE-2018-20615)
* Sat Dec 22 2018 Ryan O'Hara <rohara@redhat.com> - 1.8.16-1
- Update to 1.8.16
* Fri Dec 14 2018 Ryan O'Hara <rohara@redhat.com> - 1.8.15-2
- Bump release
* Thu Dec 13 2018 Ryan O'Hara <rohara@redhat.com> - 1.8.15-1
- Update to 1.8.15
- Fix denial of service attack via infinite recursion (CVE-2018-20103, #1658881)
- Fix out-of-bound reads in dns_validate_dns_response (CVE-2018-20102, #1658882)
- Update to 1.8.15 (#1631815)
- Resolve CVE-2018-20102 (#1659017)
- Resolve CVE-2018-20103 (#1659019)
* Sat Dec 01 2018 Ryan O'Hara <rohara@redhat.com> - 1.8.14-2
- Use of crpyt() is not thread safe (#1643941)
* Tue Oct 02 2018 Ryan O'Hara <rohara@redhat.com> - 1.8.14-1
- Update to 1.8.14 (#1631815)
- Resolve CVE-2018-14645 (#1631539)
* Thu Sep 20 2018 Ryan O'Hara <rohara@redhat.com> - 1.8.14-1
- Update to 1.8.14 (#1610066)
* Wed Jul 25 2018 Ryan O'Hara <rohara@redhat.com> - 1.8.12-2
- Fix ownership of /var/lib/haproxy/ to avoid selinux DAC override errors
* Mon Aug 20 2018 Ryan O'Hara <rohara@redhat.com> - 1.8.13-1
- Update to 1.8.13 (#1610066)
* Thu Aug 16 2018 Ryan O'Hara <rohara@redhat.com> - 1.8.12-4
- Add BuildRequires gcc (#1604308)
* Fri Jul 13 2018 Fedora Release Engineering <releng@fedoraproject.org> - 1.8.12-3
- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild
* Tue Jul 10 2018 Ryan O'Hara <rohara@redhat.com> - 1.8.12-2
- Fix ownership of /var/lib/haproxy/ to avoid selinux DAC override errors (#1597076)
* Thu Jun 28 2018 Ryan O'Hara <rohara@redhat.com> - 1.8.12-1
- Update to 1.8.12 (#1580036)
* Wed Jun 27 2018 Ryan O'Hara <rohara@redhat.com> - 1.8.11-1
- Update to 1.8.11 (#1580036)
* Mon Jun 25 2018 Ryan O'Hara <rohara@redhat.com> - 1.8.10-1
- Update to 1.8.10 (#1580036)
* Mon May 21 2018 Ryan O'Hara <rohara@redhat.com> - 1.8.9-1
- Update to 1.8.9 (#1580036)
* Thu May 10 2018 Ryan O'Hara <rohara@redhat.com> - 1.8.8-2
- Build with USE_GETADDRINFO option
* Mon Jul 02 2018 Ryan O'Hara <rohara@redhat.com> - 1.8.12-1
- Update to 1.8.12
- Resolve CVE-2018-10184 (#1569643)
- Resolve CVE-2018-11469 (#1584787)
* Thu Apr 19 2018 Ryan O'Hara <rohara@redhat.com> - 1.8.8-1
- Update to 1.8.8 (#1560121)

View File

@ -1,6 +0,0 @@
--- !Policy
product_versions:
- rhel-9
decision_context: osci_compose_gate
rules:
- !PassingTestCaseRule {test_case_name: osci.brew-build.tier0.functional}

View File

@ -1 +0,0 @@
u haproxy - "haproxy" /var/lib/haproxy

View File

@ -1,3 +0,0 @@
---
inspections:
badfuncs: off

View File

@ -1 +0,0 @@
SHA512 (haproxy-2.4.22.tar.gz) = c22ad38046e3c70beb3bf57a62e4e74db329559059e2f36d2f801768c26b1f1222631702e83e9839fab4396c1b78089a807750ff743b4192da06c751cf9f0779

View File

@ -1,16 +0,0 @@
global
daemon
maxconn 1024
user haproxy
group haproxy
defaults
mode http
timeout connect 2s
timeout client 10s
timeout server 10s
listen test
bind *:81
server $VHOST1_NAME $VHOST1_ADDR:$VHOST1_PORT check
server $VHOST2_NAME $VHOST2_ADDR:$VHOST2_PORT check

View File

@ -1,142 +0,0 @@
#!/bin/sh
export VHOST1_NAME="vhost1"
export VHOST1_ADDR="192.168.100.101"
export VHOST1_PORT="80"
export VHOST2_NAME="vhost2"
export VHOST2_ADDR="192.168.100.102"
export VHOST2_PORT="80"
mkdir -p /var/www/html/${VHOST1_NAME}
mkdir -p /var/www/html/${VHOST2_NAME}
echo ${VHOST1_NAME} > /var/www/html/${VHOST1_NAME}/index.html
echo ${VHOST2_NAME} > /var/www/html/${VHOST2_NAME}/index.html
restorecon -R /var/www/html
cat >/etc/httpd/conf.d/vhost.conf <<EOF
<VirtualHost ${VHOST1_ADDR}:${VHOST1_PORT}>
DocumentRoot /var/www/html/${VHOST1_NAME}
</VirtualHost>
<VirtualHost ${VHOST2_ADDR}:${VHOST2_PORT}>
DocumentRoot /var/www/html/${VHOST2_NAME}
</VirtualHost>
EOF
echo -ne "[debug]: adding ${VHOST1_ADDR} ... "
ip addr add ${VHOST1_ADDR} dev lo
if [ $? -ne 0 ] ; then
echo "FAIL"
exit 1
else
echo "OK"
fi
echo -ne "[debug]: adding ${VHOST1_ADDR} ... "
ip addr add ${VHOST2_ADDR} dev lo
if [ $? -ne 0 ] ; then
echo "FAIL"
exit 1
else
echo "OK"
fi
echo -ne "[debug]: starting httpd service ... "
systemctl start httpd
if [ $? -ne 0 ] ; then
echo "FAIL"
exit 1
else
echo "OK"
fi
echo -ne "[debug]: checking httpd active ... "
systemctl -q is-active httpd
if [ $? -ne 0 ] ; then
echo "FAIL"
exit 1
else
echo "OK"
fi
VHOST1_VARS='${VHOST1_NAME}:${VHOST1_ADDR}:${VHOST1_PORT}'
VHOST2_VARS='${VHOST2_NAME}:${VHOST2_ADDR}:${VHOST2_PORT}'
echo -ne "[debug]: setting up config file .... "
envsubst "${VHOST1_VARS},${VHOST2_VARS}" < ./haproxy.cfg.in > /etc/haproxy/haproxy.cfg
if [ $? -ne 0 ] ; then
echo "FAIL"
exit 1
else
echo "OK"
fi
echo -ne "[debug]: configuring selinux policy ... "
setsebool haproxy_connect_any 1
if [ $? -ne 0 ] ; then
echo "FAIL"
exit 1
else
echo "OK"
fi
echo -ne "[debug]: starting haproxy service ... "
systemctl start haproxy
if [ $? -ne 0 ] ; then
echo "FAIL"
exit 1
else
echo "OK"
fi
echo -ne "[debug]: checking haproxy active ... "
systemctl -q is-active haproxy
if [ $? -ne 0 ] ; then
echo "FAIL"
exit 1
else
echo "OK"
fi
echo -ne "[debug]: fetching URL via haproxy ... "
if [[ $( curl -s http://127.0.0.1:81 ) != ${VHOST1_NAME} ]] ; then
echo "FAIL"
exit 1
else
echo "OK"
fi
echo -ne "[debug]: fetching URL via haproxy ... "
if [[ $( curl -s http://127.0.0.1:81 ) != ${VHOST2_NAME} ]] ; then
echo "FAIL"
exit 1
else
echo "OK"
fi
echo -ne "[debug]: stopping haproxy service ... "
systemctl stop haproxy
if [ $? -ne 0 ] ; then
echo "FAIL"
exit 1
else
echo "OK"
fi
echo -ne "[debug]: checking haproxy inactive ... "
systemctl -q is-active haproxy
if [ $? -ne 3 ] ; then
echo "FAIL"
exit 1
else
echo "OK"
fi
systemctl stop httpd
ip addr del ${VHOST1_ADDR}/32 dev lo
ip addr del ${VHOST2_ADDR}/32 dev lo
exit 0

View File

@ -1,13 +0,0 @@
- hosts: localhost
roles:
- role: standard-test-basic
tags:
- classic
tests:
- simple:
dir: .
run: ./run_tests.sh
required_packages:
- curl
- gettext
- httpd