1
0
mirror of https://github.com/apache/httpd.git synced 2025-08-08 15:02:10 +03:00

mod_ssl: negotiate the TLS protocol version per name based vhost configuration.

By using the new ClientHello callback provided by OpenSSL 1.1.1, which runs at
the earliest connection stage, we can switch the SSL_CTX of the SSL connection
early enough for OpenSSL to take into account the protocol configuration of the
vhost.

In other words:
    SSL_set_SSL_CTX(c->SSL, s->SSL_CTX)
followed by:
    SSL_set_{min,max}_proto_version(SSL_CTX_get_{min,max}_proto_version(s->SSL_CTX))
works as expected at this stage (while the same from the SNI callback is
ignored by/due to OpenSSL's state machine).

Extracting the SNI (to select the relevant vhost) in the ClientHello callback
is not as easy as calling SSL_get_servername() though, we have to work with
the raw TLS extensions helpers provided by OpenSSL. I stole this code from a
test in the OpenSSL source code (i.e. client_hello_select_server_ctx() in
test/handshake_helper.c).

We can then call init_vhost() as with the SNI callback (in use only for OpenSSL
versions earlier than 1.1.1 now), and pass it the extracted SNI.


git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1868645 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Yann Ylavic
2019-10-20 10:50:33 +00:00
parent 82b7e77b82
commit 076e28399c
3 changed files with 91 additions and 7 deletions

View File

@@ -500,8 +500,11 @@ static apr_status_t ssl_init_ctx_tls_extensions(server_rec *s,
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01893)
"Configuring TLS extension handling");
#if OPENSSL_VERSION_NUMBER < 0x10101000L || defined(LIBRESSL_VERSION_NUMBER)
/*
* Server name indication (SNI)
* The Server Name Indication (SNI) provided by the ClientHello can be
* used to select the right (name-based-)vhost and its SSL configuration
* before the handshake takes place.
*/
if (!SSL_CTX_set_tlsext_servername_callback(mctx->ssl_ctx,
ssl_callback_ServerNameIndication) ||
@@ -512,6 +515,15 @@ static apr_status_t ssl_init_ctx_tls_extensions(server_rec *s,
ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s);
return ssl_die(s);
}
#else
/*
* The ClientHello callback also allows to retrieve the SNI, but since it
* runs at the earliest possible connection stage we can even set the TLS
* protocol version(s) according to the selected (name-based-)vhost, which
* is not possible at the SNI callback stage (due to OpenSSL internals).
*/
SSL_CTX_set_client_hello_cb(mctx->ssl_ctx, ssl_callback_ClientHello, NULL);
#endif
#ifdef HAVE_OCSP_STAPLING
/*
@@ -706,7 +718,7 @@ static apr_status_t ssl_init_ctx_protocol(server_rec *s,
#else /* #if OPENSSL_VERSION_NUMBER < 0x10100000L */
/* We first determine the maximum protocol version we should provide */
#if SSL_HAVE_PROTOCOL_TLSV1_3
if (SSL_HAVE_PROTOCOL_TLSV1_3 && (protocol & SSL_PROTOCOL_TLSV1_3)) {
if (protocol & SSL_PROTOCOL_TLSV1_3) {
prot = TLS1_3_VERSION;
} else
#endif