]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
Don't reuse a SSL backend connection whose SNI differs. PR 55782.
authorYann Ylavic <ylavic@apache.org>
Thu, 27 Feb 2014 14:52:12 +0000 (14:52 +0000)
committerYann Ylavic <ylavic@apache.org>
Thu, 27 Feb 2014 14:52:12 +0000 (14:52 +0000)
This may happen when ProxyPreserveHost is on and the proxy-worker
handles connections to different Hosts.

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1572606 13f79535-47bb-0310-9956-ffa450edef68

modules/proxy/mod_proxy.h
modules/proxy/mod_proxy_http.c
modules/proxy/proxy_util.c

index b99ee17b90d8a5cf6ab4bd34945e9e6de8d09e39..e2978890147a5835807e6e026c96c38c7d8dcf0a 100644 (file)
@@ -254,6 +254,7 @@ typedef struct {
     unsigned int need_flush:1; /* Flag to decide whether we need to flush the
                                 * filter chain or not */
     unsigned int inreslist:1;  /* connection in apr_reslist? */
+    const char  *ssl_hostname; /* Hostname (SNI) in use by SSL connection */
 } proxy_conn_rec;
 
 typedef struct {
index 9f7a6b40266d70a6c651499d2741b0dd9988dd5f..6ebc2ccb0b4ee59a348a22d766407bb9391491b5 100644 (file)
@@ -1975,25 +1975,10 @@ static int proxy_http_handler(request_rec *r, proxy_worker *worker,
              * requested, such that mod_ssl can check if it is requested to do
              * so.
              */
-            if (is_ssl) {
-                proxy_dir_conf *dconf;
-                const char *ssl_hostname;
-
-                /*
-                 * In the case of ProxyPreserveHost on use the hostname of
-                 * the request if present otherwise use the one from the
-                 * backend request URI.
-                 */
-                dconf = ap_get_module_config(r->per_dir_config, &proxy_module);
-                if ((dconf->preserve_host != 0) && (r->hostname != NULL)) {
-                    ssl_hostname = r->hostname;
-                }
-                else {
-                    ssl_hostname = uri->hostname;
-                }
-
-                apr_table_set(backend->connection->notes, "proxy-request-hostname",
-                              ssl_hostname);
+            if (backend->ssl_hostname) {
+                apr_table_setn(backend->connection->notes,
+                               "proxy-request-hostname",
+                               backend->ssl_hostname);
             }
 
             /* Step Three-and-a-Half: See if the socket is still connected (if
index 0cd27c8ea09a34b79805e283c30a3f758146983e..27cd0f456fe22e9df105b77c0a34fce729b6ea56 100644 (file)
@@ -1405,6 +1405,7 @@ static void socket_cleanup(proxy_conn_rec *conn)
 {
     conn->sock = NULL;
     conn->connection = NULL;
+    conn->ssl_hostname = NULL;
     apr_pool_clear(conn->scpool);
 }
 
@@ -2346,6 +2347,35 @@ ap_proxy_determine_connection(apr_pool_t *p, request_rec *r,
         return ap_proxyerror(r, HTTP_FORBIDDEN,
                              "Connect to remote machine blocked");
     }
+    /*
+     * When SSL is configured, determine the hostname (SNI) for the request
+     * and save it in conn->ssl_hostname. Close any reused connection whose
+     * SNI differs.
+     */
+    if (conn->is_ssl) {
+        proxy_dir_conf *dconf;
+        const char *ssl_hostname;
+        /*
+         * In the case of ProxyPreserveHost on use the hostname of
+         * the request if present otherwise use the one from the
+         * backend request URI.
+         */
+        dconf = ap_get_module_config(r->per_dir_config, &proxy_module);
+        if (dconf->preserve_host) {
+            ssl_hostname = r->hostname;
+        }
+        else {
+            ssl_hostname = conn->hostname;
+        }
+        if (conn->ssl_hostname != NULL &&
+                (!ssl_hostname || strcasecmp(conn->ssl_hostname,
+                                             ssl_hostname) != 0)) {
+            socket_cleanup(conn);
+        }
+        if (conn->ssl_hostname == NULL) {
+            conn->ssl_hostname = apr_pstrdup(conn->scpool, ssl_hostname);
+        }
+    }
     ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00947)
                  "connected %s to %s:%d", *url, conn->hostname, conn->port);
     return OK;