From 84e417d8593438b56654125d6e86d948038cfa45 Mon Sep 17 00:00:00 2001 From: Emmanuel Hocdet Date: Wed, 16 Aug 2017 11:33:17 +0200 Subject: [PATCH] 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. --- doc/configuration.txt | 13 +++++++------ src/ssl_sock.c | 35 ++++++++++++++++++++++++++++++++--- 2 files changed, 39 insertions(+), 9 deletions(-) diff --git a/doc/configuration.txt b/doc/configuration.txt index 5a8c8b54e8..bd8cafa23f 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -10399,8 +10399,9 @@ crt 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 argument, haproxy will automatically search and load bundled files in that directory. @@ -10424,7 +10425,7 @@ crt-list 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 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 diff --git a/src/ssl_sock.c b/src/ssl_sock.c index 25b846b251..e1cfc66976 100644 --- a/src/ssl_sock.c +++ b/src/ssl_sock.c @@ -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); -- 2.39.5