ASF Bugzilla – Attachment 36857 Details for
Bug 62939
SSLProtocol and TLSv1.3
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
ssl callback Hello Client patch from Yann Ylavic
2.4.x-ssl_callback_ClientHello-v2.patch (text/plain), 8.81 KB, created by
Mario
on 2019-10-23 09:32:29 UTC
(
hide
)
Description:
ssl callback Hello Client patch from Yann Ylavic
Filename:
MIME Type:
Creator:
Mario
Created:
2019-10-23 09:32:29 UTC
Size:
8.81 KB
patch
obsolete
>Index: modules/ssl/ssl_engine_init.c >=================================================================== >--- modules/ssl/ssl_engine_init.c (revision 1868789) >+++ modules/ssl/ssl_engine_init.c (working copy) >@@ -498,7 +498,9 @@ static apr_status_t ssl_init_ctx_tls_extensions(se > "Configuring TLS extension handling"); > > /* >- * 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) || >@@ -510,6 +512,16 @@ static apr_status_t ssl_init_ctx_tls_extensions(se > return ssl_die(s); > } > >+#if OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined(LIBRESSL_VERSION_NUMBER) >+ /* >+ * 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 > /* > * OCSP Stapling support, status_request extension >@@ -678,7 +690,7 @@ static apr_status_t ssl_init_ctx_protocol(server_r > #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 >Index: modules/ssl/ssl_engine_kernel.c >=================================================================== >--- modules/ssl/ssl_engine_kernel.c (revision 1868789) >+++ modules/ssl/ssl_engine_kernel.c (working copy) >@@ -2328,21 +2328,23 @@ static apr_status_t set_challenge_creds(conn_rec * > * This function sets the virtual host from an extended > * client hello with a server name indication extension ("SNI", cf. RFC 6066). > */ >-static apr_status_t init_vhost(conn_rec *c, SSL *ssl) >+static apr_status_t init_vhost(conn_rec *c, SSL *ssl, const char *servername) > { >- const char *servername; > X509 *cert; > EVP_PKEY *key; > > if (c) { > SSLConnRec *sslcon = myConnConfig(c); >+ >+ if (sslcon->vhost_found) { >+ /* already found the vhost? */ >+ return sslcon->vhost_found > 0 ? APR_SUCCESS : APR_NOTFOUND; >+ } >+ sslcon->vhost_found = -1; > >- if (sslcon->server != c->base_server) { >- /* already found the vhost */ >- return APR_SUCCESS; >+ if (!servername) { >+ servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name); > } >- >- servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name); > if (servername) { > if (ap_vhost_iterate_given_conn(c, ssl_find_vhost, > (void *)servername)) { >@@ -2349,7 +2351,8 @@ static apr_status_t set_challenge_creds(conn_rec * > ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(02043) > "SSL virtual host for servername %s found", > servername); >- >+ >+ sslcon->vhost_found = +1; > return APR_SUCCESS; > } > else if (ssl_is_challenge(c, servername, &cert, &key)) { >@@ -2399,12 +2402,72 @@ static apr_status_t set_challenge_creds(conn_rec * > int ssl_callback_ServerNameIndication(SSL *ssl, int *al, modssl_ctx_t *mctx) > { > conn_rec *c = (conn_rec *)SSL_get_app_data(ssl); >- apr_status_t status = init_vhost(c, ssl); >+ apr_status_t status = init_vhost(c, ssl, NULL); > > return (status == APR_SUCCESS)? SSL_TLSEXT_ERR_OK : SSL_TLSEXT_ERR_NOACK; > } > >+#if OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined(LIBRESSL_VERSION_NUMBER) > /* >+ * This callback function is called when the ClientHello is received. >+ */ >+int ssl_callback_ClientHello(SSL *ssl, int *al, void *arg) >+{ >+ char *servername = NULL; >+ conn_rec *c = (conn_rec *)SSL_get_app_data(ssl); >+ const unsigned char *pos; >+ size_t len, remaining; >+ (void)arg; >+ >+ /* We can't use SSL_get_servername() at this earliest OpenSSL connection >+ * stage, and there is no SSL_client_hello_get0_servername() provided as >+ * of OpenSSL 1.1.1. So the code below, that extracts the SNI from the >+ * ClientHello's TLS extensions, is taken from some test code in OpenSSL, >+ * i.e. client_hello_select_server_ctx() in "test/handshake_helper.c". >+ */ >+ >+ /* >+ * The server_name extension was given too much extensibility when it >+ * was written, so parsing the normal case is a bit complex. >+ */ >+ if (!SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_server_name, &pos, >+ &remaining) >+ || remaining <= 2) >+ goto give_up; >+ >+ /* Extract the length of the supplied list of names. */ >+ len = (*(pos++) << 8); >+ len += *(pos++); >+ if (len + 2 != remaining) >+ goto give_up; >+ remaining = len; >+ >+ /* >+ * The list in practice only has a single element, so we only consider >+ * the first one. >+ */ >+ if (remaining <= 3 || *pos++ != TLSEXT_NAMETYPE_host_name) >+ goto give_up; >+ remaining--; >+ >+ /* Now we can finally pull out the byte array with the actual hostname. */ >+ len = (*(pos++) << 8); >+ len += *(pos++); >+ if (len + 2 != remaining) >+ goto give_up; >+ >+ /* Use the SNI to switch to the relevant vhost, should it differ from >+ * c->base_server. >+ */ >+ servername = apr_pstrmemdup(c->pool, (const char *)pos, len); >+ >+give_up: >+ init_vhost(c, ssl, servername); >+ return SSL_CLIENT_HELLO_SUCCESS; >+} >+#endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */ >+ >+/* > * Find a (name-based) SSL virtual host where either the ServerName > * or one of the ServerAliases matches the supplied name (to be used > * with ap_vhost_iterate_given_conn()) >@@ -2423,6 +2486,7 @@ static int ssl_find_vhost(void *servername, conn_r > if (found && (ssl = sslcon->ssl) && > (sc = mySrvConfig(s))) { > SSL_CTX *ctx = SSL_set_SSL_CTX(ssl, sc->server->ssl_ctx); >+ > /* > * SSL_set_SSL_CTX() only deals with the server cert, > * so we need to duplicate a few additional settings >@@ -2429,6 +2493,12 @@ static int ssl_find_vhost(void *servername, conn_r > * from the ctx by hand > */ > SSL_set_options(ssl, SSL_CTX_get_options(ctx)); >+#if OPENSSL_VERSION_NUMBER >= 0x10100000L \ >+ && (!defined(LIBRESSL_VERSION_NUMBER) \ >+ || LIBRESSL_VERSION_NUMBER >= 0x20800000L) >+ SSL_set_min_proto_version(ssl, SSL_CTX_get_min_proto_version(ctx)); >+ SSL_set_max_proto_version(ssl, SSL_CTX_get_max_proto_version(ctx)); >+#endif > if ((SSL_get_verify_mode(ssl) == SSL_VERIFY_NONE) || > (SSL_num_renegotiations(ssl) == 0)) { > /* >@@ -2625,7 +2695,7 @@ int ssl_callback_alpn_select(SSL *ssl, > * they callback the SNI. We need to make sure that we know which vhost > * we are dealing with so we respect the correct protocols. > */ >- init_vhost(c, ssl); >+ init_vhost(c, ssl, NULL); > > proposed = ap_select_protocol(c, NULL, sslconn->server, client_protos); > if (!proposed) { >Index: modules/ssl/ssl_private.h >=================================================================== >--- modules/ssl/ssl_private.h (revision 1868789) >+++ modules/ssl/ssl_private.h (working copy) >@@ -554,6 +554,7 @@ typedef struct { > > const char *cipher_suite; /* cipher suite used in last reneg */ > int service_unavailable; /* thouugh we negotiate SSL, no requests will be served */ >+ int vhost_found; /* whether we found vhost from SNI already */ > } SSLConnRec; > > /* BIG FAT WARNING: SSLModConfigRec has unusual memory lifetime: it is >@@ -928,6 +929,9 @@ void ssl_callback_Info(const SSL *, int, i > #ifdef HAVE_TLSEXT > int ssl_callback_ServerNameIndication(SSL *, int *, modssl_ctx_t *); > #endif >+#if OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined(LIBRESSL_VERSION_NUMBER) >+int ssl_callback_ClientHello(SSL *, int *, void *); >+#endif > #ifdef HAVE_TLS_SESSION_TICKETS > int ssl_callback_SessionTicket(SSL *, unsigned char *, unsigned char *, > EVP_CIPHER_CTX *, HMAC_CTX *, int); >Index: . >=================================================================== >--- . (revision 1868789) >+++ . (working copy) > >Property changes on: . >___________________________________________________________________ >Modified: svn:mergeinfo >## -0,0 +0,1 ## > Merged /httpd/httpd/trunk:r1868645,1868743
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 62939
: 36857