From b47b9d27189779ea08ac11e2510c8f415146d24d Mon Sep 17 00:00:00 2001 From: Guenter Knauf Date: Fri, 21 Dec 2007 13:16:21 +0000 Subject: [PATCH] Added server name indication (RFC 4366) support (PR 34607). Submitted by: Kaspar Brand git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@606190 13f79535-47bb-0310-9956-ffa450edef68 --- CHANGES | 3 + modules/ssl/ssl_engine_init.c | 108 +++++++++++++++++++++++++++++++ modules/ssl/ssl_engine_kernel.c | 23 +++++++ modules/ssl/ssl_toolkit_compat.h | 6 ++ 4 files changed, 140 insertions(+) diff --git a/CHANGES b/CHANGES index 4c8af74771..169ae96e3b 100644 --- a/CHANGES +++ b/CHANGES @@ -2,6 +2,9 @@ Changes with Apache 2.3.0 [ When backported to 2.2.x, remove entry from this file ] + *) mod_ssl: Added server name indication support (RFC 4366). + PR 34607. [Kaspar Brand ] + *) ApacheMonitor.exe: Introduce --kill argument for use by the installer. This will permit the installation tool to remove all running instances before attempting to remove the .exe. diff --git a/modules/ssl/ssl_engine_init.c b/modules/ssl/ssl_engine_init.c index 5a60516a0a..3da87cea38 100644 --- a/modules/ssl/ssl_engine_init.c +++ b/modules/ssl/ssl_engine_init.c @@ -135,6 +135,87 @@ static int ssl_tmp_keys_init(server_rec *s) return OK; } +#ifndef OPENSSL_NO_TLSEXT +static int set_ssl_vhost(void *servername, conn_rec *c, server_rec *s) +{ + SSLSrvConfigRec *sc; + SSL *ssl; + BOOL found = FALSE; + apr_array_header_t *names; + int i; + + /* check ServerName */ + if (!strcasecmp(servername, s->server_hostname)) + found = TRUE; + + /* if not matched yet, check ServerAlias entries */ + 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; + } + } + } + } + + /* set SSL_CTX (if matched) */ + if (found) { + if ((ssl = ((SSLConnRec *)myConnConfig(c))->ssl) == NULL) + return 0; + if (!(sc = mySrvConfig(s))) + return 0; + SSL_set_SSL_CTX(ssl,sc->server->ssl_ctx); + return 1; + } + return 0; +} + +int ssl_set_vhost_ctx(SSL *ssl, const char *servername) +{ + conn_rec *c; + + if (servername == NULL) /* should not occur. */ + return 0; + + SSL_set_SSL_CTX(ssl,NULL); + + if (!(c = (conn_rec *)SSL_get_app_data(ssl))) + return 0; + + return ap_vhost_iterate_given_conn(c,set_ssl_vhost,servername); +} + +int ssl_servername_cb(SSL *s, int *al, modssl_ctx_t *mctx) +{ + const char *servername = SSL_get_servername(s,TLSEXT_NAMETYPE_host_name); + + if (servername) { + return ssl_set_vhost_ctx(s,servername)?SSL_TLSEXT_ERR_OK:SSL_TLSEXT_ERR_ALERT_FATAL; + } + return SSL_TLSEXT_ERR_NOACK; +} +#endif + /* * Per-module initialization */ @@ -355,6 +436,29 @@ static void ssl_init_server_check(server_rec *s, } } +static void ssl_init_server_extensions(server_rec *s, + apr_pool_t *p, + apr_pool_t *ptemp, + modssl_ctx_t *mctx) +{ + /* + * Configure TLS extensions support + */ + +#ifndef OPENSSL_NO_TLSEXT + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, + "Configuring TLS extensions facility"); + + if (!SSL_CTX_set_tlsext_servername_callback(mctx->ssl_ctx, ssl_servername_cb) || + !SSL_CTX_set_tlsext_servername_arg(mctx->ssl_ctx, mctx)) { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, + "Unable to initialize servername callback, bad openssl version."); + ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, s); + ssl_die(); + } +#endif +} + static void ssl_init_ctx_protocol(server_rec *s, apr_pool_t *p, apr_pool_t *ptemp, @@ -712,6 +816,8 @@ static void ssl_init_ctx(server_rec *s, /* XXX: proxy support? */ ssl_init_ctx_cert_chain(s, p, ptemp, mctx); } + + ssl_init_server_extensions(s, p, ptemp, mctx); } static int ssl_server_import_cert(server_rec *s, @@ -1038,6 +1144,7 @@ void ssl_init_CheckServers(server_rec *base_server, apr_pool_t *p) } } +#ifdef OPENSSL_NO_TLSEXT /* * Give out warnings when more than one SSL-aware virtual server uses the * same IP:port. This doesn't work because mod_ssl then will always use @@ -1082,6 +1189,7 @@ void ssl_init_CheckServers(server_rec *base_server, apr_pool_t *p) "Init: You should not use name-based " "virtual hosts in conjunction with SSL!!"); } +#endif } #ifdef SSLC_VERSION_NUMBER diff --git a/modules/ssl/ssl_engine_kernel.c b/modules/ssl/ssl_engine_kernel.c index 9b85522338..5d741af54a 100644 --- a/modules/ssl/ssl_engine_kernel.c +++ b/modules/ssl/ssl_engine_kernel.c @@ -297,6 +297,19 @@ int ssl_hook_Access(request_rec *r) * the currently active one. */ +#ifndef OPENSSL_NO_TLSEXT + /* + * We will switch to another virtualhost and to its ssl_ctx + * if changed, we will force a renegotiation. + */ + if (r->hostname && !SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name)) { + SSL_CTX *ctx = SSL_get_SSL_CTX(ssl); + if (ssl_set_vhost_ctx(ssl,(char *)r->hostname) && + ctx != SSL_get_SSL_CTX(ssl)) + renegotiate = TRUE; + } +#endif + /* * Override of SSLCipherSuite * @@ -1063,6 +1076,9 @@ int ssl_hook_Fixup(request_rec *r) SSLDirConfigRec *dc = myDirConfig(r); apr_table_t *env = r->subprocess_env; char *var, *val = ""; +#ifndef OPENSSL_NO_TLSEXT + const char* servername; +#endif STACK_OF(X509) *peer_certs; SSL *ssl; int i; @@ -1089,6 +1105,13 @@ int ssl_hook_Fixup(request_rec *r) /* the always present HTTPS (=HTTP over SSL) flag! */ apr_table_setn(env, "HTTPS", "on"); +#ifndef OPENSSL_NO_TLSEXT + /* add content of SNI TLS extension (if supplied with ClientHello) */ + if (servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name)) { + apr_table_set(env, "SSL_TLS_SNI", servername); + } +#endif + /* standard SSL environment variables */ if (dc->nOptions & SSL_OPT_STDENVVARS) { for (i = 0; ssl_hook_Fixup_vars[i]; i++) { diff --git a/modules/ssl/ssl_toolkit_compat.h b/modules/ssl/ssl_toolkit_compat.h index e3850e2e0a..29dff3aaa7 100644 --- a/modules/ssl/ssl_toolkit_compat.h +++ b/modules/ssl/ssl_toolkit_compat.h @@ -270,6 +270,12 @@ typedef void (*modssl_popfree_fn)(char *data); #define SSL_SESS_CACHE_NO_INTERNAL SSL_SESS_CACHE_NO_INTERNAL_LOOKUP #endif +#ifndef OPENSSL_NO_TLSEXT +#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME +#define OPENSSL_NO_TLSEXT +#endif +#endif + #endif /* SSL_TOOLKIT_COMPAT_H */ /** @} */ -- 2.50.1