From: Amos Jeffries Date: Sat, 16 Jul 2022 11:44:16 +0000 (+0000) Subject: Bug 5133: OpenSSL 3.0 support (#694) X-Git-Tag: SQUID_5_7~1 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=3db8afad158dcdaa9390d8b998239e5763ae2cf4;p=thirdparty%2Fsquid.git Bug 5133: OpenSSL 3.0 support (#694) This TLS update includes: * Fix build with OpenSSL v3. * Refactor RSA key generation to avoid deprecated RSA_*() APIs. * Refactor DH parameter and key config to avoid deprecated DH_*() APIs. * Refactor ECDH key creation to avoid deprecated EC_*() APIs. * Deprecate ssl_engine support in builds with OpenSSL v1-. * Disable ssl_engine support in builds OpenSSL v3+. We deprecated/removed ssl_engine support (as summarized in the last two bullets above) without providing an OpenSSL Providers-based alternative because of the following factors: 1. We do not have the resources to update ssl_engine code to build (without deprecation warnings) with OpenSSL v3 when the feature is unused. 2. We do not have the resources to create an OpenSSL v3 Provider-based replacement for ssl_engine code that uses deprecated Engine APIs. 3. OpenSSL v3 deprecated Engine support (triggering deprecation warnings in applications that use Engine APIs with OpenSSL v3). Since Squid default builds use -Werror, doing nothing would break such builds. 4. Squid ssl_engine does not appear to be a popular feature. --- diff --git a/configure.ac b/configure.ac index 1799c81f2b..dcfb59043b 100644 --- a/configure.ac +++ b/configure.ac @@ -1333,6 +1333,7 @@ if test "x$with_openssl" = "xyes"; then openssl/bio.h \ openssl/bn.h \ openssl/crypto.h \ + openssl/decoder.h \ openssl/dh.h \ openssl/err.h \ openssl/evp.h \ diff --git a/src/cf.data.pre b/src/cf.data.pre index 1182564370..9b744715b3 100644 --- a/src/cf.data.pre +++ b/src/cf.data.pre @@ -3049,6 +3049,8 @@ DEFAULT: none DOC_START The OpenSSL engine to use. You will need to set this if you would like to use hardware SSL acceleration for example. + + Not supported in builds with OpenSSL v3 or newer. DOC_END NAME: sslproxy_session_ttl diff --git a/src/main.cc b/src/main.cc index 080e71a1a4..a55d9ed032 100644 --- a/src/main.cc +++ b/src/main.cc @@ -679,7 +679,9 @@ mainHandleCommandLineOption(const int optId, const char *optValue) printf("%s\n",SQUID_BUILD_INFO); #if USE_OPENSSL printf("\nThis binary uses %s. ", OpenSSL_version(OPENSSL_VERSION)); +#if OPENSSL_VERSION_MAJOR < 3 printf("For legal restrictions on distribution see https://www.openssl.org/source/license.html\n\n"); +#endif #endif printf( "configure options: %s\n", SQUID_CONFIGURE_OPTIONS); diff --git a/src/security/PeerOptions.cc b/src/security/PeerOptions.cc index 005d816878..b61280a8c0 100644 --- a/src/security/PeerOptions.cc +++ b/src/security/PeerOptions.cc @@ -293,134 +293,134 @@ Security::PeerOptions::createClientContext(bool setOptions) /// set of options we can parse and what they map to static struct ssl_option { const char *name; - long value; + Security::ParsedOptions value; } ssl_options[] = { -#if SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG +#if defined(SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG) { "NETSCAPE_REUSE_CIPHER_CHANGE_BUG", SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG }, #endif -#if SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG +#if defined(SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG) { "SSLREF2_REUSE_CERT_TYPE_BUG", SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG }, #endif -#if SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER +#if defined(SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER) { "MICROSOFT_BIG_SSLV3_BUFFER", SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER }, #endif -#if SSL_OP_SSLEAY_080_CLIENT_DH_BUG +#if defined(SSL_OP_SSLEAY_080_CLIENT_DH_BUG) { "SSLEAY_080_CLIENT_DH_BUG", SSL_OP_SSLEAY_080_CLIENT_DH_BUG }, #endif -#if SSL_OP_TLS_D5_BUG +#if defined(SSL_OP_TLS_D5_BUG) { "TLS_D5_BUG", SSL_OP_TLS_D5_BUG }, #endif -#if SSL_OP_TLS_BLOCK_PADDING_BUG +#if defined(SSL_OP_TLS_BLOCK_PADDING_BUG) { "TLS_BLOCK_PADDING_BUG", SSL_OP_TLS_BLOCK_PADDING_BUG }, #endif -#if SSL_OP_TLS_ROLLBACK_BUG +#if defined(SSL_OP_TLS_ROLLBACK_BUG) { "TLS_ROLLBACK_BUG", SSL_OP_TLS_ROLLBACK_BUG }, #endif -#if SSL_OP_ALL +#if defined(SSL_OP_ALL) { "ALL", SSL_OP_ALL }, #endif -#if SSL_OP_SINGLE_DH_USE +#if defined(SSL_OP_SINGLE_DH_USE) { "SINGLE_DH_USE", SSL_OP_SINGLE_DH_USE }, #endif -#if SSL_OP_EPHEMERAL_RSA +#if defined(SSL_OP_EPHEMERAL_RSA) { "EPHEMERAL_RSA", SSL_OP_EPHEMERAL_RSA }, #endif -#if SSL_OP_PKCS1_CHECK_1 +#if defined(SSL_OP_PKCS1_CHECK_1) { "PKCS1_CHECK_1", SSL_OP_PKCS1_CHECK_1 }, #endif -#if SSL_OP_PKCS1_CHECK_2 +#if defined(SSL_OP_PKCS1_CHECK_2) { "PKCS1_CHECK_2", SSL_OP_PKCS1_CHECK_2 }, #endif -#if SSL_OP_NETSCAPE_CA_DN_BUG +#if defined(SSL_OP_NETSCAPE_CA_DN_BUG) { "NETSCAPE_CA_DN_BUG", SSL_OP_NETSCAPE_CA_DN_BUG }, #endif -#if SSL_OP_NON_EXPORT_FIRST +#if defined(SSL_OP_NON_EXPORT_FIRST) { "NON_EXPORT_FIRST", SSL_OP_NON_EXPORT_FIRST }, #endif -#if SSL_OP_CIPHER_SERVER_PREFERENCE +#if defined(SSL_OP_CIPHER_SERVER_PREFERENCE) { "CIPHER_SERVER_PREFERENCE", SSL_OP_CIPHER_SERVER_PREFERENCE }, #endif -#if SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG +#if defined(SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG) { "NETSCAPE_DEMO_CIPHER_CHANGE_BUG", SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG }, #endif -#if SSL_OP_NO_SSLv3 +#if defined(SSL_OP_NO_SSLv3) { "NO_SSLv3", SSL_OP_NO_SSLv3 }, #endif -#if SSL_OP_NO_TLSv1 +#if defined(SSL_OP_NO_TLSv1) { "NO_TLSv1", SSL_OP_NO_TLSv1 }, #else { "NO_TLSv1", 0 }, #endif -#if SSL_OP_NO_TLSv1_1 +#if defined(SSL_OP_NO_TLSv1_1) { "NO_TLSv1_1", SSL_OP_NO_TLSv1_1 }, #else { "NO_TLSv1_1", 0 }, #endif -#if SSL_OP_NO_TLSv1_2 +#if defined(SSL_OP_NO_TLSv1_2) { "NO_TLSv1_2", SSL_OP_NO_TLSv1_2 }, #else { "NO_TLSv1_2", 0 }, #endif -#if SSL_OP_NO_TLSv1_3 +#if defined(SSL_OP_NO_TLSv1_3) { "NO_TLSv1_3", SSL_OP_NO_TLSv1_3 }, #else { "NO_TLSv1_3", 0 }, #endif -#if SSL_OP_NO_COMPRESSION +#if defined(SSL_OP_NO_COMPRESSION) { "No_Compression", SSL_OP_NO_COMPRESSION }, #endif -#if SSL_OP_NO_TICKET +#if defined(SSL_OP_NO_TICKET) { "NO_TICKET", SSL_OP_NO_TICKET }, #endif -#if SSL_OP_SINGLE_ECDH_USE +#if defined(SSL_OP_SINGLE_ECDH_USE) { "SINGLE_ECDH_USE", SSL_OP_SINGLE_ECDH_USE }, @@ -455,7 +455,7 @@ Security::PeerOptions::parseOptions() #if USE_OPENSSL ::Parser::Tokenizer tok(str); - long op = 0; + ParsedOptions op = 0; while (!tok.atEnd()) { enum { @@ -472,7 +472,8 @@ Security::PeerOptions::parseOptions() static const CharacterSet optChars = CharacterSet("TLS-option", "_") + CharacterSet::ALPHA + CharacterSet::DIGIT; int64_t hex = 0; SBuf option; - long value = 0; + ParsedOptions value = 0; + bool found = false; // Bug 4429: identify the full option name before determining text or numeric if (tok.prefix(option, optChars)) { @@ -481,14 +482,16 @@ Security::PeerOptions::parseOptions() for (struct ssl_option *opttmp = ssl_options; opttmp->name; ++opttmp) { if (option.cmp(opttmp->name) == 0) { value = opttmp->value; + found = true; break; } } // Special case.. hex specification ::Parser::Tokenizer tmp(option); - if (!value && tmp.int64(hex, 16, false) && tmp.atEnd()) { + if (!found && tmp.int64(hex, 16, false) && tmp.atEnd()) { value = hex; + found = true; } } @@ -502,7 +505,7 @@ Security::PeerOptions::parseOptions() break; } } else { - debugs(83, DBG_PARSE_NOTE(1), "ERROR: Unknown TLS option " << option); + debugs(83, DBG_PARSE_NOTE(DBG_IMPORTANT), "ERROR: " << (found?"Unsupported":"Unknown") << " TLS option " << option); } static const CharacterSet delims("TLS-option-delim",":,"); @@ -512,9 +515,10 @@ Security::PeerOptions::parseOptions() } -#if SSL_OP_NO_SSLv2 +#if defined(SSL_OP_NO_SSLv2) // compliance with RFC 6176: Prohibiting Secure Sockets Layer (SSL) Version 2.0 - op = op | SSL_OP_NO_SSLv2; + if (SSL_OP_NO_SSLv2) + op |= SSL_OP_NO_SSLv2; #endif parsedOptions = op; diff --git a/src/security/ServerOptions.cc b/src/security/ServerOptions.cc index e96869c70f..4897692bb3 100644 --- a/src/security/ServerOptions.cc +++ b/src/security/ServerOptions.cc @@ -10,8 +10,10 @@ #include "anyp/PortCfg.h" #include "base/Packable.h" #include "cache_cf.h" +#include "error/SysErrorDetail.h" #include "fatal.h" #include "globals.h" +#include "security/Io.h" #include "security/ServerOptions.h" #include "security/Session.h" #include "SquidConfig.h" @@ -19,6 +21,9 @@ #include "compat/openssl.h" #include "ssl/support.h" +#if HAVE_OPENSSL_DECODER_H +#include +#endif #if HAVE_OPENSSL_ERR_H #include #endif @@ -352,11 +357,20 @@ Security::ServerOptions::loadDhParams() if (dhParamsFile.isEmpty()) return; + // TODO: After loading and validating parameters, also validate that "the + // public and private components have the correct mathematical + // relationship". See EVP_PKEY_check(). + #if USE_OPENSSL +#if OPENSSL_VERSION_MAJOR < 3 DH *dhp = nullptr; if (FILE *in = fopen(dhParamsFile.c_str(), "r")) { dhp = PEM_read_DHparams(in, NULL, NULL, NULL); fclose(in); + } else { + const auto xerrno = errno; + debugs(83, DBG_IMPORTANT, "WARNING: Failed to open '" << dhParamsFile << "'" << xstrerr(xerrno)); + return; } if (!dhp) { @@ -374,7 +388,71 @@ Security::ServerOptions::loadDhParams() } parsedDhParams.resetWithoutLocking(dhp); + +#else // OpenSSL 3.0+ + const auto type = eecdhCurve.isEmpty() ? "DH" : "EC"; + + Security::ForgetErrors(); + EVP_PKEY *rawPkey = nullptr; + using DecoderContext = std::unique_ptr >; + if (const DecoderContext dctx{OSSL_DECODER_CTX_new_for_pkey(&rawPkey, "PEM", nullptr, type, 0, nullptr, nullptr)}) { + + // OpenSSL documentation is vague on this, but OpenSSL code and our + // tests suggest that rawPkey remains nil here while rawCtx keeps + // rawPkey _address_ for use by the decoder (see OSSL_DECODER_from_fp() + // below). Thus, we must not move *rawPkey into a smart pointer until + // decoding is over. For cleanup code simplicity, we assert nil rawPkey. + assert(!rawPkey); + + if (OSSL_DECODER_CTX_get_num_decoders(dctx.get()) == 0) { + auto ssl_error = ERR_get_error(); + debugs(83, DBG_IMPORTANT, "WARNING: No suitable decoders found for " << type << " parameters. " << Security::ErrorString(ssl_error)); + return; + } + + if (const auto in = fopen(dhParamsFile.c_str(), "r")) { + if (OSSL_DECODER_from_fp(dctx.get(), in)) { + assert(rawPkey); + const Security::DhePointer pkey(rawPkey); + // TODO: verify that the loaded parameters match the curve named in eecdhCurve + + if (const Ssl::EVP_PKEY_CTX_Pointer pkeyCtx{EVP_PKEY_CTX_new_from_pkey(nullptr, pkey.get(), nullptr)}) { + switch (EVP_PKEY_param_check(pkeyCtx.get())) { + case 1: // success + parsedDhParams = pkey; + break; + case -2: { + auto ssl_error = ERR_get_error(); + debugs(83, DBG_PARSE_NOTE(2), "WARNING: OpenSSL does not support " << type << " parameters check: " << dhParamsFile << ". " << Security::ErrorString(ssl_error)); + } break; + default: { + auto ssl_error = ERR_get_error(); + debugs(83, DBG_IMPORTANT, "ERROR: Failed to verify " << type << " parameters in " << dhParamsFile << ". " << Security::ErrorString(ssl_error)); + } break; + } + } else { + // TODO: Reduce error reporting code duplication. + auto ssl_error = ERR_get_error(); + debugs(83, DBG_IMPORTANT, "ERROR: Cannot check " << type << " parameters in " << dhParamsFile << ". " << Security::ErrorString(ssl_error)); + } + } else { + auto ssl_error = ERR_get_error(); + debugs(83, DBG_IMPORTANT, "WARNING: Failed to decode " << type << " parameters '" << dhParamsFile << "'. " << Security::ErrorString(ssl_error)); + EVP_PKEY_free(rawPkey); // probably still nil, but just in case + } + fclose(in); + } else { + const auto xerrno = errno; + debugs(83, DBG_IMPORTANT, "WARNING: Failed to open '" << dhParamsFile << "'" << xstrerr(xerrno)); + } + + } else { + auto ssl_error = ERR_get_error(); + debugs(83, DBG_IMPORTANT, "WARNING: Unable to create decode context for " << type << " parameters. " << Security::ErrorString(ssl_error)); + return; + } #endif +#endif // USE_OPENSSL } bool @@ -452,12 +530,16 @@ Security::ServerOptions::updateContextEecdh(Security::ContextPointer &ctx) debugs(83, 9, "Setting Ephemeral ECDH curve to " << eecdhCurve << "."); #if USE_OPENSSL && OPENSSL_VERSION_NUMBER >= 0x0090800fL && !defined(OPENSSL_NO_ECDH) + + Security::ForgetErrors(); + int nid = OBJ_sn2nid(eecdhCurve.c_str()); if (!nid) { debugs(83, DBG_CRITICAL, "ERROR: Unknown EECDH curve '" << eecdhCurve << "'"); return; } +#if OPENSSL_VERSION_MAJOR < 3 auto ecdh = EC_KEY_new_by_curve_name(nid); if (!ecdh) { const auto x = ERR_get_error(); @@ -471,6 +553,14 @@ Security::ServerOptions::updateContextEecdh(Security::ContextPointer &ctx) } EC_KEY_free(ecdh); +#else + // TODO: Support multiple group names via SSL_CTX_set1_groups_list(). + if (!SSL_CTX_set1_groups(ctx.get(), &nid, 1)) { + auto ssl_error = ERR_get_error(); + debugs(83, DBG_CRITICAL, "ERROR: Unable to set Ephemeral ECDH: " << Security::ErrorString(ssl_error)); + return; + } +#endif #else debugs(83, DBG_CRITICAL, "ERROR: EECDH is not available in this build." << " Please link against OpenSSL>=0.9.8 and ensure OPENSSL_NO_ECDH is not set."); diff --git a/src/security/forward.h b/src/security/forward.h index 26225aae01..9c4ff051b1 100644 --- a/src/security/forward.h +++ b/src/security/forward.h @@ -93,10 +93,25 @@ typedef std::list CertList; typedef std::list CertRevokeList; #if USE_OPENSSL +CtoCpp1(EVP_PKEY_free, EVP_PKEY *) +using PrivateKeyPointer = Security::LockingPointer>; +#elif USE_GNUTLS +using PrivateKeyPointer = std::shared_ptr; +#else +using PrivateKeyPointer = std::shared_ptr; +#endif + +#if USE_OPENSSL +#if OPENSSL_VERSION_MAJOR < 3 CtoCpp1(DH_free, DH *); typedef Security::LockingPointer > DhePointer; #else -typedef void *DhePointer; +using DhePointer = PrivateKeyPointer; +#endif +#elif USE_GNUTLS +using DhePointer = void *; +#else +using DhePointer = void *; #endif class EncryptorAnswer; @@ -159,7 +174,7 @@ class IoResult; class KeyData; #if USE_OPENSSL -typedef long ParsedOptions; +using ParsedOptions = uint64_t; #elif USE_GNUTLS typedef std::shared_ptr ParsedOptions; #else @@ -175,15 +190,6 @@ class PeerConnector; class BlindPeerConnector; class PeerOptions; -#if USE_OPENSSL -CtoCpp1(EVP_PKEY_free, EVP_PKEY *) -typedef Security::LockingPointer > PrivateKeyPointer; -#elif USE_GNUTLS -typedef std::shared_ptr PrivateKeyPointer; -#else -typedef std::shared_ptr PrivateKeyPointer; -#endif - class ServerOptions; class ErrorDetail; diff --git a/src/ssl/gadgets.cc b/src/ssl/gadgets.cc index ef572ba740..d1def598ee 100644 --- a/src/ssl/gadgets.cc +++ b/src/ssl/gadgets.cc @@ -9,36 +9,26 @@ #include "squid.h" #include "ssl/gadgets.h" -EVP_PKEY * Ssl::createSslPrivateKey() +static Security::PrivateKeyPointer +CreateRsaPrivateKey() { - Security::PrivateKeyPointer pkey(EVP_PKEY_new()); - - if (!pkey) - return NULL; - - BIGNUM_Pointer bn(BN_new()); - if (!bn) - return NULL; - - if (!BN_set_word(bn.get(), RSA_F4)) - return NULL; - - Ssl::RSA_Pointer rsa(RSA_new()); + Ssl::EVP_PKEY_CTX_Pointer rsa(EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, nullptr)); if (!rsa) - return NULL; + return nullptr; - int num = 2048; // Maybe use 4096 RSA keys, or better make it configurable? - if (!RSA_generate_key_ex(rsa.get(), num, bn.get(), NULL)) - return NULL; + if (EVP_PKEY_keygen_init(rsa.get()) <= 0) + return nullptr; - if (!rsa) - return NULL; + int num = 2048; // Maybe use 4096 RSA keys, or better make it configurable? + if (EVP_PKEY_CTX_set_rsa_keygen_bits(rsa.get(), num) <= 0) + return nullptr; - if (!EVP_PKEY_assign_RSA(pkey.get(), (rsa.get()))) - return NULL; + /* Generate key */ + EVP_PKEY *pkey = nullptr; + if (EVP_PKEY_keygen(rsa.get(), &pkey) <= 0) + return nullptr; - rsa.release(); - return pkey.release(); + return Security::PrivateKeyPointer(pkey); } /** @@ -56,7 +46,7 @@ static bool setSerialNumber(ASN1_INTEGER *ai, BIGNUM const* serial) if (!bn) return false; - if (!BN_pseudo_rand(bn.get(), 64, 0, 0)) + if (!BN_rand(bn.get(), 64, 0, 0)) return false; } @@ -375,7 +365,11 @@ mimicExtensions(Security::CertPointer & cert, Security::CertPointer const &mimic // XXX: Add PublicKeyPointer. In OpenSSL, public and private keys are // internally represented by EVP_PKEY pair, but GnuTLS uses distinct types. const Security::PrivateKeyPointer certKey(X509_get_pubkey(mimicCert.get())); +#if OPENSSL_VERSION_MAJOR < 3 const auto rsaPkey = EVP_PKEY_get0_RSA(certKey.get()) != nullptr; +#else + const auto rsaPkey = EVP_PKEY_is_a(certKey.get(), "RSA") == 1; +#endif int added = 0; int nid; @@ -544,13 +538,8 @@ static bool buildCertificate(Security::CertPointer & cert, Ssl::CertificatePrope static bool generateFakeSslCertificate(Security::CertPointer & certToStore, Security::PrivateKeyPointer & pkeyToStore, Ssl::CertificateProperties const &properties, Ssl::BIGNUM_Pointer const &serial) { - Security::PrivateKeyPointer pkey; // Use signing certificates private key as generated certificate private key - if (properties.signWithPkey.get()) - pkey.resetAndLock(properties.signWithPkey.get()); - else // if not exist generate one - pkey.resetWithoutLocking(Ssl::createSslPrivateKey()); - + const auto pkey = properties.signWithPkey ? properties.signWithPkey : CreateRsaPrivateKey(); if (!pkey) return false; diff --git a/src/ssl/gadgets.h b/src/ssl/gadgets.h index 8e46f89920..4c5b30bd55 100644 --- a/src/ssl/gadgets.h +++ b/src/ssl/gadgets.h @@ -58,7 +58,7 @@ typedef std::unique_ptr> TXT_DB_Poi typedef std::unique_ptr> X509_NAME_Pointer; -typedef std::unique_ptr> RSA_Pointer; +using EVP_PKEY_CTX_Pointer = std::unique_ptr>; typedef std::unique_ptr> X509_REQ_Pointer; @@ -72,12 +72,6 @@ typedef std::unique_ptr> X509_EXTENSION_Pointer; typedef std::unique_ptr> X509_STORE_CTX_Pointer; -/** - \ingroup SslCrtdSslAPI - * Create 1024 bits rsa key. - */ -EVP_PKEY * createSslPrivateKey(); - /** \ingroup SslCrtdSslAPI * Write private key and SSL certificate to memory. diff --git a/src/ssl/support.cc b/src/ssl/support.cc index 11ef077eb5..2cfb8b3ba8 100644 --- a/src/ssl/support.cc +++ b/src/ssl/support.cc @@ -557,7 +557,11 @@ Ssl::VerifyCallbackParameters::At(Security::Connection &sconn) } // "dup" function for SSL_get_ex_new_index("cert_err_check") -#if SQUID_USE_CONST_CRYPTO_EX_DATA_DUP +#if OPENSSL_VERSION_MAJOR >= 3 +static int +ssl_dupAclChecklist(CRYPTO_EX_DATA *, const CRYPTO_EX_DATA *, void **, + int, long, void *) +#elif SQUID_USE_CONST_CRYPTO_EX_DATA_DUP static int ssl_dupAclChecklist(CRYPTO_EX_DATA *, const CRYPTO_EX_DATA *, void *, int, long, void *) @@ -654,8 +658,12 @@ Ssl::Initialize(void) SQUID_OPENSSL_init_ssl(); -#if !defined(OPENSSL_NO_ENGINE) if (::Config.SSL.ssl_engine) { +#if OPENSSL_VERSION_MAJOR < 3 + debugs(83, DBG_PARSE_NOTE(DBG_IMPORTANT), "WARNING: Support for ssl_engine is deprecated " << + "in Squids built with OpenSSL v1 (like this Squid). " << + "It is removed in Squids built with OpenSSL v3+."); +#if !defined(OPENSSL_NO_ENGINE) ENGINE_load_builtin_engines(); ENGINE *e; if (!(e = ENGINE_by_id(::Config.SSL.ssl_engine))) @@ -665,11 +673,14 @@ Ssl::Initialize(void) const auto ssl_error = ERR_get_error(); fatalf("Failed to initialise SSL engine: %s\n", Security::ErrorString(ssl_error)); } - } -#else - if (::Config.SSL.ssl_engine) - fatalf("Your OpenSSL has no SSL engine support\n"); +#else /* OPENSSL_NO_ENGINE */ + throw TextException("Cannot use ssl_engine in Squid built with OpenSSL configured to disable SSL engine support", Here()); +#endif + +#else /* OPENSSL_VERSION_MAJOR */ + throw TextException("Cannot use ssl_engine in Squid built with OpenSSL v3+", Here()); #endif + } const char *defName = ::Config.SSL.certSignHash ? ::Config.SSL.certSignHash : SQUID_SSL_SIGN_HASH_IF_NONE; Ssl::DefaultSignHash = EVP_get_digestbyname(defName);