diff -rNU 30 ../httpd-2.2.12-o/modules/ssl/ssl_engine_kernel.c ./modules/ssl/ssl_engine_kernel.c
--- ../httpd-2.2.12-o/modules/ssl/ssl_engine_kernel.c	2013-04-26 18:24:51.000000000 +0200
+++ ./modules/ssl/ssl_engine_kernel.c	2013-04-29 13:07:40.000000000 +0200
@@ -8,60 +8,85 @@
  *     http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
 /*                      _             _
  *  _ __ ___   ___   __| |    ___ ___| |  mod_ssl
  * | '_ ` _ \ / _ \ / _` |   / __/ __| |  Apache Interface to OpenSSL
  * | | | | | | (_) | (_| |   \__ \__ \ |
  * |_| |_| |_|\___/ \__,_|___|___/___/_|
  *                      |_____|
  *  ssl_engine_kernel.c
  *  The SSL engine kernel
  */
                              /* ``It took me fifteen years to discover
                                   I had no talent for programming, but
                                   I couldn't give it up because by that
                                   time I was too famous.''
                                             -- Unknown                */
 #include "ssl_private.h"
 
 static void ssl_configure_env(request_rec *r, SSLConnRec *sslconn);
 #ifndef OPENSSL_NO_TLSEXT
 static int ssl_find_vhost(void *servername, conn_rec *c, server_rec *s);
 #endif
 
+
+/* Perform a speculative (and non-blocking) read from the connection
+ * filters for the given request, to determine whether there is any
+ * pending data to read.  Return non-zero if there is, else zero. */
+static int has_buffered_data(request_rec *r)
+{
+    apr_bucket_brigade *bb;
+    apr_off_t len;
+    apr_status_t rv;
+    int result;
+
+    bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
+
+    rv = ap_get_brigade(r->connection->input_filters, bb, AP_MODE_SPECULATIVE,
+                        APR_NONBLOCK_READ, 1);
+    result = rv == APR_SUCCESS
+        && apr_brigade_length(bb, 1, &len) == APR_SUCCESS
+        && len > 0;
+
+    apr_brigade_destroy(bb);
+
+    return result;
+}
+
+
 /*
  *  Post Read Request Handler
  */
 int ssl_hook_ReadReq(request_rec *r)
 {
     SSLConnRec *sslconn = myConnConfig(r->connection);
 #ifndef OPENSSL_NO_TLSEXT
     const char *servername;
 #endif
     SSL *ssl;
 
     if (!sslconn) {
         return DECLINED;
     }
 
     if (sslconn->non_ssl_request) {
         const char *errmsg;
         char *thisurl;
         char *thisport = "";
         int port = ap_get_server_port(r);
 
         if (!ap_is_default_port(port, r)) {
             thisport = apr_psprintf(r->pool, ":%u", port);
         }
 
         thisurl = ap_escape_html(r->pool,
                                  apr_psprintf(r->pool, "https://%s%s/",
                                               ap_get_server_name(r),
                                               thisport));
 
@@ -195,61 +220,61 @@
                     sslconn->shutdown_type = SSL_SHUTDOWN_TYPE_ACCURATE;
                 }
                 return; /* should only ever be one ssl-*-shutdown */
             }
             break;
         }
     }
 }
 
 /*
  *  Access Handler
  */
 int ssl_hook_Access(request_rec *r)
 {
     SSLDirConfigRec *dc         = myDirConfig(r);
     SSLSrvConfigRec *sc         = mySrvConfig(r->server);
     SSLConnRec *sslconn         = myConnConfig(r->connection);
     SSL *ssl                    = sslconn ? sslconn->ssl : NULL;
     server_rec *handshakeserver = sslconn ? sslconn->server : NULL;
     SSL_CTX *ctx = NULL;
     apr_array_header_t *requires;
     ssl_require_t *ssl_requires;
     char *cp;
     int ok, i;
     BOOL renegotiate = FALSE, renegotiate_quick = FALSE;
     X509 *cert;
     X509 *peercert;
     X509_STORE *cert_store = NULL;
     X509_STORE_CTX cert_store_ctx;
     STACK_OF(SSL_CIPHER) *cipher_list_old = NULL, *cipher_list = NULL;
-    SSL_CIPHER *cipher = NULL;
+    const SSL_CIPHER *cipher = NULL;
     int depth, verify_old, verify, n;
 
     if (ssl) {
         ctx = SSL_get_SSL_CTX(ssl);
     }
 
     /*
      * Support for SSLRequireSSL directive
      */
     if (dc->bSSLRequired && !ssl) {
         if (sc->enabled == SSL_ENABLED_OPTIONAL) {
             /* This vhost was configured for optional SSL, just tell the
              * client that we need to upgrade.
              */
             apr_table_setn(r->err_headers_out, "Upgrade", "TLS/1.0, HTTP/1.1");
             apr_table_setn(r->err_headers_out, "Connection", "Upgrade");
 
             return HTTP_UPGRADE_REQUIRED;
         }
 
         ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
                       "access to %s failed, reason: %s",
                       r->filename, "SSL connection required");
 
         /* remember forbidden access for strict require option */
         apr_table_setn(r->notes, "ssl-access-forbidden", "1");
 
         return HTTP_FORBIDDEN;
     }
 
