From 401f5d1ca77b71fa5dd446d556ad9c795f3261b0 Mon Sep 17 00:00:00 2001 From: Joe Orton Date: Thu, 21 Nov 2019 16:54:17 +0000 Subject: [PATCH] mod_ssl: fix request body buffering w/TLSv1.3 PHA (#1775146) Resolves: rhbz#1775146 --- httpd-2.4.41-r1870095.patch | 119 ++++++++++++++++++++++++++++++++++++ httpd.spec | 7 ++- 2 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 httpd-2.4.41-r1870095.patch diff --git a/httpd-2.4.41-r1870095.patch b/httpd-2.4.41-r1870095.patch new file mode 100644 index 0000000..5f5b2e2 --- /dev/null +++ b/httpd-2.4.41-r1870095.patch @@ -0,0 +1,119 @@ +# ./pullrev.sh 1870095 +http://svn.apache.org/viewvc?view=revision&revision=1870095 + +https://bugzilla.redhat.com/show_bug.cgi?id=1775146 + +--- httpd-2.4.41/modules/ssl/ssl_engine_kernel.c ++++ httpd-2.4.41/modules/ssl/ssl_engine_kernel.c +@@ -114,6 +114,45 @@ + return result; + } + ++/* If a renegotiation is required for the location, and the request ++ * includes a message body (and the client has not requested a "100 ++ * Continue" response), then the client will be streaming the request ++ * body over the wire already. In that case, it is not possible to ++ * stop and perform a new SSL handshake immediately; once the SSL ++ * library moves to the "accept" state, it will reject the SSL packets ++ * which the client is sending for the request body. ++ * ++ * To allow authentication to complete in the hook, the solution used ++ * here is to fill a (bounded) buffer with the request body, and then ++ * to reinject that request body later. ++ * ++ * This function is called to fill the renegotiation buffer for the ++ * location as required, or fail. Returns zero on success or HTTP_ ++ * error code on failure. ++ */ ++static int fill_reneg_buffer(request_rec *r, SSLDirConfigRec *dc) ++{ ++ int rv; ++ apr_size_t rsize; ++ ++ /* ### this is HTTP/1.1 specific, special case for protocol? */ ++ if (r->expecting_100 || !ap_request_has_body(r)) { ++ return 0; ++ } ++ ++ rsize = dc->nRenegBufferSize == UNSET ? DEFAULT_RENEG_BUFFER_SIZE : dc->nRenegBufferSize; ++ if (rsize > 0) { ++ /* Fill the I/O buffer with the request body if possible. */ ++ rv = ssl_io_buffer_fill(r, rsize); ++ } ++ else { ++ /* If the reneg buffer size is set to zero, just fail. */ ++ rv = HTTP_REQUEST_ENTITY_TOO_LARGE; ++ } ++ ++ return rv; ++} ++ + #ifdef HAVE_TLSEXT + static int ap_array_same_str_set(apr_array_header_t *s1, apr_array_header_t *s2) + { +@@ -814,41 +853,14 @@ + } + } + +- /* If a renegotiation is now required for this location, and the +- * request includes a message body (and the client has not +- * requested a "100 Continue" response), then the client will be +- * streaming the request body over the wire already. In that +- * case, it is not possible to stop and perform a new SSL +- * handshake immediately; once the SSL library moves to the +- * "accept" state, it will reject the SSL packets which the client +- * is sending for the request body. +- * +- * To allow authentication to complete in this auth hook, the +- * solution used here is to fill a (bounded) buffer with the +- * request body, and then to reinject that request body later. +- */ +- if (renegotiate && !renegotiate_quick +- && !r->expecting_100 +- && ap_request_has_body(r)) { +- int rv; +- apr_size_t rsize; +- +- rsize = dc->nRenegBufferSize == UNSET ? DEFAULT_RENEG_BUFFER_SIZE : +- dc->nRenegBufferSize; +- if (rsize > 0) { +- /* Fill the I/O buffer with the request body if possible. */ +- rv = ssl_io_buffer_fill(r, rsize); +- } +- else { +- /* If the reneg buffer size is set to zero, just fail. */ +- rv = HTTP_REQUEST_ENTITY_TOO_LARGE; +- } +- +- if (rv) { ++ /* Fill reneg buffer if required. */ ++ if (renegotiate && !renegotiate_quick) { ++ rc = fill_reneg_buffer(r, dc); ++ if (rc) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02257) + "could not buffer message body to allow " + "SSL renegotiation to proceed"); +- return rv; ++ return rc; + } + } + +@@ -1132,7 +1144,18 @@ + } + } + ++ /* Fill reneg buffer if required. */ + if (change_vmode) { ++ rc = fill_reneg_buffer(r, dc); ++ if (rc) { ++ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO() ++ "could not buffer message body to allow " ++ "TLS Post-Handshake Authentication to proceed"); ++ return rc; ++ } ++ } ++ ++ if (change_vmode) { + char peekbuf[1]; + + if (r->connection->master) { diff --git a/httpd.spec b/httpd.spec index 46d518f..7ad5c6c 100644 --- a/httpd.spec +++ b/httpd.spec @@ -13,7 +13,7 @@ Summary: Apache HTTP Server Name: httpd Version: 2.4.41 -Release: 8%{?dist} +Release: 9%{?dist} URL: https://httpd.apache.org/ Source0: https://www.apache.org/dist/httpd/httpd-%{version}.tar.bz2 Source1: https://www.apache.org/dist/httpd/httpd-%{version}.tar.bz2.asc @@ -87,6 +87,7 @@ Patch42: httpd-2.4.41-r1828172+.patch Patch58: httpd-2.4.34-r1738878.patch Patch60: httpd-2.4.34-enable-sslv3.patch Patch61: httpd-2.4.41-r1865749.patch +Patch62: httpd-2.4.41-r1870095.patch # Security fixes @@ -227,6 +228,7 @@ interface for storing and accessing per-user session data. %patch58 -p1 -b .r1738878 %patch60 -p1 -b .enable-sslv3 %patch61 -p1 -b .r1865749 +%patch62 -p1 -b .r1870095 # Patch in the vendor string sed -i '/^#define PLATFORM/s/Unix/%{vstring}/' os/unix/os.h @@ -747,6 +749,9 @@ exit $rv %{_rpmconfigdir}/macros.d/macros.httpd %changelog +* Thu Nov 21 2019 Joe Orton - 2.4.41-9 +- mod_ssl: fix request body buffering w/TLSv1.3 PHA (#1775146) + * Wed Nov 13 2019 Joe Orton - 2.4.41-8 - apachectl: in graceful/graceful-stop, only signal main process (#1758798)