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
Index: modules/ssl/ssl_engine_kernel.c
===================================================================
--- modules/ssl/ssl_engine_kernel.c (revision 1551684)
+++ modules/ssl/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);