MINOR: ssl: support Openssl 1.1.1 early callback for switchctx

Use Openssl-1.1.1 SSL_CTX_set_client_hello_cb to mimic BoringSSL early callback.
Native multi certificate and SSL/TLS method per certificate is now supported by
Openssl >= 1.1.1.
This commit is contained in:
Emmanuel Hocdet 2017-08-16 11:33:17 +02:00 committed by Willy Tarreau
parent 48e8755639
commit 84e417d859
2 changed files with 39 additions and 9 deletions

View File

@ -10399,8 +10399,9 @@ crt <cert>
to use both RSA and ECDSA cipher suites. Users connecting with an SNI of
"rsa.example.com" will only be able to use RSA cipher suites, and users
connecting with "ecdsa.example.com" will only be able to use ECDSA cipher
suites. With BoringSSL multi-cert is natively supported, no need to bundle
certificates. ECDSA certificate will be preferred if client support it.
suites. With BoringSSL and Openssl >= 1.1.1 multi-cert is natively supported,
no need to bundle certificates. ECDSA certificate will be preferred if client
support it.
If a directory name is given as the <cert> argument, haproxy will
automatically search and load bundled files in that directory.
@ -10424,7 +10425,7 @@ crt-list <file>
sslbindconf support "npn", "alpn", "verify", "ca-file", "no-ca-names",
crl-file", "ecdhe", "curves", "ciphers" configuration. With BoringSSL
"ssl-min-ver" and "ssl-max-ver" are also supported.
and Openssl >= 1.1.1 "ssl-min-ver" and "ssl-max-ver" are also supported.
It override the configuration set in bind line for the certificate.
Wildcards are supported in the SNI filter. Negative filter are also supported,
@ -10438,9 +10439,9 @@ crt-list <file>
Multi-cert bundling (see "crt") is supported with crt-list, as long as only
the base name is given in the crt-list. SNI filter will do the same work on
all bundled certificates. With BoringSSL multi-cert is natively supported,
avoid multi-cert bundling. RSA and ECDSA certificates can be declared in a
row, and set different ssl and filter parameter.
all bundled certificates. With BoringSSL and Openssl >= 1.1.1 multi-cert is
natively supported, avoid multi-cert bundling. RSA and ECDSA certificates can
be declared in a row, and set different ssl and filter parameter.
crt-list file example:
cert1.pem

View File

@ -1828,7 +1828,7 @@ ssl_sock_generate_certificate(const char *servername, struct bind_conf *bind_con
#ifndef SSL_OP_NO_TLSv1_2 /* needs OpenSSL >= 1.0.1 */
#define SSL_OP_NO_TLSv1_2 0
#endif
#ifndef SSL_OP_NO_TLSv1_3 /* dev */
#ifndef SSL_OP_NO_TLSv1_3 /* needs OpenSSL >= 1.1.1 */
#define SSL_OP_NO_TLSv1_3 0
#endif
#ifndef SSL_OP_SINGLE_DH_USE /* needs OpenSSL >= 0.9.6 */
@ -1951,7 +1951,7 @@ static void ssl_sock_switchctx_set(SSL *ssl, SSL_CTX *ctx)
SSL_set_SSL_CTX(ssl, ctx);
}
#ifdef OPENSSL_IS_BORINGSSL
#if (OPENSSL_VERSION_NUMBER >= 0x10101000L) || defined(OPENSSL_IS_BORINGSSL)
static int ssl_sock_switchctx_err_cbk(SSL *ssl, int *al, void *priv)
{
@ -1963,9 +1963,14 @@ static int ssl_sock_switchctx_err_cbk(SSL *ssl, int *al, void *priv)
return SSL_TLSEXT_ERR_OK;
}
#ifdef OPENSSL_IS_BORINGSSL
static int ssl_sock_switchctx_cbk(const struct ssl_early_callback_ctx *ctx)
{
SSL *ssl = ctx->ssl;
#else
static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *arg)
{
#endif
struct connection *conn;
struct bind_conf *s;
const uint8_t *extension_data;
@ -1981,8 +1986,12 @@ static int ssl_sock_switchctx_cbk(const struct ssl_early_callback_ctx *ctx)
conn = SSL_get_app_data(ssl);
s = objt_listener(conn->target)->bind_conf;
#ifdef OPENSSL_IS_BORINGSSL
if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_server_name,
&extension_data, &extension_len)) {
#else
if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_server_name, &extension_data, &extension_len)) {
#endif
/*
* The server_name extension was given too much extensibility when it
* was written, so parsing the normal case is a bit complex.
@ -2022,7 +2031,11 @@ static int ssl_sock_switchctx_cbk(const struct ssl_early_callback_ctx *ctx)
}
/* extract/check clientHello informations */
#ifdef OPENSSL_IS_BORINGSSL
if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
#else
if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
#endif
uint8_t sign;
size_t len;
if (extension_len < 2)
@ -2057,13 +2070,21 @@ static int ssl_sock_switchctx_cbk(const struct ssl_early_callback_ctx *ctx)
const SSL_CIPHER *cipher;
size_t len;
const uint8_t *cipher_suites;
#ifdef OPENSSL_IS_BORINGSSL
len = ctx->cipher_suites_len;
cipher_suites = ctx->cipher_suites;
#else
len = SSL_client_hello_get0_ciphers(ssl, &cipher_suites);
#endif
if (len % 2 != 0)
goto abort;
for (; len != 0; len -= 2, cipher_suites += 2) {
#ifdef OPENSSL_IS_BORINGSSL
uint16_t cipher_suite = (cipher_suites[0] << 8) | cipher_suites[1];
cipher = SSL_get_cipher_by_value(cipher_suite);
#else
cipher = SSL_CIPHER_find(ssl, cipher_suites);
#endif
if (cipher && SSL_CIPHER_get_auth_nid(cipher) == NID_auth_ecdsa) {
has_ecdsa = 1;
break;
@ -2152,7 +2173,12 @@ static int ssl_sock_switchctx_cbk(const struct ssl_early_callback_ctx *ctx)
abort:
/* abort handshake (was SSL_TLSEXT_ERR_ALERT_FATAL) */
conn->err_code = CO_ER_SSL_HANDSHAKE;
#ifdef OPENSSL_IS_BORINGSSL
return ssl_select_cert_error;
#else
*al = SSL_AD_UNRECOGNIZED_NAME;
return 0;
#endif
}
#else /* OPENSSL_IS_BORINGSSL */
@ -3647,6 +3673,9 @@ ssl_sock_initial_ctx(struct bind_conf *bind_conf)
#ifdef OPENSSL_IS_BORINGSSL
SSL_CTX_set_select_certificate_cb(ctx, ssl_sock_switchctx_cbk);
SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
#elif (OPENSSL_VERSION_NUMBER >= 0x10101000L)
SSL_CTX_set_client_hello_cb(ctx, ssl_sock_switchctx_cbk, NULL);
SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
#else
SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
@ -6773,7 +6802,7 @@ static int parse_tls_method_minmax(char **args, int cur_arg, struct tls_version_
static int ssl_bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
{
#if !defined(OPENSSL_IS_BORINGSSL)
#if (OPENSSL_VERSION_NUMBER < 0x10101000L) || !defined(OPENSSL_IS_BORINGSSL)
Warning("crt-list: ssl-min-ver and ssl-max-ver are not supported with this Openssl version (skipped).\n");
#endif
return parse_tls_method_minmax(args, cur_arg, &conf->ssl_methods, err);