From b3ceae982ac37ef9c23ab794ab0b300da6d9d5ff Mon Sep 17 00:00:00 2001 From: Joe Orton Date: Nov 21 2019 16:56:37 +0000 Subject: mod_ssl: fix request body buffering w/TLSv1.3 PHA (#1775146) --- diff --git a/httpd-2.4.41-r1870095+.patch b/httpd-2.4.41-r1870095+.patch new file mode 100644 index 0000000..f29e6f2 --- /dev/null +++ b/httpd-2.4.41-r1870095+.patch @@ -0,0 +1,117 @@ +# ./pullrev.sh 1870095 1870097 +http://svn.apache.org/viewvc?view=revision&revision=1870095 +http://svn.apache.org/viewvc?view=revision&revision=1870097 + +--- 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,6 +1144,17 @@ + } + } + ++ /* 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(10228) ++ "could not buffer message body to allow " ++ "TLS Post-Handshake Authentication to proceed"); ++ return rc; ++ } ++ } ++ + if (change_vmode) { + char peekbuf[1]; + diff --git a/httpd-2.4.41-r1870095.patch b/httpd-2.4.41-r1870095.patch deleted file mode 100644 index 5f5b2e2..0000000 --- a/httpd-2.4.41-r1870095.patch +++ /dev/null @@ -1,119 +0,0 @@ -# ./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 7ad5c6c..51ea1da 100644 --- a/httpd.spec +++ b/httpd.spec @@ -87,7 +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 +Patch62: httpd-2.4.41-r1870095+.patch # Security fixes