401f5d1
# ./pullrev.sh 1870095
401f5d1
http://svn.apache.org/viewvc?view=revision&revision=1870095
401f5d1
401f5d1
https://bugzilla.redhat.com/show_bug.cgi?id=1775146
401f5d1
401f5d1
--- httpd-2.4.41/modules/ssl/ssl_engine_kernel.c
401f5d1
+++ httpd-2.4.41/modules/ssl/ssl_engine_kernel.c
401f5d1
@@ -114,6 +114,45 @@
401f5d1
     return result;
401f5d1
 }
401f5d1
 
401f5d1
+/* If a renegotiation is required for the location, and the request
401f5d1
+ * includes a message body (and the client has not requested a "100
401f5d1
+ * Continue" response), then the client will be streaming the request
401f5d1
+ * body over the wire already.  In that case, it is not possible to
401f5d1
+ * stop and perform a new SSL handshake immediately; once the SSL
401f5d1
+ * library moves to the "accept" state, it will reject the SSL packets
401f5d1
+ * which the client is sending for the request body.
401f5d1
+ *
401f5d1
+ * To allow authentication to complete in the hook, the solution used
401f5d1
+ * here is to fill a (bounded) buffer with the request body, and then
401f5d1
+ * to reinject that request body later.
401f5d1
+ *
401f5d1
+ * This function is called to fill the renegotiation buffer for the
401f5d1
+ * location as required, or fail.  Returns zero on success or HTTP_
401f5d1
+ * error code on failure.
401f5d1
+ */
401f5d1
+static int fill_reneg_buffer(request_rec *r, SSLDirConfigRec *dc)
401f5d1
+{
401f5d1
+    int rv;
401f5d1
+    apr_size_t rsize;
401f5d1
+
401f5d1
+    /* ### this is HTTP/1.1 specific, special case for protocol? */
401f5d1
+    if (r->expecting_100 || !ap_request_has_body(r)) {
401f5d1
+        return 0;
401f5d1
+    }
401f5d1
+
401f5d1
+    rsize = dc->nRenegBufferSize == UNSET ? DEFAULT_RENEG_BUFFER_SIZE : dc->nRenegBufferSize;
401f5d1
+    if (rsize > 0) {
401f5d1
+        /* Fill the I/O buffer with the request body if possible. */
401f5d1
+        rv = ssl_io_buffer_fill(r, rsize);
401f5d1
+    }
401f5d1
+    else {
401f5d1
+        /* If the reneg buffer size is set to zero, just fail. */
401f5d1
+        rv = HTTP_REQUEST_ENTITY_TOO_LARGE;
401f5d1
+    }
401f5d1
+
401f5d1
+    return rv;
401f5d1
+}
401f5d1
+
401f5d1
 #ifdef HAVE_TLSEXT
401f5d1
 static int ap_array_same_str_set(apr_array_header_t *s1, apr_array_header_t *s2)
401f5d1
 {
401f5d1
@@ -814,41 +853,14 @@
401f5d1
         }
401f5d1
     }
401f5d1
 
401f5d1
-    /* If a renegotiation is now required for this location, and the
401f5d1
-     * request includes a message body (and the client has not
401f5d1
-     * requested a "100 Continue" response), then the client will be
401f5d1
-     * streaming the request body over the wire already.  In that
401f5d1
-     * case, it is not possible to stop and perform a new SSL
401f5d1
-     * handshake immediately; once the SSL library moves to the
401f5d1
-     * "accept" state, it will reject the SSL packets which the client
401f5d1
-     * is sending for the request body.
401f5d1
-     *
401f5d1
-     * To allow authentication to complete in this auth hook, the
401f5d1
-     * solution used here is to fill a (bounded) buffer with the
401f5d1
-     * request body, and then to reinject that request body later.
401f5d1
-     */
401f5d1
-    if (renegotiate && !renegotiate_quick
401f5d1
-        && !r->expecting_100
401f5d1
-        && ap_request_has_body(r)) {
401f5d1
-        int rv;
401f5d1
-        apr_size_t rsize;
401f5d1
-
401f5d1
-        rsize = dc->nRenegBufferSize == UNSET ? DEFAULT_RENEG_BUFFER_SIZE :
401f5d1
-                                                dc->nRenegBufferSize;
401f5d1
-        if (rsize > 0) {
401f5d1
-            /* Fill the I/O buffer with the request body if possible. */
401f5d1
-            rv = ssl_io_buffer_fill(r, rsize);
401f5d1
-        }
401f5d1
-        else {
401f5d1
-            /* If the reneg buffer size is set to zero, just fail. */
401f5d1
-            rv = HTTP_REQUEST_ENTITY_TOO_LARGE;
401f5d1
-        }
401f5d1
-
401f5d1
-        if (rv) {
401f5d1
+    /* Fill reneg buffer if required. */
401f5d1
+    if (renegotiate && !renegotiate_quick) {
401f5d1
+        rc = fill_reneg_buffer(r, dc);
401f5d1
+        if (rc) {
401f5d1
             ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02257)
401f5d1
                           "could not buffer message body to allow "
401f5d1
                           "SSL renegotiation to proceed");
401f5d1
-            return rv;
401f5d1
+            return rc;
401f5d1
         }
401f5d1
     }
401f5d1
 
401f5d1
@@ -1132,7 +1144,18 @@
401f5d1
             }
401f5d1
         }
401f5d1
 
401f5d1
+        /* Fill reneg buffer if required. */
401f5d1
         if (change_vmode) {
401f5d1
+            rc = fill_reneg_buffer(r, dc);
401f5d1
+            if (rc) {
401f5d1
+                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO()
401f5d1
+                              "could not buffer message body to allow "
401f5d1
+                              "TLS Post-Handshake Authentication to proceed");
401f5d1
+                return rc;
401f5d1
+            }
401f5d1
+        }
401f5d1
+
401f5d1
+        if (change_vmode) {
401f5d1
             char peekbuf[1];
401f5d1
 
401f5d1
             if (r->connection->master) {