diff options
author | Daniel Gustafsson | 2024-09-02 11:51:48 +0000 |
---|---|---|
committer | Daniel Gustafsson | 2024-09-02 11:51:48 +0000 |
commit | a70e01d4306fdbcd5fbedb4ca97e5c21c995da60 (patch) | |
tree | 78a6e4588190fcd1568f98f28b3b38eef028c8e6 /src/interfaces | |
parent | 6ebeeae29626e742bbe16db3fa6fccf1186c0dfb (diff) |
Remove support for OpenSSL older than 1.1.0
OpenSSL 1.0.2 has been EOL from the upstream OpenSSL project for
some time, and is no longer the default OpenSSL version with any
vendor which package PostgreSQL. By retiring support for OpenSSL
1.0.2 we can remove a lot of no longer required complexity for
managing state within libcrypto which is now handled by OpenSSL.
Reviewed-by: Jacob Champion <jacob.champion@enterprisedb.com>
Reviewed-by: Peter Eisentraut <peter@eisentraut.org>
Reviewed-by: Michael Paquier <michael@paquier.xyz>
Discussion: https://postgr.es/m/ZG3JNursG69dz1lr@paquier.xyz
Discussion: https://postgr.es/m/CA+hUKGKh7QrYzu=8yWEUJvXtMVm_CNWH1L_TLWCbZMwbi1XP2Q@mail.gmail.com
Diffstat (limited to 'src/interfaces')
-rw-r--r-- | src/interfaces/libpq/fe-connect.c | 18 | ||||
-rw-r--r-- | src/interfaces/libpq/fe-secure-openssl.c | 246 | ||||
-rw-r--r-- | src/interfaces/libpq/fe-secure.c | 35 | ||||
-rw-r--r-- | src/interfaces/libpq/libpq-int.h | 23 |
4 files changed, 10 insertions, 312 deletions
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c index 4cd7281b6ed..3fa2dd864fe 100644 --- a/src/interfaces/libpq/fe-connect.c +++ b/src/interfaces/libpq/fe-connect.c @@ -3343,16 +3343,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 * ssl_in_use set. @@ -3545,14 +3535,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. */ pollres = pqsecure_open_client(conn); diff --git a/src/interfaces/libpq/fe-secure-openssl.c b/src/interfaces/libpq/fe-secure-openssl.c index b6fffd7b9b0..b5749d0292e 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 f628082337e..5567be9d39d 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 8ed1b28fcc0..9579f803538 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); @@ -797,23 +791,6 @@ extern void pq_reset_sigpipe(sigset_t *osigset, bool sigpipe_pending, */ /* - * 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. */ extern PostgresPollingStatusType pgtls_open_client(PGconn *conn); |