From 9c57025fb4627f19d0a8feaf86bdfb4ece6236e7 Mon Sep 17 00:00:00 2001 From: Maximilian Moehl Date: Tue, 12 Jul 2022 14:58:42 +0200 Subject: [PATCH] feat: expose flag 'h1-accept-payload-with-any-method' --- ci/release_notes.md | 1 + .../disable-http10-body-in-get-request.patch | 27 ------------------- jobs/haproxy/spec | 3 +++ jobs/haproxy/templates/haproxy.config.erb | 3 +++ .../global_and_default_options_spec.rb | 12 +++++++++ 5 files changed, 19 insertions(+), 27 deletions(-) delete mode 100644 haproxy-patches/disable-http10-body-in-get-request.patch diff --git a/ci/release_notes.md b/ci/release_notes.md index b78934d9..9bc48597 100644 --- a/ci/release_notes.md +++ b/ci/release_notes.md @@ -3,6 +3,7 @@ # New Features - socat is directly executable due to a symlink +- expose `h1-accept-payload-with-any-method` as `ha_proxy.always_allow_body_http10` # Upgrades - HAProxy 2.5.4 -> 2.5.7 diff --git a/haproxy-patches/disable-http10-body-in-get-request.patch b/haproxy-patches/disable-http10-body-in-get-request.patch deleted file mode 100644 index 99fde696..00000000 --- a/haproxy-patches/disable-http10-body-in-get-request.patch +++ /dev/null @@ -1,27 +0,0 @@ ---- src/mux_h1.c 2022-02-25 17:10:16.000000000 +0100 -+++ src/mux_h1.updated.c 2022-05-05 13:30:41.000000000 +0200 -@@ -1426,24 +1426,6 @@ - goto end; - } - -- -- /* Reject HTTP/1.0 GET/HEAD/DELETE requests with a payload. There is a -- * payload if the c-l is not null or the the payload is chunk-encoded. -- * A parsing error is reported but a A 413-Payload-Too-Large is returned -- * instead of a 400-Bad-Request. -- */ -- if (!(h1m->flags & (H1_MF_RESP|H1_MF_VER_11)) && -- (((h1m->flags & H1_MF_CLEN) && h1m->body_len) || (h1m->flags & H1_MF_CHNK)) && -- (h1sl.rq.meth == HTTP_METH_GET || h1sl.rq.meth == HTTP_METH_HEAD || h1sl.rq.meth == HTTP_METH_DELETE)) { -- h1s->flags |= H1S_F_PARSING_ERROR; -- htx->flags |= HTX_FL_PARSING_ERROR; -- h1s->h1c->errcode = 413; -- TRACE_ERROR("HTTP/1.0 GET/HEAD/DELETE request with a payload forbidden", H1_EV_RX_DATA|H1_EV_RX_HDRS|H1_EV_H1S_ERR, h1s->h1c->conn, h1s); -- h1_capture_bad_message(h1s->h1c, h1s, h1m, buf); -- ret = 0; -- goto end; -- } -- - /* Reject any message with an unknown transfer-encoding. In fact if any - * encoding other than "chunked". A 422-Unprocessable-Content is - * returned for an invalid request, a 502-Bad-Gateway for an invalid diff --git a/jobs/haproxy/spec b/jobs/haproxy/spec index a39ac988..ed281684 100644 --- a/jobs/haproxy/spec +++ b/jobs/haproxy/spec @@ -677,3 +677,6 @@ properties: ha_proxy.enable_http2: description: Enables ingress (frontend) and egress (backend) HTTP/2 ALPN negotiation. Egress (backend) HTTP protocol version may be overriden by `ha_proxy.backend_ssl`, `ha_proxy.disable_backend_http2_websockets` and `ha_proxy.backend_match_http_protocol`. default: false + ha_proxy.always_allow_body_http10: + description: Always allow a body to be sent when using HTTP/1.0. By default HAProxy denies GET/HEAD/DELETE requests with a body when using HTTP/1.0 due to potential request smuggling attacks. See https://github.com/haproxy/haproxy/commit/e136bd12a32970bc90d862d5fe09ea1952b62974 + default: false diff --git a/jobs/haproxy/templates/haproxy.config.erb b/jobs/haproxy/templates/haproxy.config.erb index b878f2d5..ccbde4a6 100644 --- a/jobs/haproxy/templates/haproxy.config.erb +++ b/jobs/haproxy/templates/haproxy.config.erb @@ -276,6 +276,9 @@ global <%- if backend_match_http_protocol && backends.length == 2 -%> set-var proc.h2_alpn_tag str(h2) <%- end -%> + <%- if p("ha_proxy.always_allow_body_http10") %> + h1-accept-payload-with-any-method + <%- end %> defaults log global diff --git a/spec/haproxy/templates/haproxy_config/global_and_default_options_spec.rb b/spec/haproxy/templates/haproxy_config/global_and_default_options_spec.rb index 6bec4a3a..f0e1f5ba 100644 --- a/spec/haproxy/templates/haproxy_config/global_and_default_options_spec.rb +++ b/spec/haproxy/templates/haproxy_config/global_and_default_options_spec.rb @@ -491,4 +491,16 @@ expect(defaults).to include('option allbackups') end end + + context 'when ha_proxy.always_allow_body_http10 is true' do + let(:properties) do + { + 'always_allow_body_http10' => true + } + end + + it 'sets the global option' do + expect(global).to include('h1-accept-payload-with-any-method') + end + end end