]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: ssl: support Openssl 1.1.1 early callback for switchctx
authorEmmanuel Hocdet <manu@gandi.net>
Wed, 16 Aug 2017 09:33:17 +0000 (11:33 +0200)
committerWilly Tarreau <w@1wt.eu>
Fri, 27 Oct 2017 08:54:05 +0000 (10:54 +0200)
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
src/ssl_sock.c

index 5a8c8b54e82e62e3e2482b3aadd884a18eee33d7..bd8cafa23f069f0442822dfe49f5fb659c5a52ff 100644 (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
index 25b846b251ee815b457b8928eca00f83775eb7a0..e1cfc66976bba145af89acdd2cd2a6d5f9f81ee3 100644 (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);