From c288d560c5b24e021b7f313d61f258dba37dc04e Mon Sep 17 00:00:00 2001 From: Daniel Gustafsson Date: Fri, 5 Apr 2024 14:43:09 +0200 Subject: [PATCH v4] Remove support for OpenSSL 1.0.2 This makes OpenSSL 1.1.1/LibreSSL 3.3.2 the minimally required versions. Also adjust to past tense in documentation Author: Daniel Gustafsson Reviewed-by: Jacob Champion Reviewed-by: Michael Paquier --- config/programs.m4 | 25 +++ configure | 75 +++++---- configure.ac | 20 +-- contrib/pgcrypto/openssl.c | 8 - doc/src/sgml/installation.sgml | 2 +- doc/src/sgml/libpq.sgml | 6 +- meson.build | 45 +++--- src/backend/libpq/be-secure-openssl.c | 33 ++-- src/common/Makefile | 3 +- src/common/hmac_openssl.c | 34 +--- src/common/meson.build | 1 - src/common/protocol_openssl.c | 117 -------------- src/include/common/openssl.h | 14 +- src/include/pg_config.h.in | 3 - src/interfaces/libpq/fe-secure-openssl.c | 197 ----------------------- src/interfaces/libpq/libpq-int.h | 5 - src/port/pg_strong_random.c | 6 +- 17 files changed, 133 insertions(+), 461 deletions(-) delete mode 100644 src/common/protocol_openssl.c diff --git a/config/programs.m4 b/config/programs.m4 index 490ec9fe9f..230ec21cd7 100644 --- a/config/programs.m4 +++ b/config/programs.m4 @@ -143,6 +143,31 @@ if test "$pgac_cv_ldap_safe" != yes; then fi]) +# PGAC_CHECK_OPENSSL +# ------------------ +# Check for OpenSSL being at least version 1.1.1 and LibreSSL being at least +# version 3.3.2 (which shipped in OpenBSD 6.9). The actual version number +# found is not recorded, instead we gate functionality based on capabilities to +# avoid having to check multiple version numbers in the code. +AC_DEFUN([PGAC_CHECK_OPENSSL], +[AC_CACHE_CHECK([for compatible OpenSSL installation], [pgac_cv_openssl_safe], +[AC_COMPILE_IFELSE([AC_LANG_PROGRAM( +[#include +#if ((OPENSSL_VERSION_NUMBER == 0x20000000) && \ + (defined(LIBRESSL_VERSION_NUMBER) && \ + LIBRESSL_VERSION_NUMBER < 0x3030200fL)) +choke me +#endif +#if (OPENSSL_VERSION_NUMBER < 0x10101000L) +choke me +#endif], [])], +[pgac_cv_openssl_safe=yes], +[pgac_cv_openssl_safe=no])]) + +if test "$pgac_cv_openssl_safe" != yes; then + AC_MSG_ERROR([OpenSSL 1.1.1 or later is required.]) +fi]) + # PGAC_CHECK_READLINE # ------------------- diff --git a/configure b/configure index 36feeafbb2..32b0f1bc6d 100755 --- a/configure +++ b/configure @@ -12327,9 +12327,10 @@ if test "$with_openssl" = yes ; then fi if test "$with_ssl" = openssl ; then - # Minimum required OpenSSL version is 1.0.2 + # Minimum required OpenSSL version is 1.1.1, but we set 1.1.0 as the deprecation + # level since 1.1.1 wasn't defined as a deprecation point by OpenSSL -$as_echo "#define OPENSSL_API_COMPAT 0x10002000L" >>confdefs.h +$as_echo "#define OPENSSL_API_COMPAT 0x10100000L" >>confdefs.h if test "$PORTNAME" != "win32"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CRYPTO_new_ex_data in -lcrypto" >&5 @@ -12544,50 +12545,58 @@ else fi fi - # Function introduced in OpenSSL 1.0.2, not in LibreSSL. - for ac_func in SSL_CTX_set_cert_cb -do : - ac_fn_c_check_func "$LINENO" "SSL_CTX_set_cert_cb" "ac_cv_func_SSL_CTX_set_cert_cb" -if test "x$ac_cv_func_SSL_CTX_set_cert_cb" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_SSL_CTX_SET_CERT_CB 1 -_ACEOF -fi -done + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for compatible OpenSSL installation" >&5 +$as_echo_n "checking for compatible OpenSSL installation... " >&6; } +if ${pgac_cv_openssl_safe+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#if ((OPENSSL_VERSION_NUMBER == 0x20000000) && \ + (defined(LIBRESSL_VERSION_NUMBER) && \ + LIBRESSL_VERSION_NUMBER < 0x3030200fL)) +choke me +#endif +#if (OPENSSL_VERSION_NUMBER < 0x10101000L) +choke me +#endif +int +main () +{ - # Functions introduced in OpenSSL 1.1.0. We used to check for - # OPENSSL_VERSION_NUMBER, but that didn't work with 1.1.0, because LibreSSL - # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it - # doesn't have these OpenSSL 1.1.0 functions. So check for individual - # functions. - for ac_func in OPENSSL_init_ssl BIO_meth_new ASN1_STRING_get0_data HMAC_CTX_new HMAC_CTX_free -do : - as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` -ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" -if eval test \"x\$"$as_ac_var"\" = x"yes"; then : - cat >>confdefs.h <<_ACEOF -#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 + ; + return 0; +} _ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + pgac_cv_openssl_safe=yes +else + pgac_cv_openssl_safe=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_openssl_safe" >&5 +$as_echo "$pgac_cv_openssl_safe" >&6; } +if test "$pgac_cv_openssl_safe" != yes; then + as_fn_error $? "OpenSSL 1.1.1 or later is required." "$LINENO" 5 fi -done - # OpenSSL versions before 1.1.0 required setting callback functions, for - # thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock() - # function was removed. - for ac_func in CRYPTO_lock + # Function introduced in OpenSSL 1.0.2, not in LibreSSL. + for ac_func in SSL_CTX_set_cert_cb do : - ac_fn_c_check_func "$LINENO" "CRYPTO_lock" "ac_cv_func_CRYPTO_lock" -if test "x$ac_cv_func_CRYPTO_lock" = xyes; then : + ac_fn_c_check_func "$LINENO" "SSL_CTX_set_cert_cb" "ac_cv_func_SSL_CTX_set_cert_cb" +if test "x$ac_cv_func_SSL_CTX_set_cert_cb" = xyes; then : cat >>confdefs.h <<_ACEOF -#define HAVE_CRYPTO_LOCK 1 +#define HAVE_SSL_CTX_SET_CERT_CB 1 _ACEOF fi done - # Function introduced in OpenSSL 1.1.1. + # Function introduced in OpenSSL 1.1.1, not in LibreSSL. for ac_func in X509_get_signature_info do : ac_fn_c_check_func "$LINENO" "X509_get_signature_info" "ac_cv_func_X509_get_signature_info" diff --git a/configure.ac b/configure.ac index 57f734879e..b1e8d7f696 100644 --- a/configure.ac +++ b/configure.ac @@ -1335,8 +1335,9 @@ fi if test "$with_ssl" = openssl ; then dnl Order matters! - # Minimum required OpenSSL version is 1.0.2 - AC_DEFINE(OPENSSL_API_COMPAT, [0x10002000L], + # Minimum required OpenSSL version is 1.1.1, but we set 1.1.0 as the deprecation + # level since 1.1.1 wasn't defined as a deprecation point by OpenSSL + AC_DEFINE(OPENSSL_API_COMPAT, [0x10100000L], [Define to the OpenSSL API version in use. This avoids deprecation warnings from newer OpenSSL versions.]) if test "$PORTNAME" != "win32"; then AC_CHECK_LIB(crypto, CRYPTO_new_ex_data, [], [AC_MSG_ERROR([library 'crypto' is required for OpenSSL])]) @@ -1345,19 +1346,12 @@ if test "$with_ssl" = openssl ; then AC_SEARCH_LIBS(CRYPTO_new_ex_data, [eay32 crypto], [], [AC_MSG_ERROR([library 'eay32' or 'crypto' is required for OpenSSL])]) AC_SEARCH_LIBS(SSL_new, [ssleay32 ssl], [], [AC_MSG_ERROR([library 'ssleay32' or 'ssl' is required for OpenSSL])]) fi + + PGAC_CHECK_OPENSSL + # Function introduced in OpenSSL 1.0.2, not in LibreSSL. AC_CHECK_FUNCS([SSL_CTX_set_cert_cb]) - # Functions introduced in OpenSSL 1.1.0. We used to check for - # OPENSSL_VERSION_NUMBER, but that didn't work with 1.1.0, because LibreSSL - # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it - # doesn't have these OpenSSL 1.1.0 functions. So check for individual - # functions. - AC_CHECK_FUNCS([OPENSSL_init_ssl BIO_meth_new ASN1_STRING_get0_data HMAC_CTX_new HMAC_CTX_free]) - # OpenSSL versions before 1.1.0 required setting callback functions, for - # thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock() - # function was removed. - AC_CHECK_FUNCS([CRYPTO_lock]) - # Function introduced in OpenSSL 1.1.1. + # Function introduced in OpenSSL 1.1.1, not in LibreSSL. AC_CHECK_FUNCS([X509_get_signature_info]) AC_DEFINE([USE_OPENSSL], 1, [Define to 1 to build with OpenSSL support. (--with-ssl=openssl)]) elif test "$with_ssl" != no ; then diff --git a/contrib/pgcrypto/openssl.c b/contrib/pgcrypto/openssl.c index 8259de5e39..26454bc3e2 100644 --- a/contrib/pgcrypto/openssl.c +++ b/contrib/pgcrypto/openssl.c @@ -154,8 +154,6 @@ digest_free(PX_MD *h) pfree(h); } -static int px_openssl_initialized = 0; - /* PUBLIC functions */ int @@ -166,12 +164,6 @@ px_find_digest(const char *name, PX_MD **res) PX_MD *h; OSSLDigest *digest; - if (!px_openssl_initialized) - { - px_openssl_initialized = 1; - OpenSSL_add_all_algorithms(); - } - md = EVP_get_digestbyname(name); if (md == NULL) return PXE_NO_HASH; diff --git a/doc/src/sgml/installation.sgml b/doc/src/sgml/installation.sgml index a453f804cd..1d5578d935 100644 --- a/doc/src/sgml/installation.sgml +++ b/doc/src/sgml/installation.sgml @@ -293,7 +293,7 @@ encrypted client connections. OpenSSL is also required for random number generation on platforms that do not have /dev/urandom (except Windows). The minimum - required version is 1.0.2. + required version is 1.1.1. diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml index e69feacfe6..8987ca5d65 100644 --- a/doc/src/sgml/libpq.sgml +++ b/doc/src/sgml/libpq.sgml @@ -1779,11 +1779,11 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname SSL compression is nowadays considered insecure and its use is no - longer recommended. OpenSSL 1.1.0 disables + longer recommended. OpenSSL 1.1.0 disabled compression by default, and many operating system distributions - disable it in prior versions as well, so setting this parameter to on + disabled it in prior versions as well, so setting this parameter to on will not have any effect if the server does not accept compression. - PostgreSQL 14 disables compression + PostgreSQL 14 disabled compression completely in the backend. diff --git a/meson.build b/meson.build index 87437960bc..6fc1417bba 100644 --- a/meson.build +++ b/meson.build @@ -1268,6 +1268,28 @@ if sslopt in ['auto', 'openssl'] endif if ssl.found() + # Check for OpenSSL being at least version 1.1.1 and LibreSSL being at + # least version 3.3.2 (which shipped in OpenBSD 6.9). The actual version + # number found is not recorded, instead we gate functionality based on + # capabilities to avoid having to check multiple version numbers in the + # code. + compat_test_code = ''' +#include +#if ((OPENSSL_VERSION_NUMBER == 0x20000000) && \ + (defined(LIBRESSL_VERSION_NUMBER) && \ + LIBRESSL_VERSION_NUMBER < 0x3030200fL)) +choke me +#endif +#if (OPENSSL_VERSION_NUMBER < 0x10101000L) +choke me +#endif +''' + if not cc.compiles(compat_test_code, + name: 'OpenSSL implementation compatible', + dependencies: ssl, args: test_c_args) + error('OpenSSL 1.1.1 or later is required') + endif + check_funcs = [ ['CRYPTO_new_ex_data', {'required': true}], ['SSL_new', {'required': true}], @@ -1275,23 +1297,7 @@ if sslopt in ['auto', 'openssl'] # Function introduced in OpenSSL 1.0.2, not in LibreSSL. ['SSL_CTX_set_cert_cb'], - # Functions introduced in OpenSSL 1.1.0. We used to check for - # OPENSSL_VERSION_NUMBER, but that didn't work with 1.1.0, because LibreSSL - # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it - # doesn't have these OpenSSL 1.1.0 functions. So check for individual - # functions. - ['OPENSSL_init_ssl'], - ['BIO_meth_new'], - ['ASN1_STRING_get0_data'], - ['HMAC_CTX_new'], - ['HMAC_CTX_free'], - - # OpenSSL versions before 1.1.0 required setting callback functions, for - # thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock() - # function was removed. - ['CRYPTO_lock'], - - # Function introduced in OpenSSL 1.1.1 + # Function introduced in OpenSSL 1.1.1, not in LibreSSL ['X509_get_signature_info'], ] @@ -1314,7 +1320,10 @@ if sslopt in ['auto', 'openssl'] if are_openssl_funcs_complete cdata.set('USE_OPENSSL', 1, description: 'Define to 1 to build with OpenSSL support. (-Dssl=openssl)') - cdata.set('OPENSSL_API_COMPAT', '0x10002000L', + # Minimum required OpenSSL version is 1.1.1, but we set 1.1.0 as the + # deprecation level since 1.1.1 wasn't defined as a deprecation point by + # OpenSSL + cdata.set('OPENSSL_API_COMPAT', '0x10100000L', description: 'Define to the OpenSSL API version in use. This avoids deprecation warnings from newer OpenSSL versions.') ssl_library = 'openssl' else diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c index 72e43af353..0acf4758e4 100644 --- a/src/backend/libpq/be-secure-openssl.c +++ b/src/backend/libpq/be-secure-openssl.c @@ -44,6 +44,7 @@ * include , but some other Windows headers do.) */ #include "common/openssl.h" +#include #include #include #ifndef OPENSSL_NO_ECDH @@ -98,13 +99,7 @@ be_tls_init(bool isServerStart) /* This stuff need be done only once. */ if (!SSL_initialized) { -#ifdef HAVE_OPENSSL_INIT_SSL OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL); -#else - OPENSSL_config(NULL); - SSL_library_init(); - SSL_load_error_strings(); -#endif SSL_initialized = true; } @@ -261,15 +256,20 @@ be_tls_init(bool isServerStart) /* disallow SSL compression */ SSL_CTX_set_options(context, SSL_OP_NO_COMPRESSION); -#ifdef SSL_OP_NO_RENEGOTIATION - /* - * Disallow SSL renegotiation, option available since 1.1.0h. This - * concerns only TLSv1.2 and older protocol versions, as TLSv1.3 has no - * support for renegotiation. + * Disallow SSL renegotiation. This concerns only TLSv1.2 and older + * protocol versions, as TLSv1.3 has no support for renegotiation. + * SSL_OP_NO_RENEGOTIATION is available in OpenSSL since 1.1.0h (via a + * backport from 1.1.1). SSL_OP_NO_CLIENT_RENEGOTIATION is available in + * LibreSSL since 2.5.1 disallowing all client-initiated renegotiation + * (this is usually on by default). */ +#ifdef SSL_OP_NO_RENEGOTIATION SSL_CTX_set_options(context, SSL_OP_NO_RENEGOTIATION); #endif +#ifdef SSL_OP_NO_CLIENT_RENEGOTIATION + SSL_CTX_set_options(context, SSL_OP_NO_CLIENT_RENEGOTIATION); +#endif /* set up ephemeral DH and ECDH keys */ if (!initialize_dh(context, isServerStart)) @@ -533,6 +533,8 @@ aloop: case SSL_R_TLSV1_ALERT_PROTOCOL_VERSION: #ifdef SSL_R_VERSION_TOO_HIGH case SSL_R_VERSION_TOO_HIGH: +#endif +#ifdef SSL_R_VERSION_TOO_LOW case SSL_R_VERSION_TOO_LOW: #endif give_proto_hint = true; @@ -898,7 +900,6 @@ my_BIO_s_socket(void) if (!my_bio_methods) { BIO_METHOD *biom = (BIO_METHOD *) BIO_s_socket(); -#ifdef HAVE_BIO_METH_NEW int my_bio_index; my_bio_index = BIO_get_new_index(); @@ -921,14 +922,6 @@ my_BIO_s_socket(void) my_bio_methods = NULL; return NULL; } -#else - my_bio_methods = malloc(sizeof(BIO_METHOD)); - if (!my_bio_methods) - return NULL; - memcpy(my_bio_methods, biom, sizeof(BIO_METHOD)); - my_bio_methods->bread = my_sock_read; - my_bio_methods->bwrite = my_sock_write; -#endif } return my_bio_methods; } diff --git a/src/common/Makefile b/src/common/Makefile index 3d83299432..fdc33ed6d4 100644 --- a/src/common/Makefile +++ b/src/common/Makefile @@ -88,8 +88,7 @@ OBJS_COMMON = \ ifeq ($(with_ssl),openssl) OBJS_COMMON += \ cryptohash_openssl.o \ - hmac_openssl.o \ - protocol_openssl.o + hmac_openssl.o else OBJS_COMMON += \ cryptohash.o \ diff --git a/src/common/hmac_openssl.c b/src/common/hmac_openssl.c index 84fcf340d8..c2506de7c5 100644 --- a/src/common/hmac_openssl.c +++ b/src/common/hmac_openssl.c @@ -35,17 +35,11 @@ /* * In backend, use an allocation in TopMemoryContext to count for resowner - * cleanup handling if necessary. For versions of OpenSSL where HMAC_CTX is - * known, just use palloc(). In frontend, use malloc to be able to return + * cleanup handling if necessary. In frontend, use malloc to be able to return * a failure status back to the caller. */ #ifndef FRONTEND -#ifdef HAVE_HMAC_CTX_NEW -#define USE_RESOWNER_FOR_HMAC #define ALLOC(size) MemoryContextAlloc(TopMemoryContext, size) -#else -#define ALLOC(size) palloc(size) -#endif #define FREE(ptr) pfree(ptr) #else /* FRONTEND */ #define ALLOC(size) malloc(size) @@ -68,13 +62,13 @@ struct pg_hmac_ctx pg_hmac_errno error; const char *errreason; -#ifdef USE_RESOWNER_FOR_HMAC +#ifndef FRONTEND ResourceOwner resowner; #endif }; /* ResourceOwner callbacks to hold HMAC contexts */ -#ifdef USE_RESOWNER_FOR_HMAC +#ifndef FRONTEND static void ResOwnerReleaseHMAC(Datum res); static const ResourceOwnerDesc hmac_resowner_desc = @@ -139,16 +133,11 @@ pg_hmac_create(pg_cryptohash_type type) * previous runs. */ ERR_clear_error(); - -#ifdef USE_RESOWNER_FOR_HMAC +#ifndef FRONTEND ResourceOwnerEnlarge(CurrentResourceOwner); #endif -#ifdef HAVE_HMAC_CTX_NEW ctx->hmacctx = HMAC_CTX_new(); -#else - ctx->hmacctx = ALLOC(sizeof(HMAC_CTX)); -#endif if (ctx->hmacctx == NULL) { @@ -162,11 +151,8 @@ pg_hmac_create(pg_cryptohash_type type) return NULL; } -#ifndef HAVE_HMAC_CTX_NEW - memset(ctx->hmacctx, 0, sizeof(HMAC_CTX)); -#endif -#ifdef USE_RESOWNER_FOR_HMAC +#ifndef FRONTEND ctx->resowner = CurrentResourceOwner; ResourceOwnerRememberHMAC(CurrentResourceOwner, ctx); #endif @@ -328,14 +314,8 @@ pg_hmac_free(pg_hmac_ctx *ctx) if (ctx == NULL) return; -#ifdef HAVE_HMAC_CTX_FREE HMAC_CTX_free(ctx->hmacctx); -#else - explicit_bzero(ctx->hmacctx, sizeof(HMAC_CTX)); - FREE(ctx->hmacctx); -#endif - -#ifdef USE_RESOWNER_FOR_HMAC +#ifndef FRONTEND if (ctx->resowner) ResourceOwnerForgetHMAC(ctx->resowner, ctx); #endif @@ -379,7 +359,7 @@ pg_hmac_error(pg_hmac_ctx *ctx) /* ResourceOwner callbacks */ -#ifdef USE_RESOWNER_FOR_HMAC +#ifndef FRONTEND static void ResOwnerReleaseHMAC(Datum res) { diff --git a/src/common/meson.build b/src/common/meson.build index de68e408fa..8cbc46ab81 100644 --- a/src/common/meson.build +++ b/src/common/meson.build @@ -44,7 +44,6 @@ if ssl.found() common_sources += files( 'cryptohash_openssl.c', 'hmac_openssl.c', - 'protocol_openssl.c', ) else common_sources += files( diff --git a/src/common/protocol_openssl.c b/src/common/protocol_openssl.c deleted file mode 100644 index ae378685e1..0000000000 --- a/src/common/protocol_openssl.c +++ /dev/null @@ -1,117 +0,0 @@ -/*------------------------------------------------------------------------- - * - * protocol_openssl.c - * OpenSSL functionality shared between frontend and backend - * - * This should only be used if code is compiled with OpenSSL support. - * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group - * Portions Copyright (c) 1994, Regents of the University of California - * - * IDENTIFICATION - * src/common/protocol_openssl.c - * - *------------------------------------------------------------------------- - */ - -#ifndef FRONTEND -#include "postgres.h" -#else -#include "postgres_fe.h" -#endif - -#include "common/openssl.h" - -/* - * Replacements for APIs introduced in OpenSSL 1.1.0. - */ -#ifndef SSL_CTX_set_min_proto_version - -/* - * OpenSSL versions that support TLS 1.3 shouldn't get here because they - * already have these functions. So we don't have to keep updating the below - * code for every new TLS version, and eventually it can go away. But let's - * just check this to make sure ... - */ -#ifdef TLS1_3_VERSION -#error OpenSSL version mismatch -#endif - -int -SSL_CTX_set_min_proto_version(SSL_CTX *ctx, int version) -{ - int ssl_options = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3; - - if (version > TLS1_VERSION) - ssl_options |= SSL_OP_NO_TLSv1; - - /* - * Some OpenSSL versions define TLS*_VERSION macros but not the - * corresponding SSL_OP_NO_* macro, so in those cases we have to return - * unsuccessfully here. - */ -#ifdef TLS1_1_VERSION - if (version > TLS1_1_VERSION) - { -#ifdef SSL_OP_NO_TLSv1_1 - ssl_options |= SSL_OP_NO_TLSv1_1; -#else - return 0; -#endif - } -#endif -#ifdef TLS1_2_VERSION - if (version > TLS1_2_VERSION) - { -#ifdef SSL_OP_NO_TLSv1_2 - ssl_options |= SSL_OP_NO_TLSv1_2; -#else - return 0; -#endif - } -#endif - - SSL_CTX_set_options(ctx, ssl_options); - - return 1; /* success */ -} - -int -SSL_CTX_set_max_proto_version(SSL_CTX *ctx, int version) -{ - int ssl_options = 0; - - Assert(version != 0); - - /* - * Some OpenSSL versions define TLS*_VERSION macros but not the - * corresponding SSL_OP_NO_* macro, so in those cases we have to return - * unsuccessfully here. - */ -#ifdef TLS1_1_VERSION - if (version < TLS1_1_VERSION) - { -#ifdef SSL_OP_NO_TLSv1_1 - ssl_options |= SSL_OP_NO_TLSv1_1; -#else - return 0; -#endif - } -#endif -#ifdef TLS1_2_VERSION - if (version < TLS1_2_VERSION) - { -#ifdef SSL_OP_NO_TLSv1_2 - ssl_options |= SSL_OP_NO_TLSv1_2; -#else - return 0; -#endif - } -#endif - - SSL_CTX_set_options(ctx, ssl_options); - - return 1; /* success */ -} - -#endif /* !SSL_CTX_set_min_proto_version */ diff --git a/src/include/common/openssl.h b/src/include/common/openssl.h index 964d691d32..cc54604e6e 100644 --- a/src/include/common/openssl.h +++ b/src/include/common/openssl.h @@ -18,10 +18,10 @@ #include /* - * OpenSSL doesn't provide any very nice way to identify the min/max - * protocol versions the library supports, so we fake it as best we can. - * Note in particular that this doesn't account for restrictions that - * might be specified in the installation's openssl.cnf. + * LibreSSL doesn't provide any very nice way to identify the max protocol + * versions the library supports, analogous to TLS_MAX_VERSION in OpenSSL, so + * we define our own. Note in particular that this doesn't account for + * restrictions that might be specified in the installation's openssl.cnf. * * We disable SSLv3 and older in library setup, so TLSv1 is the oldest * protocol version of interest. @@ -38,12 +38,6 @@ #define MAX_OPENSSL_TLS_VERSION "TLSv1" #endif -/* src/common/protocol_openssl.c */ -#ifndef SSL_CTX_set_min_proto_version -extern int SSL_CTX_set_min_proto_version(SSL_CTX *ctx, int version); -extern int SSL_CTX_set_max_proto_version(SSL_CTX *ctx, int version); -#endif - #endif /* USE_OPENSSL */ #endif /* COMMON_OPENSSL_H */ diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in index 591e1ca3df..27989dff25 100644 --- a/src/include/pg_config.h.in +++ b/src/include/pg_config.h.in @@ -84,9 +84,6 @@ /* Define to 1 if you have the header file. */ #undef HAVE_CRTDEFS_H -/* Define to 1 if you have the `CRYPTO_lock' function. */ -#undef HAVE_CRYPTO_LOCK - /* Define to 1 if you have the declaration of `fdatasync', and to 0 if you don't. */ #undef HAVE_DECL_FDATASYNC diff --git a/src/interfaces/libpq/fe-secure-openssl.c b/src/interfaces/libpq/fe-secure-openssl.c index 0c8c9f8dcb..96f91938ef 100644 --- a/src/interfaces/libpq/fe-secure-openssl.c +++ b/src/interfaces/libpq/fe-secure-openssl.c @@ -71,7 +71,6 @@ static int openssl_verify_peer_name_matches_certificate_name(PGconn *conn, static int openssl_verify_peer_name_matches_certificate_ip(PGconn *conn, ASN1_OCTET_STRING *addr_entry, char **store_name); -static void destroy_ssl_system(void); static int initialize_SSL(PGconn *conn); static PostgresPollingStatusType open_client_SSL(PGconn *conn); static char *SSLerrmessage(unsigned long ecode); @@ -505,11 +504,7 @@ openssl_verify_peer_name_matches_certificate_name(PGconn *conn, ASN1_STRING *nam /* * GEN_DNS can be only IA5String, equivalent to US ASCII. */ -#ifdef HAVE_ASN1_STRING_GET0_DATA namedata = ASN1_STRING_get0_data(name_entry); -#else - namedata = ASN1_STRING_data(name_entry); -#endif len = ASN1_STRING_length(name_entry); /* OK to cast from unsigned to plain char, since it's all ASCII. */ @@ -540,11 +535,7 @@ openssl_verify_peer_name_matches_certificate_ip(PGconn *conn, * GEN_IPADD is an OCTET STRING containing an IP address in network byte * order. */ -#ifdef HAVE_ASN1_STRING_GET0_DATA addrdata = ASN1_STRING_get0_data(addr_entry); -#else - addrdata = ASN1_STRING_data(addr_entry); -#endif len = ASN1_STRING_length(addr_entry); return pq_verify_peer_name_matches_certificate_ip(conn, addrdata, len, store_name); @@ -712,49 +703,6 @@ pgtls_verify_peer_name_matches_certificate_guts(PGconn *conn, return rc; } -#if defined(HAVE_CRYPTO_LOCK) -/* - * Callback functions for OpenSSL internal locking. (OpenSSL 1.1.0 - * does its own locking, and doesn't need these anymore. The - * CRYPTO_lock() function was removed in 1.1.0, when the callbacks - * were made obsolete, so we assume that if CRYPTO_lock() exists, - * the callbacks are still required.) - */ - -static unsigned long -pq_threadidcallback(void) -{ - /* - * This is not standards-compliant. pthread_self() returns pthread_t, and - * shouldn't be cast to unsigned long, but CRYPTO_set_id_callback requires - * it, so we have to do it. - */ - return (unsigned long) pthread_self(); -} - -static pthread_mutex_t *pq_lockarray; - -static void -pq_lockingcallback(int mode, int n, const char *file, int line) -{ - /* - * There's no way to report a mutex-primitive failure, so we just Assert - * in development builds, and ignore any errors otherwise. Fortunately - * this is all obsolete in modern OpenSSL. - */ - if (mode & CRYPTO_LOCK) - { - if (pthread_mutex_lock(&pq_lockarray[n])) - Assert(false); - } - else - { - if (pthread_mutex_unlock(&pq_lockarray[n])) - Assert(false); - } -} -#endif /* HAVE_CRYPTO_LOCK */ - /* * Initialize SSL library. * @@ -771,67 +719,10 @@ pgtls_init(PGconn *conn, bool do_ssl, bool do_crypto) if (pthread_mutex_lock(&ssl_config_mutex)) return -1; -#ifdef HAVE_CRYPTO_LOCK - if (pq_init_crypto_lib) - { - /* - * If necessary, set up an array to hold locks for libcrypto. - * libcrypto will tell us how big to make this array. - */ - if (pq_lockarray == NULL) - { - int i; - - pq_lockarray = malloc(sizeof(pthread_mutex_t) * CRYPTO_num_locks()); - if (!pq_lockarray) - { - pthread_mutex_unlock(&ssl_config_mutex); - return -1; - } - for (i = 0; i < CRYPTO_num_locks(); i++) - { - if (pthread_mutex_init(&pq_lockarray[i], NULL)) - { - free(pq_lockarray); - pq_lockarray = NULL; - pthread_mutex_unlock(&ssl_config_mutex); - return -1; - } - } - } - - if (do_crypto && !conn->crypto_loaded) - { - if (crypto_open_connections++ == 0) - { - /* - * These are only required for threaded libcrypto - * applications, but make sure we don't stomp on them if - * they're already set. - */ - if (CRYPTO_get_id_callback() == NULL) - CRYPTO_set_id_callback(pq_threadidcallback); - if (CRYPTO_get_locking_callback() == NULL) - CRYPTO_set_locking_callback(pq_lockingcallback); - } - - conn->crypto_loaded = true; - } - } -#endif /* HAVE_CRYPTO_LOCK */ - if (!ssl_lib_initialized && do_ssl) { if (pq_init_ssl_lib) - { -#ifdef HAVE_OPENSSL_INIT_SSL OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL); -#else - OPENSSL_config(NULL); - SSL_library_init(); - SSL_load_error_strings(); -#endif - } ssl_lib_initialized = true; } @@ -839,52 +730,6 @@ pgtls_init(PGconn *conn, bool do_ssl, bool do_crypto) return 0; } -/* - * This function is needed because if the libpq library is unloaded - * from the application, the callback functions will no longer exist when - * libcrypto is used by other parts of the system. For this reason, - * we unregister the callback functions when the last libpq - * connection is closed. (The same would apply for OpenSSL callbacks - * if we had any.) - * - * Callbacks are only set when we're compiled in threadsafe mode, so - * we only need to remove them in this case. They are also not needed - * with OpenSSL 1.1.0 anymore. - */ -static void -destroy_ssl_system(void) -{ -#if defined(HAVE_CRYPTO_LOCK) - if (pthread_mutex_lock(&ssl_config_mutex)) - return; - - if (pq_init_crypto_lib && crypto_open_connections > 0) - --crypto_open_connections; - - if (pq_init_crypto_lib && crypto_open_connections == 0) - { - /* - * No connections left, unregister libcrypto callbacks, if no one - * registered different ones in the meantime. - */ - if (CRYPTO_get_locking_callback() == pq_lockingcallback) - CRYPTO_set_locking_callback(NULL); - if (CRYPTO_get_id_callback() == pq_threadidcallback) - CRYPTO_set_id_callback(NULL); - - /* - * We don't free the lock array. If we get another connection in this - * process, we will just re-use them with the existing mutexes. - * - * This means we leak a little memory on repeated load/unload of the - * library. - */ - } - - pthread_mutex_unlock(&ssl_config_mutex); -#endif -} - /* * Create per-connection SSL object, and load the client certificate, * private key, and trusted CA certs. @@ -1596,8 +1441,6 @@ open_client_SSL(PGconn *conn) void pgtls_close(PGconn *conn) { - bool destroy_needed = false; - if (conn->ssl_in_use) { if (conn->ssl) @@ -1612,8 +1455,6 @@ pgtls_close(PGconn *conn) SSL_free(conn->ssl); conn->ssl = NULL; conn->ssl_in_use = false; - - destroy_needed = true; } if (conn->peer) @@ -1631,30 +1472,6 @@ pgtls_close(PGconn *conn) } #endif } - else - { - /* - * In the non-SSL case, just remove the crypto callbacks if the - * connection has then loaded. This code path has no dependency on - * any pending SSL calls. - */ - if (conn->crypto_loaded) - destroy_needed = true; - } - - /* - * This will remove our crypto locking hooks if this is the last - * connection using libcrypto which means we must wait to call it until - * after all the potential SSL calls have been made, otherwise we can end - * up with a race condition and possible deadlocks. - * - * See comments above destroy_ssl_system(). - */ - if (destroy_needed) - { - destroy_ssl_system(); - conn->crypto_loaded = false; - } } @@ -1895,7 +1712,6 @@ my_BIO_s_socket(void) if (!my_bio_methods) { BIO_METHOD *biom = (BIO_METHOD *) BIO_s_socket(); -#ifdef HAVE_BIO_METH_NEW int my_bio_index; my_bio_index = BIO_get_new_index(); @@ -1921,14 +1737,6 @@ my_BIO_s_socket(void) { goto err; } -#else - res = malloc(sizeof(BIO_METHOD)); - if (!res) - goto err; - memcpy(res, biom, sizeof(BIO_METHOD)); - res->bread = my_sock_read; - res->bwrite = my_sock_write; -#endif } my_bio_methods = res; @@ -1936,13 +1744,8 @@ my_BIO_s_socket(void) return res; err: -#ifdef HAVE_BIO_METH_NEW if (res) BIO_meth_free(res); -#else - if (res) - free(res); -#endif pthread_mutex_unlock(&ssl_config_mutex); return NULL; } diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h index 9c05f11a6e..d049087301 100644 --- a/src/interfaces/libpq/libpq-int.h +++ b/src/interfaces/libpq/libpq-int.h @@ -565,11 +565,6 @@ struct pg_conn void *engine; /* dummy field to keep struct the same if * OpenSSL version changes */ #endif - bool crypto_loaded; /* Track if libcrypto locking callbacks have - * been done for this connection. This can be - * removed once support for OpenSSL 1.0.2 is - * removed as this locking is handled - * internally in OpenSSL >= 1.1.0. */ #endif /* USE_OPENSSL */ #endif /* USE_SSL */ diff --git a/src/port/pg_strong_random.c b/src/port/pg_strong_random.c index 5f2b248425..5df63f99e4 100644 --- a/src/port/pg_strong_random.c +++ b/src/port/pg_strong_random.c @@ -56,9 +56,9 @@ void pg_strong_random_init(void) { /* - * Make sure processes do not share OpenSSL randomness state. This is no - * longer required in OpenSSL 1.1.1 and later versions, but until we drop - * support for version < 1.1.1 we need to do this. + * Make sure processes do not share OpenSSL randomness state. This is in + * theory no longer be required in OpenSSL 1.1.1 and later versions, but + * there is no harm in taking extra precautions. */ RAND_poll(); } -- 2.32.1 (Apple Git-133)