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 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 "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 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 suites. With BoringSSL and Openssl >= 1.1.1 multi-cert is natively supported,
certificates. ECDSA certificate will be preferred if client support it. 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 If a directory name is given as the <cert> argument, haproxy will
automatically search and load bundled files in that directory. 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", sslbindconf support "npn", "alpn", "verify", "ca-file", "no-ca-names",
crl-file", "ecdhe", "curves", "ciphers" configuration. With BoringSSL 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. It override the configuration set in bind line for the certificate.
Wildcards are supported in the SNI filter. Negative filter are also supported, 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 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 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, all bundled certificates. With BoringSSL and Openssl >= 1.1.1 multi-cert is
avoid multi-cert bundling. RSA and ECDSA certificates can be declared in a natively supported, avoid multi-cert bundling. RSA and ECDSA certificates can
row, and set different ssl and filter parameter. be declared in a row, and set different ssl and filter parameter.
crt-list file example: crt-list file example:
cert1.pem 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 */ #ifndef SSL_OP_NO_TLSv1_2 /* needs OpenSSL >= 1.0.1 */
#define SSL_OP_NO_TLSv1_2 0 #define SSL_OP_NO_TLSv1_2 0
#endif #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 #define SSL_OP_NO_TLSv1_3 0
#endif #endif
#ifndef SSL_OP_SINGLE_DH_USE /* needs OpenSSL >= 0.9.6 */ #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); 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) 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; return SSL_TLSEXT_ERR_OK;
} }
#ifdef OPENSSL_IS_BORINGSSL
static int ssl_sock_switchctx_cbk(const struct ssl_early_callback_ctx *ctx) static int ssl_sock_switchctx_cbk(const struct ssl_early_callback_ctx *ctx)
{ {
SSL *ssl = ctx->ssl; SSL *ssl = ctx->ssl;
#else
static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *arg)
{
#endif
struct connection *conn; struct connection *conn;
struct bind_conf *s; struct bind_conf *s;
const uint8_t *extension_data; 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); conn = SSL_get_app_data(ssl);
s = objt_listener(conn->target)->bind_conf; s = objt_listener(conn->target)->bind_conf;
#ifdef OPENSSL_IS_BORINGSSL
if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_server_name, if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_server_name,
&extension_data, &extension_len)) { &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 * The server_name extension was given too much extensibility when it
* was written, so parsing the normal case is a bit complex. * 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 */ /* extract/check clientHello informations */
#ifdef OPENSSL_IS_BORINGSSL
if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) { 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; uint8_t sign;
size_t len; size_t len;
if (extension_len < 2) 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; const SSL_CIPHER *cipher;
size_t len; size_t len;
const uint8_t *cipher_suites; const uint8_t *cipher_suites;
#ifdef OPENSSL_IS_BORINGSSL
len = ctx->cipher_suites_len; len = ctx->cipher_suites_len;
cipher_suites = ctx->cipher_suites; cipher_suites = ctx->cipher_suites;
#else
len = SSL_client_hello_get0_ciphers(ssl, &cipher_suites);
#endif
if (len % 2 != 0) if (len % 2 != 0)
goto abort; goto abort;
for (; len != 0; len -= 2, cipher_suites += 2) { for (; len != 0; len -= 2, cipher_suites += 2) {
#ifdef OPENSSL_IS_BORINGSSL
uint16_t cipher_suite = (cipher_suites[0] << 8) | cipher_suites[1]; uint16_t cipher_suite = (cipher_suites[0] << 8) | cipher_suites[1];
cipher = SSL_get_cipher_by_value(cipher_suite); 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) { if (cipher && SSL_CIPHER_get_auth_nid(cipher) == NID_auth_ecdsa) {
has_ecdsa = 1; has_ecdsa = 1;
break; break;
@ -2152,7 +2173,12 @@ static int ssl_sock_switchctx_cbk(const struct ssl_early_callback_ctx *ctx)
abort: abort:
/* abort handshake (was SSL_TLSEXT_ERR_ALERT_FATAL) */ /* abort handshake (was SSL_TLSEXT_ERR_ALERT_FATAL) */
conn->err_code = CO_ER_SSL_HANDSHAKE; conn->err_code = CO_ER_SSL_HANDSHAKE;
#ifdef OPENSSL_IS_BORINGSSL
return ssl_select_cert_error; return ssl_select_cert_error;
#else
*al = SSL_AD_UNRECOGNIZED_NAME;
return 0;
#endif
} }
#else /* OPENSSL_IS_BORINGSSL */ #else /* OPENSSL_IS_BORINGSSL */
@ -3647,6 +3673,9 @@ ssl_sock_initial_ctx(struct bind_conf *bind_conf)
#ifdef OPENSSL_IS_BORINGSSL #ifdef OPENSSL_IS_BORINGSSL
SSL_CTX_set_select_certificate_cb(ctx, ssl_sock_switchctx_cbk); SSL_CTX_set_select_certificate_cb(ctx, ssl_sock_switchctx_cbk);
SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_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 #else
SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk); SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf); 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) 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"); Warning("crt-list: ssl-min-ver and ssl-max-ver are not supported with this Openssl version (skipped).\n");
#endif #endif
return parse_tls_method_minmax(args, cur_arg, &conf->ssl_methods, err); return parse_tls_method_minmax(args, cur_arg, &conf->ssl_methods, err);