@@ -693,60 +718,78 @@
             }
 
             X509_STORE_CTX_init(&cert_store_ctx, cert_store, cert, cert_stack);
             depth = SSL_get_verify_depth(ssl);
 
             if (depth >= 0) {
                 X509_STORE_CTX_set_depth(&cert_store_ctx, depth);
             }
 
             X509_STORE_CTX_set_ex_data(&cert_store_ctx,
                                        SSL_get_ex_data_X509_STORE_CTX_idx(),
                                        (char *)ssl);
 
             if (!modssl_X509_verify_cert(&cert_store_ctx)) {
                 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
                               "Re-negotiation verification step failed");
                 ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, r->server);
             }
 
             SSL_set_verify_result(ssl, cert_store_ctx.error);
             X509_STORE_CTX_cleanup(&cert_store_ctx);
 
             if (cert_stack != SSL_get_peer_cert_chain(ssl)) {
                 /* we created this ourselves, so free it */
                 sk_X509_pop_free(cert_stack, X509_free);
             }
         }
         else {
             request_rec *id = r->main ? r->main : r;
 
+            /* Additional mitigation for CVE-2009-3555: At this point,
+             * before renegotiating, an (entire) request has been read
+             * from the connection.  An attacker may have sent further
+             * data to "prefix" any subsequent request by the victim's
+             * client after the renegotiation; this data may already
+             * have been read and buffered.  Forcing a connection
+             * closure after the response ensures such data will be
+             * discarded.  Legimately pipelined HTTP requests will be
+             * retried anyway with this approach. */
+            if (has_buffered_data(r)) {
+                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+                              "insecure SSL re-negotiation required, but "
+                              "a pipelined request is present; keepalive "
+                              "disabled");
+                r->connection->keepalive = AP_CONN_CLOSE;
+            }
+
+
             /* do a full renegotiation */
             ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
                           "Performing full renegotiation: "
                           "complete handshake protocol");
 
             SSL_set_session_id_context(ssl,
                                        (unsigned char *)&id,
                                        sizeof(id));
 
             /* Toggle the renegotiation state to allow the new
              * handshake to proceed. */
             sslconn->reneg_state = RENEG_ALLOW;
             
             SSL_renegotiate(ssl);
             SSL_do_handshake(ssl);
 
             if (SSL_get_state(ssl) != SSL_ST_OK) {
                 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
                               "Re-negotiation request failed");
 
                 r->connection->aborted = 1;
                 return HTTP_FORBIDDEN;
             }
 
             ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
                           "Awaiting re-negotiation handshake");
 
             /* XXX: Should replace SSL_set_state with SSL_renegotiate(ssl);
              * However, this causes failures in perl-framework currently,
              * perhaps pre-test if we have already negotiated?
@@ -1927,61 +1970,61 @@
 void ssl_callback_Info(MODSSL_INFO_CB_ARG_TYPE ssl, int where, int rc)
 {
     conn_rec *c;
     server_rec *s;
     SSLConnRec *scr;
 
     /* Retrieve the conn_rec and the associated SSLConnRec. */
     if ((c = (conn_rec *)SSL_get_app_data((SSL *)ssl)) == NULL) {
         return;
     }
 
     if ((scr = myConnConfig(c)) == NULL) {
         return;
     }
 
     /* If the reneg state is to reject renegotiations, check the SSL
      * state machine and move to ABORT if a Client Hello is being
      * read. */
     if ((where & SSL_CB_ACCEPT_LOOP) && scr->reneg_state == RENEG_REJECT) {
         int state = SSL_get_state(ssl);
         
         if (state == SSL3_ST_SR_CLNT_HELLO_A 
             || state == SSL23_ST_SR_CLNT_HELLO_A) {
             scr->reneg_state = RENEG_ABORT;
             ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c,
                           "rejecting client initiated renegotiation");
         }
     }
     /* If the first handshake is complete, change state to reject any
      * subsequent client-initated renegotiation. */
-    else if (where & SSL_CB_HANDSHAKE_DONE && scr->reneg_state == RENEG_INIT) {
+    else if ((where & SSL_CB_HANDSHAKE_DONE) && scr->reneg_state == RENEG_INIT) {
         scr->reneg_state = RENEG_REJECT;
     }
 
     s = mySrvFromConn(c);
     if (s && s->loglevel >= APLOG_DEBUG) {
         log_tracing_state(ssl, c, s, where, rc);
     }
 }
 
 #ifndef OPENSSL_NO_TLSEXT
 /*
  * This callback function is executed when OpenSSL encounters an extended
  * client hello with a server name indication extension ("SNI", cf. RFC 4366).
  */
 int ssl_callback_ServerNameIndication(SSL *ssl, int *al, modssl_ctx_t *mctx)
 {
     const char *servername =
                 SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
 
     if (servername) {
         conn_rec *c = (conn_rec *)SSL_get_app_data(ssl);
         if (c) {
             if (ap_vhost_iterate_given_conn(c, ssl_find_vhost,
                                             (void *)servername)) {
                 ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c,
                               "SSL virtual host for servername %s found",
                               servername);
                 return SSL_TLSEXT_ERR_OK;
             }
             else {
