From 629440d4164ae7815cfb1bcc4af769a4ceabd4df Mon Sep 17 00:00:00 2001 From: Remi Gacogne Date: Thu, 5 Mar 2020 10:22:17 +0100 Subject: [PATCH] Detect {Libre,Open}SSL functions availability during configure Instead of using version numbers, which is brittle, notably because LibreSSL faked the OpenSSL version numbers at some point without implementing all the newly introduced functions. --- m4/pdns_check_libcrypto.m4 | 2 +- pdns/digests.hh | 6 +++--- pdns/dnsdistdist/libssl.cc | 9 +++++---- pdns/dnsdistdist/m4/dnsdist_with_libssl.m4 | 2 +- pdns/dnssecinfra.cc | 2 +- pdns/opensslsigners.cc | 6 +++--- 6 files changed, 14 insertions(+), 13 deletions(-) diff --git a/m4/pdns_check_libcrypto.m4 b/m4/pdns_check_libcrypto.m4 index c71c98acc8..789f294164 100644 --- a/m4/pdns_check_libcrypto.m4 +++ b/m4/pdns_check_libcrypto.m4 @@ -111,7 +111,7 @@ AC_DEFUN([PDNS_CHECK_LIBCRYPTO], [ [AC_LANG_PROGRAM([#include ], [ERR_load_CRYPTO_strings()])], [ AC_MSG_RESULT([yes]) - AC_CHECK_FUNCS([RAND_bytes RAND_pseudo_bytes]) + AC_CHECK_FUNCS([RAND_bytes RAND_pseudo_bytes CRYPTO_memcmp OPENSSL_init_crypto EVP_MD_CTX_new EVP_MD_CTX_free RSA_get0_key]) $1 ], [ AC_MSG_RESULT([no]) diff --git a/pdns/digests.hh b/pdns/digests.hh index 8e32acc2d7..0f30ba8306 100644 --- a/pdns/digests.hh +++ b/pdns/digests.hh @@ -28,10 +28,10 @@ inline std::string pdns_hash(const EVP_MD * md, const std::string& input) { -#if OPENSSL_VERSION_NUMBER < 0x1010000fL - auto mdctx = std::unique_ptr(EVP_MD_CTX_create(), EVP_MD_CTX_destroy); -#else +#if defined(HAVE_EVP_MD_CTX_NEW) && defined(HAVE_EVP_MD_CTX_FREE) auto mdctx = std::unique_ptr(EVP_MD_CTX_new(), EVP_MD_CTX_free); +#else + auto mdctx = std::unique_ptr(EVP_MD_CTX_create(), EVP_MD_CTX_destroy); #endif if (!mdctx) { throw std::runtime_error(std::string(EVP_MD_name(md)) + " context initialization failed"); diff --git a/pdns/dnsdistdist/libssl.cc b/pdns/dnsdistdist/libssl.cc index 6715a6d38a..064c1b46d6 100644 --- a/pdns/dnsdistdist/libssl.cc +++ b/pdns/dnsdistdist/libssl.cc @@ -72,7 +72,7 @@ static int s_keyLogIndex{-1}; void registerOpenSSLUser() { if (s_users.fetch_add(1) == 0) { -#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL && (!defined LIBRESSL_VERSION_NUMBER || LIBRESSL_VERSION_NUMBER >= 0x2070000fL)) +#ifdef HAVE_OPENSSL_INIT_CRYPTO /* load the default configuration file (or one specified via OPENSSL_CONF), which can then be used to load engines */ OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, nullptr); @@ -333,7 +333,7 @@ std::map libssl_load_ocsp_responses(const std::vector& ctx) { -#if (OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined LIBRESSL_VERSION_NUMBER) +#ifdef HAVE_SSL_CTX_GET0_PRIVATEKEY auto pkey = SSL_CTX_get0_privatekey(ctx.get()); #else auto temp = std::unique_ptr(SSL_new(ctx.get()), SSL_free); @@ -432,8 +432,9 @@ const std::string& libssl_tls_version_to_string(LibsslTLSVersion version) bool libssl_set_min_tls_version(std::unique_ptr& ctx, LibsslTLSVersion version) { -#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL && !defined LIBRESSL_VERSION_NUMBER) - /* these functions have been introduced in 1.1.0, and the use of SSL_OP_NO_* is deprecated */ +#if defined(HAVE_SSL_CTX_SET_MIN_PROTO_VERSION) || defined(SSL_CTX_set_min_proto_version) + /* These functions have been introduced in 1.1.0, and the use of SSL_OP_NO_* is deprecated + Warning: SSL_CTX_set_min_proto_version is a function-like macro in OpenSSL */ int vers; switch(version) { case LibsslTLSVersion::TLS10: diff --git a/pdns/dnsdistdist/m4/dnsdist_with_libssl.m4 b/pdns/dnsdistdist/m4/dnsdist_with_libssl.m4 index fb6eed63b4..8706e2e2c7 100644 --- a/pdns/dnsdistdist/m4/dnsdist_with_libssl.m4 +++ b/pdns/dnsdistdist/m4/dnsdist_with_libssl.m4 @@ -17,7 +17,7 @@ AC_DEFUN([DNSDIST_WITH_LIBSSL], [ save_LIBS=$LIBS CFLAGS="$LIBSSL_CFLAGS $CFLAGS" LIBS="$LIBSSL_LIBS -lcrypto $LIBS" - AC_CHECK_FUNCS([SSL_CTX_set_ciphersuites OCSP_basic_sign SSL_CTX_set_num_tickets SSL_CTX_set_keylog_callback]) + AC_CHECK_FUNCS([SSL_CTX_set_ciphersuites OCSP_basic_sign SSL_CTX_set_num_tickets SSL_CTX_set_keylog_callback SSL_CTX_get0_privatekey SSL_CTX_set_min_proto_version]) CFLAGS=$save_CFLAGS LIBS=$save_LIBS diff --git a/pdns/dnssecinfra.cc b/pdns/dnssecinfra.cc index 0b0200c953..426bf596a0 100644 --- a/pdns/dnssecinfra.cc +++ b/pdns/dnssecinfra.cc @@ -632,7 +632,7 @@ static bool constantTimeStringEquals(const std::string& a, const std::string& b) return false; } const size_t size = a.size(); -#if OPENSSL_VERSION_NUMBER >= 0x0090819fL +#ifdef HAVE_CRYPTO_MEMCMP return CRYPTO_memcmp(a.c_str(), b.c_str(), size) == 0; #else const volatile unsigned char *_a = (const volatile unsigned char *) a.c_str(); diff --git a/pdns/opensslsigners.cc b/pdns/opensslsigners.cc index d0cc0809ee..6322db0ebd 100644 --- a/pdns/opensslsigners.cc +++ b/pdns/opensslsigners.cc @@ -38,7 +38,7 @@ #include "dnssecinfra.hh" #include "dnsseckeeper.hh" -#if (OPENSSL_VERSION_NUMBER < 0x1010000fL || defined LIBRESSL_VERSION_NUMBER) +#if (OPENSSL_VERSION_NUMBER < 0x1010000fL || (defined LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2090100fL) /* OpenSSL < 1.1.0 needs support for threading/locking in the calling application. */ static pthread_mutex_t *openssllocks; @@ -81,7 +81,7 @@ void openssl_thread_cleanup() OPENSSL_free(openssllocks); } -#if !defined(LIBRESSL_VERSION_NUMBER) || LIBRESSL_VERSION_NUMBER < 0x2070000fL +#ifndef HAVE_RSA_GET0_KEY /* those symbols are defined in LibreSSL 2.7.0+ */ /* compat helpers. These DO NOT do any of the checking that the libssl 1.1 functions do. */ static inline void RSA_get0_key(const RSA* rsakey, const BIGNUM** n, const BIGNUM** e, const BIGNUM** d) { @@ -150,7 +150,7 @@ static inline int ECDSA_SIG_set0(ECDSA_SIG* signature, BIGNUM* pr, BIGNUM* ps) { } #endif /* HAVE_LIBCRYPTO_ECDSA */ -#endif /* !defined(LIBRESSL_VERSION_NUMBER) || LIBRESSL_VERSION_NUMBER < 0x2070000fL */ +#endif /* HAVE_RSA_GET0_KEY */ #else void openssl_thread_setup() {} -- 2.47.2