From cf6c7246d53d9e7cc97f30ba20e6eaaf20d94d23 Mon Sep 17 00:00:00 2001 From: Stefan Eissing Date: Fri, 28 Aug 2015 13:00:52 +0000 Subject: [PATCH] first stab at a better SNI vs. request name matching, by accounting for serveralias and wildcards git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1698330 13f79535-47bb-0310-9956-ffa450edef68 --- modules/ssl/ssl_engine_kernel.c | 62 +++++++-------------------------- modules/ssl/ssl_private.h | 2 ++ modules/ssl/ssl_util.c | 46 ++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 49 deletions(-) diff --git a/modules/ssl/ssl_engine_kernel.c b/modules/ssl/ssl_engine_kernel.c index bd1b7cbb00..60865b7ae8 100644 --- a/modules/ssl/ssl_engine_kernel.c +++ b/modules/ssl/ssl_engine_kernel.c @@ -200,14 +200,18 @@ int ssl_hook_ReadReq(request_rec *r) if (rv != APR_SUCCESS || scope_id) { return HTTP_BAD_REQUEST; } - if (strcasecmp(host, servername)) { + if (strcasecmp(host, servername) + || !sslconn->server + || !ssl_util_vhost_matches(host, sslconn->server)) { + /* + * We are really not in Kansas anymore... + * The request hostname does not match the SNI and does not + * select the virtual host that was selected by the SNI. + */ 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); - if (r->connection->keepalives > 0) { - return HTTP_MISDIRECTED_REQUEST; - } - return HTTP_BAD_REQUEST; + "Hostname %s provided via SNI and hostname %s provided" + " via HTTP are different", servername, host); + return HTTP_MISDIRECTED_REQUEST; } } else if (((sc->strict_sni_vhost_check == SSL_ENABLED_TRUE) @@ -2000,50 +2004,10 @@ static int ssl_find_vhost(void *servername, conn_rec *c, server_rec *s) { SSLSrvConfigRec *sc; SSL *ssl; - BOOL found = FALSE; - apr_array_header_t *names; - int i; + BOOL found; SSLConnRec *sslcon; - /* check ServerName */ - if (!strcasecmp(servername, s->server_hostname)) { - found = TRUE; - } - - /* - * if not matched yet, check ServerAlias entries - * (adapted from vhost.c:matches_aliases()) - */ - if (!found) { - names = s->names; - if (names) { - char **name = (char **)names->elts; - for (i = 0; i < names->nelts; ++i) { - if (!name[i]) - continue; - if (!strcasecmp(servername, name[i])) { - found = TRUE; - break; - } - } - } - } - - /* if still no match, check ServerAlias entries with wildcards */ - if (!found) { - names = s->wild_names; - if (names) { - char **name = (char **)names->elts; - for (i = 0; i < names->nelts; ++i) { - if (!name[i]) - continue; - if (!ap_strcasecmp_match(servername, name[i])) { - found = TRUE; - break; - } - } - } - } + found = ssl_util_vhost_matches(servername, s); /* set SSL_CTX (if matched) */ sslcon = myConnConfig(c); diff --git a/modules/ssl/ssl_private.h b/modules/ssl/ssl_private.h index 48ad0e7206..6b89fcf24c 100644 --- a/modules/ssl/ssl_private.h +++ b/modules/ssl/ssl_private.h @@ -853,6 +853,8 @@ BOOL ssl_util_path_check(ssl_pathcheck_t, const char *, apr_pool_t *); void ssl_util_thread_setup(apr_pool_t *); int ssl_init_ssl_connection(conn_rec *c, request_rec *r); +BOOL ssl_util_vhost_matches(const char *servername, server_rec *s); + /** Pass Phrase Support */ apr_status_t ssl_load_encrypted_pkey(server_rec *, apr_pool_t *, int, const char *, apr_array_header_t **); diff --git a/modules/ssl/ssl_util.c b/modules/ssl/ssl_util.c index c21971dd77..05c4fbd583 100644 --- a/modules/ssl/ssl_util.c +++ b/modules/ssl/ssl_util.c @@ -60,6 +60,52 @@ char *ssl_util_vhostid(apr_pool_t *p, server_rec *s) return id; } +/* + * Return TRUE iff the given servername matches the server record when + * selecting virtual hosts. + */ +BOOL ssl_util_vhost_matches(const char *servername, server_rec *s) +{ + apr_array_header_t *names; + int i; + + /* check ServerName */ + if (!strcasecmp(servername, s->server_hostname)) { + return TRUE; + } + + /* + * if not matched yet, check ServerAlias entries + * (adapted from vhost.c:matches_aliases()) + */ + names = s->names; + if (names) { + char **name = (char **)names->elts; + for (i = 0; i < names->nelts; ++i) { + if (!name[i]) + continue; + if (!strcasecmp(servername, name[i])) { + return TRUE; + } + } + } + + /* if still no match, check ServerAlias entries with wildcards */ + names = s->wild_names; + if (names) { + char **name = (char **)names->elts; + for (i = 0; i < names->nelts; ++i) { + if (!name[i]) + continue; + if (!ap_strcasecmp_match(servername, name[i])) { + return TRUE; + } + } + } + + return FALSE; +} + apr_file_t *ssl_util_ppopen(server_rec *s, apr_pool_t *p, const char *cmd, const char * const *argv) { -- 2.50.0