From: Yann Ylavic Date: Fri, 18 Jul 2014 21:38:38 +0000 (+0000) Subject: Merge r1572630, r1572611, r1572967, r1573229 from trunk: X-Git-Tag: 2.2.28~18 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e20c8a2bba393c88d4b773c2ec9339940dbf4636;p=thirdparty%2Fapache%2Fhttpd.git Merge r1572630, r1572611, r1572967, r1573229 from trunk: Redo what was reverted in r1572627. Don't reuse a SSL backend connection whose SNI differs. PR 55782. This may happen when ProxyPreserveHost is on and the proxy-worker handles connections to different Hosts. Follows up r1572606. MMN minor bump required by proxy_conn_rec change. mod_proxy: follows up r1572630. Don't reuse a SSL backend connection with no SNI for a request requiring SNI. mod_proxy: Add comment and avoid ternary operator as condition (no functional change). Submitted by: ylavic Reviewed by: ylavic, rpluem, wrowe git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.2.x@1611813 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/include/ap_mmn.h b/include/ap_mmn.h index 3d2701e77be..bff6eff357a 100644 --- a/include/ap_mmn.h +++ b/include/ap_mmn.h @@ -152,6 +152,7 @@ * 20051115.32 (2.2.24) Add ap_get_exec_line * 20051115.33 (2.2.24) Add ap_pregsub_ex() * 20051115.34 (2.2.28) Add ap_copy_scoreboard_worker() + * 20051115.35 (2.2.27) Add SSL reusable SNI to mod_proxy.h's proxy_conn_rec */ #define MODULE_MAGIC_COOKIE 0x41503232UL /* "AP22" */ @@ -159,7 +160,7 @@ #ifndef MODULE_MAGIC_NUMBER_MAJOR #define MODULE_MAGIC_NUMBER_MAJOR 20051115 #endif -#define MODULE_MAGIC_NUMBER_MINOR 34 /* 0...n */ +#define MODULE_MAGIC_NUMBER_MINOR 35 /* 0...n */ /** * Determine if the server's current MODULE_MAGIC_NUMBER is at least a diff --git a/modules/proxy/mod_proxy.h b/modules/proxy/mod_proxy.h index 99048445f3f..2d4998d9432 100644 --- a/modules/proxy/mod_proxy.h +++ b/modules/proxy/mod_proxy.h @@ -248,6 +248,7 @@ typedef struct { int need_flush;/* Flag to decide whether we need to flush the * filter chain or not */ void *forward; /* opaque forward proxy data */ + const char *ssl_hostname;/* Hostname (SNI) in use by SSL connection */ } proxy_conn_rec; typedef struct { diff --git a/modules/proxy/mod_proxy_http.c b/modules/proxy/mod_proxy_http.c index ca3c5ee5fee..330f80bd765 100644 --- a/modules/proxy/mod_proxy_http.c +++ b/modules/proxy/mod_proxy_http.c @@ -2028,23 +2028,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) { - 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. - */ - if ((conf->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); } } diff --git a/modules/proxy/proxy_util.c b/modules/proxy/proxy_util.c index 85d31386e86..2a94aa6be91 100644 --- a/modules/proxy/proxy_util.c +++ b/modules/proxy/proxy_util.c @@ -1698,6 +1698,7 @@ static void socket_cleanup(proxy_conn_rec *conn) { conn->sock = NULL; conn->connection = NULL; + conn->ssl_hostname = NULL; apr_pool_clear(conn->scpool); } @@ -2197,6 +2198,38 @@ 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) { + 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. + */ + if (conf->preserve_host) { + ssl_hostname = r->hostname; + } + else { + ssl_hostname = conn->hostname; + } + /* + * Close if a SNI is in use but this request requires no or + * a different one, or no SNI is in use but one is required. + */ + if ((conn->ssl_hostname && (!ssl_hostname || + strcasecmp(conn->ssl_hostname, + ssl_hostname) != 0)) || + (!conn->ssl_hostname && ssl_hostname && conn->sock)) { + socket_cleanup(conn); + } + if (conn->ssl_hostname == NULL) { + conn->ssl_hostname = apr_pstrdup(conn->scpool, ssl_hostname); + } + } ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "proxy: connected %s to %s:%d", *url, conn->hostname, conn->port);