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
This commit is contained in:
Daniel Gustafsson 2024-09-02 13:51:48 +02:00
parent 6ebeeae296
commit a70e01d430
18 changed files with 53 additions and 574 deletions

31
configure vendored
View File

@ -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`

View File

@ -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

View File

@ -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;

View File

@ -293,7 +293,7 @@
encrypted client connections. <productname>OpenSSL</productname> is
also required for random number generation on platforms that do not
have <filename>/dev/urandom</filename> (except Windows). The minimum
required version is 1.0.2.
required version is 1.1.0.
</para>
</listitem>

View File

@ -9865,9 +9865,11 @@ ldap://ldap.acme.com/cn=dbserver,cn=hosts?pgconnectinfo?base?(objectclass=*)
<title>SSL Library Initialization</title>
<para>
If your application initializes <literal>libssl</literal> and/or
<literal>libcrypto</literal> libraries and <application>libpq</application>
is built with <acronym>SSL</acronym> support, you should call
Applications which need to be compatible with older versions of
<productname>PostgreSQL</productname>, using <productname>OpenSSL</productname>
version 1.0.2 or older, need to initialize the SSL library before using it.
Applications which initialize <literal>libssl</literal> and/or
<literal>libcrypto</literal> libraries should call
<xref linkend="libpq-PQinitOpenSSL"/> to tell <application>libpq</application>
that the <literal>libssl</literal> and/or <literal>libcrypto</literal> 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 <productname>OpenSSL</productname>
version 1.1.0 or later, as duplicate initializations are no longer problematic.
</para>
<para>
Refer to the documentation for the version of <productname>PostgreSQL</productname>
that you are targeting for details on their use.
</para>
<para>
<variablelist>
@ -9890,21 +9896,8 @@ void PQinitOpenSSL(int do_ssl, int do_crypto);
</para>
<para>
When <parameter>do_ssl</parameter> is non-zero, <application>libpq</application>
will initialize the <productname>OpenSSL</productname> library before first
opening a database connection. When <parameter>do_crypto</parameter> is
non-zero, the <literal>libcrypto</literal> library will be initialized. By
default (if <xref linkend="libpq-PQinitOpenSSL"/> is not called), both libraries
are initialized. When SSL support is not compiled in, this function is
present but does nothing.
</para>
<para>
If your application uses and initializes either <productname>OpenSSL</productname>
or its underlying <literal>libcrypto</literal> library, you <emphasis>must</emphasis>
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.
</para>
</listitem>
</varlistentry>
@ -9921,11 +9914,14 @@ void PQinitSSL(int do_ssl);
<para>
This function is equivalent to
<literal>PQinitOpenSSL(do_ssl, do_ssl)</literal>.
It is sufficient for applications that initialize both or neither
of <productname>OpenSSL</productname> and <literal>libcrypto</literal>.
This function is deprecated and only present for backwards compatibility,
it does nothing.
</para>
<para>
<xref linkend="libpq-PQinitSSL"/> and <xref linkend="libpq-PQinitOpenSSL"/>
are maintained for backwards compatibility, but are no longer required
since <productname>PostgreSQL</productname> 18.
<xref linkend="libpq-PQinitSSL"/> has been present since
<productname>PostgreSQL</productname> 8.0, while <xref linkend="libpq-PQinitOpenSSL"/>
was added in <productname>PostgreSQL</productname> 8.4, so <xref linkend="libpq-PQinitSSL"/>

View File

@ -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

View File

@ -44,6 +44,7 @@
* include <wincrypt.h>, but some other Windows headers do.)
*/
#include "common/openssl.h"
#include <openssl/bn.h>
#include <openssl/conf.h>
#include <openssl/dh.h>
#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;
}

View File

@ -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 \

View File

@ -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);

View File

@ -44,7 +44,6 @@ if ssl.found()
common_sources += files(
'cryptohash_openssl.c',
'hmac_openssl.c',
'protocol_openssl.c',
)
else
common_sources += files(

View File

@ -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 */

View File

@ -18,10 +18,10 @@
#include <openssl/ssl.h>
/*
* 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 */

View File

@ -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 <atomic.h> 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 <crtdefs.h> 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 <ifaddrs.h> header file. */
#undef HAVE_IFADDRS_H

View File

@ -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.
*/

View File

@ -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;
}

View File

@ -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 */
}
/*

View File

@ -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.
*/

View File

@ -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