diff --git a/configure b/configure index 537366945c..53c8a1f2ba 100755 --- a/configure +++ b/configure @@ -12313,9 +12313,9 @@ 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.0 -$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 @@ -12547,33 +12547,20 @@ done # 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 + for ac_func in OPENSSL_init_ssl 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 : + ac_fn_c_check_func "$LINENO" "OPENSSL_init_ssl" "ac_cv_func_OPENSSL_init_ssl" +if test "x$ac_cv_func_OPENSSL_init_ssl" = xyes; then : cat >>confdefs.h <<_ACEOF -#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +#define HAVE_OPENSSL_INIT_SSL 1 _ACEOF +else + as_fn_error $? "OpenSSL version >= 1.1.0 is required for SSL support" "$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 -do : - ac_fn_c_check_func "$LINENO" "CRYPTO_lock" "ac_cv_func_CRYPTO_lock" -if test "x$ac_cv_func_CRYPTO_lock" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_CRYPTO_LOCK 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 SSL_CTX_set_num_tickets do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` diff --git a/configure.ac b/configure.ac index 4e279c4bd6..6a35b2880b 100644 --- a/configure.ac +++ b/configure.ac @@ -1314,8 +1314,8 @@ 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.0 + 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])]) @@ -1331,12 +1331,8 @@ if test "$with_ssl" = openssl ; then # 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. + AC_CHECK_FUNCS([OPENSSL_init_ssl], [], [AC_MSG_ERROR([OpenSSL version >= 1.1.0 is required for SSL support])]) + # Function introduced in OpenSSL 1.1.1, not in LibreSSL. AC_CHECK_FUNCS([X509_get_signature_info SSL_CTX_set_num_tickets]) 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 9e5a35ca3f..ff9abd4649 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.0. diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml index f916fce414..25646f6f8e 100644 --- a/doc/src/sgml/libpq.sgml +++ b/doc/src/sgml/libpq.sgml @@ -9865,9 +9865,11 @@ ldap://ldap.acme.com/cn=dbserver,cn=hosts?pgconnectinfo?base?(objectclass=*) SSL Library Initialization - If your application initializes libssl and/or - libcrypto libraries and libpq - is built with SSL support, you should call + Applications which need to be compatible with older versions of + PostgreSQL, using OpenSSL + version 1.0.2 or older, need to initialize the SSL library before using it. + Applications which initialize libssl and/or + libcrypto libraries should call to tell libpq that the libssl and/or libcrypto libraries have been initialized by your application, so that @@ -9875,6 +9877,10 @@ ldap://ldap.acme.com/cn=dbserver,cn=hosts?pgconnectinfo?base?(objectclass=*) However, this is unnecessary when using OpenSSL version 1.1.0 or later, as duplicate initializations are no longer problematic. + + Refer to the documentation for the version of PostgreSQL + that you are targeting for details on their use. + @@ -9890,21 +9896,8 @@ void PQinitOpenSSL(int do_ssl, int do_crypto); - When do_ssl is non-zero, libpq - will initialize the OpenSSL library before first - opening a database connection. When do_crypto is - non-zero, the libcrypto library will be initialized. By - default (if is not called), both libraries - are initialized. When SSL support is not compiled in, this function is - present but does nothing. - - - - If your application uses and initializes either OpenSSL - or its underlying libcrypto library, you must - call this function with zeroes for the appropriate parameter(s) - before first opening a database connection. Also be sure that you - have done that initialization before opening a database connection. + This function is deprecated and only present for backwards compatibility, + it does nothing. @@ -9921,11 +9914,14 @@ void PQinitSSL(int do_ssl); This function is equivalent to PQinitOpenSSL(do_ssl, do_ssl). - It is sufficient for applications that initialize both or neither - of OpenSSL and libcrypto. + This function is deprecated and only present for backwards compatibility, + it does nothing. + and + are maintained for backwards compatibility, but are no longer required + since PostgreSQL 18. has been present since PostgreSQL 8.0, while was added in PostgreSQL 8.4, so diff --git a/meson.build b/meson.build index ea07126f78..4764b09266 100644 --- a/meson.build +++ b/meson.build @@ -1359,26 +1359,17 @@ if sslopt in ['auto', 'openssl'] ['CRYPTO_new_ex_data', {'required': true}], ['SSL_new', {'required': true}], - # 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_init_ssl', {'required': true}], - # 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.0.2, not in LibreSSL. + ['SSL_CTX_set_cert_cb'], - # Function introduced in OpenSSL 1.1.1 + # Function introduced in OpenSSL 1.1.1, not in LibreSSL. ['X509_get_signature_info'], ['SSL_CTX_set_num_tickets'], ] @@ -1402,7 +1393,7 @@ 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', + 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 60cf5d16e7..1ebd3f2e6d 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 @@ -80,7 +81,6 @@ static const char *SSLerrmessage(unsigned long ecode); static char *X509_NAME_to_cstring(X509_NAME *name); static SSL_CTX *SSL_context = NULL; -static bool SSL_initialized = false; static bool dummy_ssl_passwd_cb_called = false; static bool ssl_is_server_start; @@ -101,19 +101,6 @@ be_tls_init(bool isServerStart) int ssl_ver_min = -1; int ssl_ver_max = -1; - /* 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; - } - /* * Create a new SSL context into which we'll load all the configuration * settings. If we fail partway through, we can avoid memory leakage by @@ -952,7 +939,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(); @@ -975,14 +961,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 89ef61c52a..d4f4b573c0 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..da2c93e32a 100644 --- a/src/common/hmac_openssl.c +++ b/src/common/hmac_openssl.c @@ -35,17 +35,12 @@ /* * 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) @@ -144,11 +139,7 @@ pg_hmac_create(pg_cryptohash_type type) 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,9 +153,6 @@ 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 ctx->resowner = CurrentResourceOwner; @@ -328,13 +316,7 @@ 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 if (ctx->resowner) ResourceOwnerForgetHMAC(ctx->resowner, ctx); diff --git a/src/common/meson.build b/src/common/meson.build index 1a564e1dce..d396e11ce9 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 979925cc2e..38006367a4 100644 --- a/src/include/pg_config.h.in +++ b/src/include/pg_config.h.in @@ -54,18 +54,12 @@ /* Define to 1 if you have the `append_history' function. */ #undef HAVE_APPEND_HISTORY -/* Define to 1 if you have the `ASN1_STRING_get0_data' function. */ -#undef HAVE_ASN1_STRING_GET0_DATA - /* Define to 1 if you have the header file. */ #undef HAVE_ATOMIC_H /* Define to 1 if you have the `backtrace_symbols' function. */ #undef HAVE_BACKTRACE_SYMBOLS -/* Define to 1 if you have the `BIO_meth_new' function. */ -#undef HAVE_BIO_METH_NEW - /* Define to 1 if your compiler handles computed gotos. */ #undef HAVE_COMPUTED_GOTO @@ -81,9 +75,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 @@ -199,12 +190,6 @@ /* Define to 1 if you have the `history_truncate_file' function. */ #undef HAVE_HISTORY_TRUNCATE_FILE -/* Define to 1 if you have the `HMAC_CTX_free' function. */ -#undef HAVE_HMAC_CTX_FREE - -/* Define to 1 if you have the `HMAC_CTX_new' function. */ -#undef HAVE_HMAC_CTX_NEW - /* Define to 1 if you have the header file. */ #undef HAVE_IFADDRS_H diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c index 4cd7281b6e..3fa2dd864f 100644 --- a/src/interfaces/libpq/fe-connect.c +++ b/src/interfaces/libpq/fe-connect.c @@ -3342,16 +3342,6 @@ keep_going: /* We will come back to here until there is #ifdef USE_SSL - /* - * Enable the libcrypto callbacks before checking if SSL needs - * to be done. This is done before sending the startup packet - * as depending on the type of authentication done, like MD5 - * or SCRAM that use cryptohashes, the callbacks would be - * required even without a SSL connection - */ - if (pqsecure_initialize(conn, false, true) < 0) - goto error_return; - /* * If SSL is enabled, start the SSL negotiation. We will come * back here after SSL encryption has been established, with @@ -3544,14 +3534,6 @@ keep_going: /* We will come back to here until there is } } - /* - * Set up global SSL state if required. The crypto state has - * already been set if libpq took care of doing that, so there - * is no need to make that happen again. - */ - if (pqsecure_initialize(conn, true, false) != 0) - goto error_return; - /* * Begin or continue the SSL negotiation process. */ diff --git a/src/interfaces/libpq/fe-secure-openssl.c b/src/interfaces/libpq/fe-secure-openssl.c index b6fffd7b9b..b5749d0292 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); @@ -83,14 +82,6 @@ static int my_sock_write(BIO *h, const char *buf, int size); static BIO_METHOD *my_BIO_s_socket(void); static int my_SSL_set_fd(PGconn *conn, int fd); - -static bool pq_init_ssl_lib = true; -static bool pq_init_crypto_lib = true; - -static bool ssl_lib_initialized = false; - -static long crypto_open_connections = 0; - static pthread_mutex_t ssl_config_mutex = PTHREAD_MUTEX_INITIALIZER; static PQsslKeyPassHook_OpenSSL_type PQsslKeyPassHook = NULL; @@ -100,20 +91,6 @@ static int ssl_protocol_version_to_openssl(const char *protocol); /* Procedures common to all secure sessions */ /* ------------------------------------------------------------ */ -void -pgtls_init_library(bool do_ssl, int do_crypto) -{ - /* - * Disallow changing the flags while we have open connections, else we'd - * get completely confused. - */ - if (crypto_open_connections != 0) - return; - - pq_init_ssl_lib = do_ssl; - pq_init_crypto_lib = do_crypto; -} - PostgresPollingStatusType pgtls_open_client(PGconn *conn) { @@ -505,11 +482,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 +513,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,179 +681,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. - * - * In threadsafe mode, this includes setting up libcrypto callback functions - * to do thread locking. - * - * If the caller has told us (through PQinitOpenSSL) that he's taking care - * of libcrypto, we expect that callbacks are already set, and won't try to - * override it. - */ -int -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; - } - - pthread_mutex_unlock(&ssl_config_mutex); - 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 -} - /* See pqcomm.h comments on OpenSSL implementation of ALPN (RFC 7301) */ static unsigned char alpn_protos[] = PG_ALPN_PROTOCOL_VECTOR; @@ -1643,8 +1439,6 @@ open_client_SSL(PGconn *conn) void pgtls_close(PGconn *conn) { - bool destroy_needed = false; - if (conn->ssl_in_use) { if (conn->ssl) @@ -1660,8 +1454,6 @@ pgtls_close(PGconn *conn) conn->ssl = NULL; conn->ssl_in_use = false; conn->ssl_handshake_started = false; - - destroy_needed = true; } if (conn->peer) @@ -1679,30 +1471,6 @@ pgtls_close(PGconn *conn) } #endif } - else - { - /* - * In the non-SSL case, just remove the crypto callbacks if the - * connection has them 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; - } } @@ -1981,7 +1749,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(); @@ -2007,14 +1774,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; @@ -2022,13 +1781,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/fe-secure.c b/src/interfaces/libpq/fe-secure.c index f628082337..5567be9d39 100644 --- a/src/interfaces/libpq/fe-secure.c +++ b/src/interfaces/libpq/fe-secure.c @@ -108,42 +108,27 @@ PQsslInUse(PGconn *conn) } /* - * Exported function to allow application to tell us it's already - * initialized OpenSSL. + * Exported function to allow application to tell us it's already initialized + * OpenSSL. Since OpenSSL 1.1.0 it is no longer required to explicitly + * initialize libssl and libcrypto, so this is a no-op. This function remains + * for backwards API compatibility. */ void PQinitSSL(int do_init) { -#ifdef USE_SSL - pgtls_init_library(do_init, do_init); -#endif + /* no-op */ } /* - * Exported function to allow application to tell us it's already - * initialized OpenSSL and/or libcrypto. + * Exported function to allow application to tell us it's already initialized + * OpenSSL. Since OpenSSL 1.1.0 it is no longer required to explicitly + * initialize libssl and libcrypto, so this is a no-op. This function remains + * for backwards API compatibility. */ void PQinitOpenSSL(int do_ssl, int do_crypto) { -#ifdef USE_SSL - pgtls_init_library(do_ssl, do_crypto); -#endif -} - -/* - * Initialize global SSL context - */ -int -pqsecure_initialize(PGconn *conn, bool do_ssl, bool do_crypto) -{ - int r = 0; - -#ifdef USE_SSL - r = pgtls_init(conn, do_ssl, do_crypto); -#endif - - return r; + /* no-op */ } /* diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h index 8ed1b28fcc..9579f80353 100644 --- a/src/interfaces/libpq/libpq-int.h +++ b/src/interfaces/libpq/libpq-int.h @@ -592,11 +592,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 */ @@ -776,7 +771,6 @@ extern int pqWriteReady(PGconn *conn); /* === in fe-secure.c === */ -extern int pqsecure_initialize(PGconn *, bool, bool); extern PostgresPollingStatusType pqsecure_open_client(PGconn *); extern void pqsecure_close(PGconn *); extern ssize_t pqsecure_read(PGconn *, void *ptr, size_t len); @@ -796,23 +790,6 @@ extern void pq_reset_sigpipe(sigset_t *osigset, bool sigpipe_pending, * The SSL implementation provides these functions. */ -/* - * Implementation of PQinitSSL(). - */ -extern void pgtls_init_library(bool do_ssl, int do_crypto); - -/* - * Initialize SSL library. - * - * The conn parameter is only used to be able to pass back an error - * message - no connection-local setup is made here. do_ssl controls - * if SSL is initialized, and do_crypto does the same for the crypto - * part. - * - * Returns 0 if OK, -1 on failure (adding a message to conn->errorMessage). - */ -extern int pgtls_init(PGconn *conn, bool do_ssl, bool do_crypto); - /* * Begin or continue negotiating a secure session. */ diff --git a/src/test/ssl/t/001_ssltests.pl b/src/test/ssl/t/001_ssltests.pl index b877327023..4bd868ff65 100644 --- a/src/test/ssl/t/001_ssltests.pl +++ b/src/test/ssl/t/001_ssltests.pl @@ -36,8 +36,7 @@ sub switch_server_cert } # Determine whether this build uses OpenSSL or LibreSSL. As a heuristic, the -# HAVE_SSL_CTX_SET_CERT_CB macro isn't defined for LibreSSL. (Nor for OpenSSL -# 1.0.1, but that's old enough that accommodating it isn't worth the cost.) +# HAVE_SSL_CTX_SET_CERT_CB macro isn't defined for LibreSSL. my $libressl = not check_pg_config("#define HAVE_SSL_CTX_SET_CERT_CB 1"); #### Some configuration