httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Ruediger Pluem <rpl...@apache.org>
Subject Re: Behavior of Host: vs. SNI Hostname in proxy CONNECT requests
Date Tue, 17 Dec 2013 21:13:02 GMT


Kaspar Brand wrote:

> If your goal is to make httpd compatible with Chrome's "Secure Web
> Proxy" or another other client doing CONNECT over SSL, that's fine, and
> I'm not opposed to it (a small change to ssl_hook_ReadReq [attached]

I guess a more general fix for this would be:

Index: ssl_engine_kernel.c
===================================================================
--- ssl_engine_kernel.c (revision 1551684)
+++ ssl_engine_kernel.c (working copy)
@@ -164,48 +164,50 @@
         return DECLINED;
     }
 #ifdef HAVE_TLSEXT
-    if ((servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name))) {
-        char *host, *scope_id;
-        apr_port_t port;
-        apr_status_t rv;
+    if (r->proxyreq != PROXYREQ_PROXY) {
+        if ((servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name))) {
+            char *host, *scope_id;
+            apr_port_t port;
+            apr_status_t rv;

-        /*
-         * The SNI extension supplied a hostname. So don't accept requests
-         * with either no hostname or a different hostname.
-         */
-        if (!r->hostname) {
-            ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, APLOGNO(02031)
-                        "Hostname %s provided via SNI, but no hostname"
-                        " provided in HTTP request", servername);
-            return HTTP_BAD_REQUEST;
+            /*
+             * The SNI extension supplied a hostname. So don't accept requests
+             * with either no hostname or a different hostname.
+             */
+            if (!r->hostname) {
+                ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, APLOGNO(02031)
+                            "Hostname %s provided via SNI, but no hostname"
+                            " provided in HTTP request", servername);
+                return HTTP_BAD_REQUEST;
+            }
+            rv = apr_parse_addr_port(&host, &scope_id, &port, r->hostname,
r->pool);
+            if (rv != APR_SUCCESS || scope_id) {
+                return HTTP_BAD_REQUEST;
+            }
+            if (strcasecmp(host, servername)) {
+                ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, APLOGNO(02032)
+                            "Hostname %s provided via SNI and hostname %s provided"
+                            " via HTTP are different", servername, host);
+                return HTTP_BAD_REQUEST;
+            }
         }
-        rv = apr_parse_addr_port(&host, &scope_id, &port, r->hostname, r->pool);
-        if (rv != APR_SUCCESS || scope_id) {
-            return HTTP_BAD_REQUEST;
+        else if (((sc->strict_sni_vhost_check == SSL_ENABLED_TRUE)
+                 || (mySrvConfig(sslconn->server))->strict_sni_vhost_check
+                    == SSL_ENABLED_TRUE)
+                 && r->connection->vhost_lookup_data) {
+            /*
+             * We are using a name based configuration here, but no hostname was
+             * provided via SNI. Don't allow that if are requested to do strict
+             * checking. Check wether this strict checking was setup either in the
+             * server config we used for handshaking or in our current server.
+             * This should avoid insecure configuration by accident.
+             */
+            ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, APLOGNO(02033)
+                         "No hostname was provided via SNI for a name based"
+                         " virtual host");
+            return HTTP_FORBIDDEN;
         }
-        if (strcasecmp(host, servername)) {
-            ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, APLOGNO(02032)
-                        "Hostname %s provided via SNI and hostname %s provided"
-                        " via HTTP are different", servername, host);
-            return HTTP_BAD_REQUEST;
-        }
     }
-    else if (((sc->strict_sni_vhost_check == SSL_ENABLED_TRUE)
-             || (mySrvConfig(sslconn->server))->strict_sni_vhost_check
-                == SSL_ENABLED_TRUE)
-             && r->connection->vhost_lookup_data) {
-        /*
-         * We are using a name based configuration here, but no hostname was
-         * provided via SNI. Don't allow that if are requested to do strict
-         * checking. Check wether this strict checking was setup either in the
-         * server config we used for handshaking or in our current server.
-         * This should avoid insecure configuration by accident.
-         */
-        ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, APLOGNO(02033)
-                     "No hostname was provided via SNI for a name based"
-                     " virtual host");
-        return HTTP_FORBIDDEN;
-    }
 #endif
     SSL_set_app_data2(ssl, r);



While this looks awfully more complex at first glance it actually just skips all these checks
if a forward proxy request
was detected by mod_proxy. This covers "normal" forward proxy requests as well as CONNECT
forward request.
Using the Host header to choose a name based virtual host on Apache side in case of a forward
proxy request does not
make any sense at all. Hence a forward proxy virtual host should always be IP/Port based.

Regards

RĂ¼diger


Mime
View raw message