public inbox for [email protected]help / color / mirror / Atom feed
[PATCH 4/9] Remove the last vestiges of Exporter from PostgresNode 25+ messages / 5 participants [nested] [flat]
* [PATCH 4/9] Remove the last vestiges of Exporter from PostgresNode @ 2021-06-01 17:49 Andrew Dunstan <[email protected]> 0 siblings, 0 replies; 25+ messages in thread From: Andrew Dunstan @ 2021-06-01 17:49 UTC (permalink / raw) Clients wanting to call get_free_port now need to do so via a qualified name: PostgresNode::get_free_port(). --- src/bin/pg_ctl/t/001_start_stop.pl | 2 +- src/test/kerberos/t/001_auth.pl | 2 +- src/test/ldap/t/001_auth.pl | 4 ++-- src/test/perl/PostgresNode.pm | 14 ++++++-------- 4 files changed, 10 insertions(+), 12 deletions(-) diff --git a/src/bin/pg_ctl/t/001_start_stop.pl b/src/bin/pg_ctl/t/001_start_stop.pl index 4bfc23b93d..1d8d6bbb70 100644 --- a/src/bin/pg_ctl/t/001_start_stop.pl +++ b/src/bin/pg_ctl/t/001_start_stop.pl @@ -25,7 +25,7 @@ command_ok([ 'pg_ctl', 'initdb', '-D', "$tempdir/data", '-o', '-N' ], 'pg_ctl initdb'); command_ok([ $ENV{PG_REGRESS}, '--config-auth', "$tempdir/data" ], 'configure authentication'); -my $node_port = get_free_port(); +my $node_port = PostgresNode::get_free_port(); open my $conf, '>>', "$tempdir/data/postgresql.conf"; print $conf "fsync = off\n"; print $conf "port = $node_port\n"; diff --git a/src/test/kerberos/t/001_auth.pl b/src/test/kerberos/t/001_auth.pl index d6191498f0..34562045cb 100644 --- a/src/test/kerberos/t/001_auth.pl +++ b/src/test/kerberos/t/001_auth.pl @@ -74,7 +74,7 @@ my $kdc_conf = "${TestLib::tmp_check}/kdc.conf"; my $krb5_cache = "${TestLib::tmp_check}/krb5cc"; my $krb5_log = "${TestLib::log_path}/krb5libs.log"; my $kdc_log = "${TestLib::log_path}/krb5kdc.log"; -my $kdc_port = get_free_port(); +my $kdc_port = PostgresNode::get_free_port(); my $kdc_datadir = "${TestLib::tmp_check}/krb5kdc"; my $kdc_pidfile = "${TestLib::tmp_check}/krb5kdc.pid"; my $keytab = "${TestLib::tmp_check}/krb5.keytab"; diff --git a/src/test/ldap/t/001_auth.pl b/src/test/ldap/t/001_auth.pl index 553041baa2..1d1282f8dc 100644 --- a/src/test/ldap/t/001_auth.pl +++ b/src/test/ldap/t/001_auth.pl @@ -58,8 +58,8 @@ my $slapd_pidfile = "${TestLib::tmp_check}/slapd.pid"; my $slapd_logfile = "${TestLib::log_path}/slapd.log"; my $ldap_conf = "${TestLib::tmp_check}/ldap.conf"; my $ldap_server = 'localhost'; -my $ldap_port = get_free_port(); -my $ldaps_port = get_free_port(); +my $ldap_port = PostgresNode::get_free_port(); +my $ldaps_port = PostgresNode::get_free_port(); my $ldap_url = "ldap://$ldap_server:$ldap_port"; my $ldaps_url = "ldaps://$ldap_server:$ldaps_port"; my $ldap_basedn = 'dc=example,dc=net'; diff --git a/src/test/perl/PostgresNode.pm b/src/test/perl/PostgresNode.pm index 2a889065ea..7ed52c83bb 100644 --- a/src/test/perl/PostgresNode.pm +++ b/src/test/perl/PostgresNode.pm @@ -69,7 +69,7 @@ PostgresNode - class representing PostgreSQL server instance $node->stop('fast'); # Find a free, unprivileged TCP port to bind some other service to - my $port = get_free_port(); + my $port = PostgresNode::get_free_port(); =head1 DESCRIPTION @@ -93,7 +93,6 @@ use warnings; use Carp; use Config; use Cwd; -use Exporter 'import'; use Fcntl qw(:mode); use File::Basename; use File::Path qw(rmtree); @@ -109,10 +108,6 @@ use TestLib (); use Time::HiRes qw(usleep); use Scalar::Util qw(blessed); -our @EXPORT = qw( - get_free_port -); - our ($use_tcp, $test_localhost, $test_pghost, $last_host_assigned, $last_port_assigned, @all_nodes, $died); @@ -1379,8 +1374,8 @@ sub installed_command =item get_free_port() Locate an unprivileged (high) TCP port that's not currently bound to -anything. This is used by new(), and is also exported for use -by test cases that need to start other, non-Postgres servers. +anything. This is used by C<new()>, and also by some test cases that need to +start other, non-Postgres servers. Ports assigned to existing PostgresNode objects are automatically excluded, even if those servers are not currently running. @@ -1388,6 +1383,9 @@ excluded, even if those servers are not currently running. XXX A port available now may become unavailable by the time we start the desired service. +Note: this is not an instance method. As it's not exported it should be +called from outside the module as C<PostgresNode::get_free_port()>. + =cut sub get_free_port -- 2.25.4 --------------2D62665F86298A3CD7493562 Content-Type: text/x-patch; charset=UTF-8; name="0005-Add-a-method-to-PostgresVersion.pm-to-produce-the-ma.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename*0="0005-Add-a-method-to-PostgresVersion.pm-to-produce-the-ma.pa"; filename*1="tch" ^ permalink raw reply [nested|flat] 25+ messages in thread
* Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~? @ 2024-04-15 05:04 Michael Paquier <[email protected]> 0 siblings, 1 reply; 25+ messages in thread From: Michael Paquier @ 2024-04-15 05:04 UTC (permalink / raw) To: Daniel Gustafsson <[email protected]>; +Cc: Peter Eisentraut <[email protected]>; Jacob Champion <[email protected]>; Thomas Munro <[email protected]>; Postgres hackers <[email protected]>; [email protected]; Tom Lane <[email protected]> On Fri, Apr 12, 2024 at 02:42:57PM +0200, Daniel Gustafsson wrote: >> On 10 Apr 2024, at 09:31, Peter Eisentraut <[email protected]> wrote: >> 2. Move to 1.1.1. I understand this has to do with the fork-safety of pg_strong_random(), and it's not an API change but a behavior change. Let's make this association clearer in the code. For example, add a version check or assertion about this into pg_strong_random() itself. > 0005 moves the fork safety init inline with calling pg_strong_random, and > removes it for everyone else. This allows 1.1.0 to be supported as we > effectively are at the 1.1.0 API level, at the cost of calls for strong random > being slower on 1.1.0. An unscientific guess based on packaged OpenSSL > versions and the EOL and ELS/LTS status of 1.1.0, is that the number of > production installs of postgres 17 using OpenSSL 1.1.0 is close to zero. It is only necessary to call RAND_poll once after forking. Wouldn't it be OK to use a static flag and use the initialization once? >> * src/port/pg_strong_random.c >> >> I would prefer to remove pg_strong_random_init() if it's no longer >> useful. I mean, if we leave it as is, and we are not removing any >> callers, then we are effectively continuing to support OpenSSL >> <1.1.1, right? > > The attached removes pg_strong_random_init and instead calls it explicitly for > 1.1.0 users by checking the OpenSSL version. > > Is the attached split in line with how you were thinking about it? If I may, 0001 looks sensible here. The bits from 0003 and 0004 could be applied before 0002, as well. --- a/src/backend/postmaster/fork_process.c +++ b/src/backend/postmaster/fork_process.c @@ -110,9 +110,6 @@ fork_process(void) close(fd); } } - - /* do post-fork initialization for random number generation */ - pg_strong_random_init(); Perhaps you intented this diff to be in 0005 rather than in 0002? With 0002 applied, only support for 1.0.2 is removed, not 1.1.0 yet. pg_strong_random(void *buf, size_t len) { int i; +#if (OPENSSL_VERSION_NUMBER <= 0x10100000L) + /* + * Make sure processes do not share OpenSSL randomness state. This is not + * requred on LibreSSL and no longer required in OpenSSL 1.1.1 and later + * versions. + */ + RAND_poll(); +#endif s/requred/required/. Rather than calling always RAND_poll(), this could use a static flag to call it only once when pg_strong_random is called for the first time. I would not mind seeing this part entirely gone with the removal of support for 1.1.0. -- Michael Attachments: [application/pgp-signature] signature.asc (833B, ../../[email protected]/2-signature.asc) download ^ permalink raw reply [nested|flat] 25+ messages in thread
* Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~? @ 2024-04-15 09:07 Daniel Gustafsson <[email protected]> parent: Michael Paquier <[email protected]> 0 siblings, 1 reply; 25+ messages in thread From: Daniel Gustafsson @ 2024-04-15 09:07 UTC (permalink / raw) To: Michael Paquier <[email protected]>; +Cc: Peter Eisentraut <[email protected]>; Jacob Champion <[email protected]>; Thomas Munro <[email protected]>; Postgres hackers <[email protected]>; [email protected]; Tom Lane <[email protected]> > On 15 Apr 2024, at 07:04, Michael Paquier <[email protected]> wrote: > On Fri, Apr 12, 2024 at 02:42:57PM +0200, Daniel Gustafsson wrote: >> Is the attached split in line with how you were thinking about it? > > If I may, 0001 looks sensible here. The bits from 0003 and 0004 could > be applied before 0002, as well. Agreed, once we are in post-freeze I think those three are mostly ready to go. > - /* do post-fork initialization for random number generation */ > - pg_strong_random_init(); > > Perhaps you intented this diff to be in 0005 rather than in 0002? > With 0002 applied, only support for 1.0.2 is removed, not 1.1.0 yet. Yes, nice catch, that was a mistake in splitting up the patch into multiple pieces, it should be in the 0005 patch for strong random. Fixed. > s/requred/required/. Fixed. > Rather than calling always RAND_poll(), this > could use a static flag to call it only once when pg_strong_random is > called for the first time. Agreed, we can good that. Fixed. > I would not mind seeing this part entirely > gone with the removal of support for 1.1.0. If we want to keep autoconf from checking versions and just check compatibility (with our code) then we will remain at 1.1.0 compatibility. The only 1.1.1 API we use is not present in LibreSSL so we can't really place a hard restriction on that. It might be that keeping it for now, and removing it later during the v18 cycle as we modernize our OpenSSL code (which I hope to find time to work on) and make use of newer 1.1.1 API:s. That way we can keep our autoconf/meson checks consistent across library checks. If we end up with no new API:s to check for by the time the last commitfest of v18 rolls around, we can revisit the decision then. -- Daniel Gustafsson Attachments: [application/octet-stream] v8-0005-Remove-pg_strong_random-initialization.patch (4.2K, ../../[email protected]/2-v8-0005-Remove-pg_strong_random-initialization.patch) download | inline diff: From fb754690b98d87115de6c7c4e6952a67db547a4a Mon Sep 17 00:00:00 2001 From: Daniel Gustafsson <[email protected]> Date: Fri, 12 Apr 2024 13:20:31 +0200 Subject: [PATCH v8 5/5] Remove pg_strong_random initialization. The random number generator in OpenSSL 1.1.1 was redesigned to provide fork safety by default, thus removing the need for calling RAND_poll after forking to ensure that two processes cannot share the same state. Since we now support 1.1.0 as the minumum version, and 1.1.1 is being increasingly phased out from production use, remove the initialization and only do it explicitly for anyone running 1.1.0. This will penalize 1.1.0 installations by doing it per call to pg_strong_random, but the number of production environments running the latest PostgreSQL combined with a very out of date OpenSSL (which never was available as LTS/ELS) is believed to be low. LibreSSL changed random number generator when forking OpenSSL and has provided fork safety since version 2.0.2. This removes the overhead of initializing the RNG for strong random which for the vast majority of users is no longer required. Discussion: https://postgr.es/m/CA+hUKGKh7QrYzu=8yWEUJvXtMVm_CNWH1L_TLWCbZMwbi1XP2Q@mail.gmail.com --- src/backend/postmaster/fork_process.c | 3 -- src/include/port.h | 1 - src/port/pg_strong_random.c | 43 ++++++++++----------------- 3 files changed, 16 insertions(+), 31 deletions(-) diff --git a/src/backend/postmaster/fork_process.c b/src/backend/postmaster/fork_process.c index 5e42a74ab5..bcff9ef661 100644 --- a/src/backend/postmaster/fork_process.c +++ b/src/backend/postmaster/fork_process.c @@ -110,9 +110,6 @@ fork_process(void) close(fd); } } - - /* do post-fork initialization for random number generation */ - pg_strong_random_init(); } else { diff --git a/src/include/port.h b/src/include/port.h index ae115d2d97..2a363764f1 100644 --- a/src/include/port.h +++ b/src/include/port.h @@ -473,7 +473,6 @@ extern char *pg_inet_net_ntop(int af, const void *src, int bits, char *dst, size_t size); /* port/pg_strong_random.c */ -extern void pg_strong_random_init(void); extern bool pg_strong_random(void *buf, size_t len); /* diff --git a/src/port/pg_strong_random.c b/src/port/pg_strong_random.c index 5f2b248425..ac78a93536 100644 --- a/src/port/pg_strong_random.c +++ b/src/port/pg_strong_random.c @@ -25,14 +25,11 @@ #include <sys/time.h> /* - * pg_strong_random & pg_strong_random_init + * pg_strong_random * * Generate requested number of random bytes. The returned bytes are * cryptographically secure, suitable for use e.g. in authentication. * - * Before pg_strong_random is called in any process, the generator must first - * be initialized by calling pg_strong_random_init(). - * * We rely on system facilities for actually generating the numbers. * We support a number of sources: * @@ -51,22 +48,26 @@ #ifdef USE_OPENSSL #include <openssl/rand.h> - -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. - */ - RAND_poll(); -} +#include <openssl/opensslv.h> bool pg_strong_random(void *buf, size_t len) { int i; +#if (OPENSSL_VERSION_NUMBER <= 0x10100000L) + static bool rand_initialized = false; + + /* + * Make sure processes do not share OpenSSL randomness state. This is not + * required on LibreSSL and no longer required in OpenSSL 1.1.1 and later + * versions. + */ + if (!rand_initialized) + { + RAND_poll(); + rand_initialized = true; + } +#endif /* * Check that OpenSSL's CSPRNG has been sufficiently seeded, and if not @@ -104,12 +105,6 @@ pg_strong_random(void *buf, size_t len) */ static HCRYPTPROV hProvider = 0; -void -pg_strong_random_init(void) -{ - /* No initialization needed on WIN32 */ -} - bool pg_strong_random(void *buf, size_t len) { @@ -143,12 +138,6 @@ pg_strong_random(void *buf, size_t len) * Without OpenSSL or Win32 support, just read /dev/urandom ourselves. */ -void -pg_strong_random_init(void) -{ - /* No initialization needed */ -} - bool pg_strong_random(void *buf, size_t len) { -- 2.39.3 (Apple Git-146) [application/octet-stream] v8-0004-Support-SSL_R_VERSION_TOO_LOW-on-LibreSSL.patch (1.2K, ../../[email protected]/3-v8-0004-Support-SSL_R_VERSION_TOO_LOW-on-LibreSSL.patch) download | inline diff: From 9e09a62f552a15bc280cf88d3ffd880175f7bdf8 Mon Sep 17 00:00:00 2001 From: Daniel Gustafsson <[email protected]> Date: Fri, 12 Apr 2024 13:12:17 +0200 Subject: [PATCH v8 4/5] Support SSL_R_VERSION_TOO_LOW on LibreSSL The SSL_R_VERSION_TOO_LOW error reason is supported in LibreSSL since LibreSSL 3.6.3, shipped in OpenSSL 7.2. Previously we only checked for SSL_R_VERSION_TOO_HIGH and then applied both under that guard since OpenSSL has only ever supported both at the same time. This breaks the check into one per reason to allow SSL_R_VERSION_TOO_LOW to work when using LibreSSL. Discussion: https://postgr.es/m/[email protected] --- src/backend/libpq/be-secure-openssl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c index efd49ffca8..59c71b15b5 100644 --- a/src/backend/libpq/be-secure-openssl.c +++ b/src/backend/libpq/be-secure-openssl.c @@ -542,6 +542,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; -- 2.39.3 (Apple Git-146) [application/octet-stream] v8-0003-Support-disallowing-SSL-renegotiation-in-LibreSSL.patch (2.0K, ../../[email protected]/4-v8-0003-Support-disallowing-SSL-renegotiation-in-LibreSSL.patch) download | inline diff: From 4c75bbe0fd09ba69b81db2d2270907f5c604ec24 Mon Sep 17 00:00:00 2001 From: Daniel Gustafsson <[email protected]> Date: Fri, 12 Apr 2024 12:44:24 +0200 Subject: [PATCH v8 3/5] Support disallowing SSL renegotiation in LibreSSL LibreSSL doesn't support the SSL_OP_NO_RENEGOTIATION macro which is used by OpenSSL, instead it has invented a similar one for client- side renegotiation: SSL_OP_NO_CLIENT_RENEGOTIATION. This has been supported since LibreSSL 2.5.1 which by now can be considered well below the minimum requirement. Discussion: https://postgr.es/m/[email protected] --- src/backend/libpq/be-secure-openssl.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c index 88153d4bda..efd49ffca8 100644 --- a/src/backend/libpq/be-secure-openssl.c +++ b/src/backend/libpq/be-secure-openssl.c @@ -262,15 +262,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)) -- 2.39.3 (Apple Git-146) [application/octet-stream] v8-0002-Remove-support-for-OpenSSL-1.0.2.patch (25.8K, ../../[email protected]/5-v8-0002-Remove-support-for-OpenSSL-1.0.2.patch) download | inline diff: From 09e807672fb9b8d3f70c522d2aaf616e2dc407d9 Mon Sep 17 00:00:00 2001 From: Daniel Gustafsson <[email protected]> Date: Fri, 12 Apr 2024 11:21:55 +0200 Subject: [PATCH v8 2/5] Remove support for OpenSSL 1.0.2 OpenSSL 1.0.2 has been EOL from upstream for some time, and is no longer the default OpenSSL version with any vendor which package PostgreSQL. By retiring support for 1.0.2 we can remove a lot of complexity from the tree which is no longer required. Reviewed-by: Jacob Champion <[email protected]> Reviewed-by: Peter Eisentraut <[email protected]> Reviewed-by: Michael Paquier <[email protected]> Discussion: https://postgr.es/m/[email protected] Discussion: https://postgr.es/m/CA+hUKGKh7QrYzu=8yWEUJvXtMVm_CNWH1L_TLWCbZMwbi1XP2Q@mail.gmail.com --- configure | 31 ++-- configure.ac | 12 +- contrib/pgcrypto/openssl.c | 8 - doc/src/sgml/installation.sgml | 2 +- meson.build | 23 +-- src/backend/libpq/be-secure-openssl.c | 16 +- src/common/Makefile | 3 +- src/common/hmac_openssl.c | 21 +-- src/common/meson.build | 1 - src/common/protocol_openssl.c | 117 -------------- src/include/common/openssl.h | 14 +- src/include/pg_config.h.in | 15 -- src/interfaces/libpq/fe-secure-openssl.c | 197 ----------------------- src/interfaces/libpq/libpq-int.h | 5 - 14 files changed, 28 insertions(+), 437 deletions(-) delete mode 100644 src/common/protocol_openssl.c diff --git a/configure b/configure index cfbd2a096f..73e76070b0 100755 --- a/configure +++ b/configure @@ -12330,9 +12330,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 @@ -12564,33 +12564,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 : - cat >>confdefs.h <<_ACEOF -#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 -_ACEOF - -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 : + 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 HAVE_CRYPTO_LOCK 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 - # 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 67e738d92b..cf85ad409e 100644 --- a/configure.ac +++ b/configure.ac @@ -1335,8 +1335,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])]) @@ -1352,12 +1352,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]) 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..e35f52a4d0 100644 --- a/doc/src/sgml/installation.sgml +++ b/doc/src/sgml/installation.sgml @@ -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> diff --git a/meson.build b/meson.build index 43fad5323c..b77dda7c2b 100644 --- a/meson.build +++ b/meson.build @@ -1272,26 +1272,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 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 + ['OPENSSL_init_ssl', {'required': true}], + + # Function introduced in OpenSSL 1.0.2, not in LibreSSL. + ['SSL_CTX_set_cert_cb'], + + # Function introduced in OpenSSL 1.1.1, not in LibreSSL ['X509_get_signature_info'], ] @@ -1314,7 +1305,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 29c9af1aab..88153d4bda 100644 --- a/src/backend/libpq/be-secure-openssl.c +++ b/src/backend/libpq/be-secure-openssl.c @@ -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 @@ -104,13 +105,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; } @@ -933,7 +928,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(); @@ -956,14 +950,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..e55b024159 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) @@ -139,16 +134,11 @@ pg_hmac_create(pg_cryptohash_type type) * previous runs. */ ERR_clear_error(); - #ifdef USE_RESOWNER_FOR_HMAC 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 +152,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 +315,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 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/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 */ diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in index f8d3e3b6b8..2b5f5cafab 100644 --- a/src/include/pg_config.h.in +++ b/src/include/pg_config.h.in @@ -54,9 +54,6 @@ /* 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 want to use atomics if available. */ #undef HAVE_ATOMICS @@ -66,9 +63,6 @@ /* 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 @@ -84,9 +78,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 @@ -198,12 +189,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 diff --git a/src/interfaces/libpq/fe-secure-openssl.c b/src/interfaces/libpq/fe-secure-openssl.c index c98cfa6084..640edebcfe 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 -} - /* See pqcomm.h comments on OpenSSL implementation of ALPN (RFC 7301) */ static unsigned char alpn_protos[] = PG_ALPN_PROTOCOL_VECTOR; @@ -1615,8 +1460,6 @@ open_client_SSL(PGconn *conn) void pgtls_close(PGconn *conn) { - bool destroy_needed = false; - if (conn->ssl_in_use) { if (conn->ssl) @@ -1632,8 +1475,6 @@ pgtls_close(PGconn *conn) conn->ssl = NULL; conn->ssl_in_use = false; conn->ssl_handshake_started = false; - - destroy_needed = true; } if (conn->peer) @@ -1651,30 +1492,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; - } } @@ -1935,7 +1752,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(); @@ -1961,14 +1777,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; @@ -1976,13 +1784,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 3691e5ee96..434d6c449f 100644 --- a/src/interfaces/libpq/libpq-int.h +++ b/src/interfaces/libpq/libpq-int.h @@ -580,11 +580,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 */ -- 2.39.3 (Apple Git-146) [application/octet-stream] v8-0001-Doc-Use-past-tense-for-things-which-happened-in-t.patch (1.6K, ../../[email protected]/6-v8-0001-Doc-Use-past-tense-for-things-which-happened-in-t.patch) download | inline diff: From 5bba79f12b32b5b9840d16971056cdd3bb7c1ab0 Mon Sep 17 00:00:00 2001 From: Daniel Gustafsson <[email protected]> Date: Fri, 12 Apr 2024 11:36:08 +0200 Subject: [PATCH v8 1/5] Doc: Use past tense for things which happened in the past The paragraph on SSL compression is largely describing events which took place many years ago, so reword with past tense. Reviewed-by: Peter Eisentraut <[email protected]> Discussion: https://postgr.es/m/[email protected] --- doc/src/sgml/libpq.sgml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml index 9199d0d2e5..0db3667fdf 100644 --- a/doc/src/sgml/libpq.sgml +++ b/doc/src/sgml/libpq.sgml @@ -1840,11 +1840,11 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname <para> SSL compression is nowadays considered insecure and its use is no - longer recommended. <productname>OpenSSL</productname> 1.1.0 disables + longer recommended. <productname>OpenSSL</productname> 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. - <productname>PostgreSQL</productname> 14 disables compression + <productname>PostgreSQL</productname> 14 disabled compression completely in the backend. </para> -- 2.39.3 (Apple Git-146) ^ permalink raw reply [nested|flat] 25+ messages in thread
* Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~? @ 2024-04-15 23:03 Michael Paquier <[email protected]> parent: Daniel Gustafsson <[email protected]> 0 siblings, 1 reply; 25+ messages in thread From: Michael Paquier @ 2024-04-15 23:03 UTC (permalink / raw) To: Daniel Gustafsson <[email protected]>; +Cc: Peter Eisentraut <[email protected]>; Jacob Champion <[email protected]>; Thomas Munro <[email protected]>; Postgres hackers <[email protected]>; [email protected]; Tom Lane <[email protected]> On Mon, Apr 15, 2024 at 11:07:05AM +0200, Daniel Gustafsson wrote: > On 15 Apr 2024, at 07:04, Michael Paquier <[email protected]> wrote: >> On Fri, Apr 12, 2024 at 02:42:57PM +0200, Daniel Gustafsson wrote: >>> Is the attached split in line with how you were thinking about it? >> >> If I may, 0001 looks sensible here. The bits from 0003 and 0004 could >> be applied before 0002, as well. > > Agreed, once we are in post-freeze I think those three are mostly > ready to go. Is there a point to wait for 0001, 0003 and 0004, though, and shouldn't these three be backpatched? 0001 is certainly OK as a doc-only change to be consistent across the board without waiting 5 more years. 0003 and 0004 are conditional and depend on if SSL_R_VERSION_TOO_LOW and SSL_OP_NO_CLIENT_RENEGOTIATION are defined at compile-time. 0003 is much more important, and note that 01e6f1a842f4 has been backpatched all the way down. 0004 is nice, still not strongly mandatory. >> Rather than calling always RAND_poll(), this >> could use a static flag to call it only once when pg_strong_random is >> called for the first time. > > Agreed, we can good that. Fixed. +#if (OPENSSL_VERSION_NUMBER <= 0x10100000L) + static bool rand_initialized = false; This does not look right. At the top of upstream's branch OpenSSL_1_1_0-stable, OPENSSL_VERSION_NUMBER is 0x101000d0L, so the initialization would be missed for any version in the 1.1.0 series except the GA one without this code being compiled, no? >> I would not mind seeing this part entirely >> gone with the removal of support for 1.1.0. > > If we want to keep autoconf from checking versions and just check compatibility > (with our code) then we will remain at 1.1.0 compatibility. The only 1.1.1 API > we use is not present in LibreSSL so we can't really place a hard restriction > on that. It might be that keeping it for now, and removing it later during the > v18 cycle as we modernize our OpenSSL code (which I hope to find time to work > on) and make use of newer 1.1.1 API:s. That way we can keep our autoconf/meson > checks consistent across library checks. If we end up with no new API:s to > check for by the time the last commitfest of v18 rolls around, we can revisit > the decision then. Okay, fine by me. -- Michael Attachments: [application/pgp-signature] signature.asc (833B, ../../[email protected]/2-signature.asc) download ^ permalink raw reply [nested|flat] 25+ messages in thread
* Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~? @ 2024-04-16 08:17 Daniel Gustafsson <[email protected]> parent: Michael Paquier <[email protected]> 0 siblings, 1 reply; 25+ messages in thread From: Daniel Gustafsson @ 2024-04-16 08:17 UTC (permalink / raw) To: Michael Paquier <[email protected]>; +Cc: Peter Eisentraut <[email protected]>; Jacob Champion <[email protected]>; Thomas Munro <[email protected]>; Postgres hackers <[email protected]>; [email protected]; Tom Lane <[email protected]> > On 16 Apr 2024, at 01:03, Michael Paquier <[email protected]> wrote: > > On Mon, Apr 15, 2024 at 11:07:05AM +0200, Daniel Gustafsson wrote: >> On 15 Apr 2024, at 07:04, Michael Paquier <[email protected]> wrote: >>> On Fri, Apr 12, 2024 at 02:42:57PM +0200, Daniel Gustafsson wrote: >>>> Is the attached split in line with how you were thinking about it? >>> >>> If I may, 0001 looks sensible here. The bits from 0003 and 0004 could >>> be applied before 0002, as well. >> >> Agreed, once we are in post-freeze I think those three are mostly >> ready to go. > > Is there a point to wait for 0001, 0003 and 0004, though, and > shouldn't these three be backpatched? 0001 is certainly OK as a > doc-only change to be consistent across the board without waiting 5 > more years. 0003 and 0004 are conditional and depend on if > SSL_R_VERSION_TOO_LOW and SSL_OP_NO_CLIENT_RENEGOTIATION are defined > at compile-time. 0003 is much more important, and note that > 01e6f1a842f4 has been backpatched all the way down. 0004 is nice, > still not strongly mandatory. I forgot (and didn't check) that we backpatched 01e6f1a842f4, with that in mind I agree that we should backpatch 0003 as well to put LibreSSL on par as much as we can. 0004 is a fix for the LibreSSL support, not adding anything new, so pushing that to master now makes sense. Unless objections are raised I'll push 0001, 0003 and 0004 shortly. 0002 and 0005 can hopefully be addressed in the July commitfest. >>> Rather than calling always RAND_poll(), this >>> could use a static flag to call it only once when pg_strong_random is >>> called for the first time. >> >> Agreed, we can good that. Fixed. > > +#if (OPENSSL_VERSION_NUMBER <= 0x10100000L) > + static bool rand_initialized = false; > > This does not look right. At the top of upstream's branch > OpenSSL_1_1_0-stable, OPENSSL_VERSION_NUMBER is 0x101000d0L, so the > initialization would be missed for any version in the 1.1.0 series > except the GA one without this code being compiled, no? Meh, I was clearly not caffeinated as that's a thinko with a typo attached to it. The check should be "< 0x10101000" to catch any version prior to 1.1.1. Fixed. -- Daniel Gustafsson Attachments: [application/octet-stream] v9-0005-Remove-pg_strong_random-initialization.patch (4.2K, ../../[email protected]/2-v9-0005-Remove-pg_strong_random-initialization.patch) download | inline diff: From 88396949018b1e66d94ec9d77f54086fb55fcaa6 Mon Sep 17 00:00:00 2001 From: Daniel Gustafsson <[email protected]> Date: Fri, 12 Apr 2024 13:20:31 +0200 Subject: [PATCH v9 5/5] Remove pg_strong_random initialization. The random number generator in OpenSSL 1.1.1 was redesigned to provide fork safety by default, thus removing the need for calling RAND_poll after forking to ensure that two processes cannot share the same state. Since we now support 1.1.0 as the minumum version, and 1.1.1 is being increasingly phased out from production use, remove the initialization and only do it explicitly for anyone running 1.1.0. This will penalize 1.1.0 installations by doing it per call to pg_strong_random, but the number of production environments running the latest PostgreSQL combined with a very out of date OpenSSL (which never was available as LTS/ELS) is believed to be low. LibreSSL changed random number generator when forking OpenSSL and has provided fork safety since version 2.0.2. This removes the overhead of initializing the RNG for strong random which for the vast majority of users is no longer required. Discussion: https://postgr.es/m/CA+hUKGKh7QrYzu=8yWEUJvXtMVm_CNWH1L_TLWCbZMwbi1XP2Q@mail.gmail.com --- src/backend/postmaster/fork_process.c | 3 -- src/include/port.h | 1 - src/port/pg_strong_random.c | 43 ++++++++++----------------- 3 files changed, 16 insertions(+), 31 deletions(-) diff --git a/src/backend/postmaster/fork_process.c b/src/backend/postmaster/fork_process.c index 5e42a74ab5..bcff9ef661 100644 --- a/src/backend/postmaster/fork_process.c +++ b/src/backend/postmaster/fork_process.c @@ -110,9 +110,6 @@ fork_process(void) close(fd); } } - - /* do post-fork initialization for random number generation */ - pg_strong_random_init(); } else { diff --git a/src/include/port.h b/src/include/port.h index ae115d2d97..2a363764f1 100644 --- a/src/include/port.h +++ b/src/include/port.h @@ -473,7 +473,6 @@ extern char *pg_inet_net_ntop(int af, const void *src, int bits, char *dst, size_t size); /* port/pg_strong_random.c */ -extern void pg_strong_random_init(void); extern bool pg_strong_random(void *buf, size_t len); /* diff --git a/src/port/pg_strong_random.c b/src/port/pg_strong_random.c index 5f2b248425..48b8671e68 100644 --- a/src/port/pg_strong_random.c +++ b/src/port/pg_strong_random.c @@ -25,14 +25,11 @@ #include <sys/time.h> /* - * pg_strong_random & pg_strong_random_init + * pg_strong_random * * Generate requested number of random bytes. The returned bytes are * cryptographically secure, suitable for use e.g. in authentication. * - * Before pg_strong_random is called in any process, the generator must first - * be initialized by calling pg_strong_random_init(). - * * We rely on system facilities for actually generating the numbers. * We support a number of sources: * @@ -51,22 +48,26 @@ #ifdef USE_OPENSSL #include <openssl/rand.h> - -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. - */ - RAND_poll(); -} +#include <openssl/opensslv.h> bool pg_strong_random(void *buf, size_t len) { int i; +#if (OPENSSL_VERSION_NUMBER < 0x10101000L) + static bool rand_initialized = false; + + /* + * Make sure processes do not share OpenSSL randomness state. This is not + * required on LibreSSL and no longer required in OpenSSL 1.1.1 and later + * versions. + */ + if (!rand_initialized) + { + RAND_poll(); + rand_initialized = true; + } +#endif /* * Check that OpenSSL's CSPRNG has been sufficiently seeded, and if not @@ -104,12 +105,6 @@ pg_strong_random(void *buf, size_t len) */ static HCRYPTPROV hProvider = 0; -void -pg_strong_random_init(void) -{ - /* No initialization needed on WIN32 */ -} - bool pg_strong_random(void *buf, size_t len) { @@ -143,12 +138,6 @@ pg_strong_random(void *buf, size_t len) * Without OpenSSL or Win32 support, just read /dev/urandom ourselves. */ -void -pg_strong_random_init(void) -{ - /* No initialization needed */ -} - bool pg_strong_random(void *buf, size_t len) { -- 2.39.3 (Apple Git-146) [application/octet-stream] v9-0004-Support-SSL_R_VERSION_TOO_LOW-on-LibreSSL.patch (1.2K, ../../[email protected]/3-v9-0004-Support-SSL_R_VERSION_TOO_LOW-on-LibreSSL.patch) download | inline diff: From db84b48ed74770bf7f67ed44475f0f52939d772d Mon Sep 17 00:00:00 2001 From: Daniel Gustafsson <[email protected]> Date: Fri, 12 Apr 2024 13:12:17 +0200 Subject: [PATCH v9 4/5] Support SSL_R_VERSION_TOO_LOW on LibreSSL The SSL_R_VERSION_TOO_LOW error reason is supported in LibreSSL since LibreSSL 3.6.3, shipped in OpenSSL 7.2. Previously we only checked for SSL_R_VERSION_TOO_HIGH and then applied both under that guard since OpenSSL has only ever supported both at the same time. This breaks the check into one per reason to allow SSL_R_VERSION_TOO_LOW to work when using LibreSSL. Discussion: https://postgr.es/m/[email protected] --- src/backend/libpq/be-secure-openssl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c index efd49ffca8..59c71b15b5 100644 --- a/src/backend/libpq/be-secure-openssl.c +++ b/src/backend/libpq/be-secure-openssl.c @@ -542,6 +542,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; -- 2.39.3 (Apple Git-146) [application/octet-stream] v9-0003-Support-disallowing-SSL-renegotiation-in-LibreSSL.patch (2.0K, ../../[email protected]/4-v9-0003-Support-disallowing-SSL-renegotiation-in-LibreSSL.patch) download | inline diff: From bf0c8974bbb8ae31c1379b99e4cfc17cf357599c Mon Sep 17 00:00:00 2001 From: Daniel Gustafsson <[email protected]> Date: Fri, 12 Apr 2024 12:44:24 +0200 Subject: [PATCH v9 3/5] Support disallowing SSL renegotiation in LibreSSL LibreSSL doesn't support the SSL_OP_NO_RENEGOTIATION macro which is used by OpenSSL, instead it has invented a similar one for client- side renegotiation: SSL_OP_NO_CLIENT_RENEGOTIATION. This has been supported since LibreSSL 2.5.1 which by now can be considered well below the minimum requirement. Discussion: https://postgr.es/m/[email protected] --- src/backend/libpq/be-secure-openssl.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c index 88153d4bda..efd49ffca8 100644 --- a/src/backend/libpq/be-secure-openssl.c +++ b/src/backend/libpq/be-secure-openssl.c @@ -262,15 +262,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)) -- 2.39.3 (Apple Git-146) [application/octet-stream] v9-0002-Remove-support-for-OpenSSL-1.0.2.patch (25.8K, ../../[email protected]/5-v9-0002-Remove-support-for-OpenSSL-1.0.2.patch) download | inline diff: From d68e4cab94e49e7567093b08ab3dc52f961ec76d Mon Sep 17 00:00:00 2001 From: Daniel Gustafsson <[email protected]> Date: Fri, 12 Apr 2024 11:21:55 +0200 Subject: [PATCH v9 2/5] Remove support for OpenSSL 1.0.2 OpenSSL 1.0.2 has been EOL from upstream for some time, and is no longer the default OpenSSL version with any vendor which package PostgreSQL. By retiring support for 1.0.2 we can remove a lot of complexity from the tree which is no longer required. Reviewed-by: Jacob Champion <[email protected]> Reviewed-by: Peter Eisentraut <[email protected]> Reviewed-by: Michael Paquier <[email protected]> Discussion: https://postgr.es/m/[email protected] Discussion: https://postgr.es/m/CA+hUKGKh7QrYzu=8yWEUJvXtMVm_CNWH1L_TLWCbZMwbi1XP2Q@mail.gmail.com --- configure | 31 ++-- configure.ac | 12 +- contrib/pgcrypto/openssl.c | 8 - doc/src/sgml/installation.sgml | 2 +- meson.build | 23 +-- src/backend/libpq/be-secure-openssl.c | 16 +- src/common/Makefile | 3 +- src/common/hmac_openssl.c | 21 +-- src/common/meson.build | 1 - src/common/protocol_openssl.c | 117 -------------- src/include/common/openssl.h | 14 +- src/include/pg_config.h.in | 15 -- src/interfaces/libpq/fe-secure-openssl.c | 197 ----------------------- src/interfaces/libpq/libpq-int.h | 5 - 14 files changed, 28 insertions(+), 437 deletions(-) delete mode 100644 src/common/protocol_openssl.c diff --git a/configure b/configure index cfbd2a096f..73e76070b0 100755 --- a/configure +++ b/configure @@ -12330,9 +12330,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 @@ -12564,33 +12564,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 : - cat >>confdefs.h <<_ACEOF -#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 -_ACEOF - -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 : + 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 HAVE_CRYPTO_LOCK 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 - # 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 67e738d92b..cf85ad409e 100644 --- a/configure.ac +++ b/configure.ac @@ -1335,8 +1335,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])]) @@ -1352,12 +1352,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]) 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..e35f52a4d0 100644 --- a/doc/src/sgml/installation.sgml +++ b/doc/src/sgml/installation.sgml @@ -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> diff --git a/meson.build b/meson.build index 43fad5323c..b77dda7c2b 100644 --- a/meson.build +++ b/meson.build @@ -1272,26 +1272,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 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 + ['OPENSSL_init_ssl', {'required': true}], + + # Function introduced in OpenSSL 1.0.2, not in LibreSSL. + ['SSL_CTX_set_cert_cb'], + + # Function introduced in OpenSSL 1.1.1, not in LibreSSL ['X509_get_signature_info'], ] @@ -1314,7 +1305,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 29c9af1aab..88153d4bda 100644 --- a/src/backend/libpq/be-secure-openssl.c +++ b/src/backend/libpq/be-secure-openssl.c @@ -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 @@ -104,13 +105,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; } @@ -933,7 +928,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(); @@ -956,14 +950,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..e55b024159 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) @@ -139,16 +134,11 @@ pg_hmac_create(pg_cryptohash_type type) * previous runs. */ ERR_clear_error(); - #ifdef USE_RESOWNER_FOR_HMAC 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 +152,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 +315,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 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/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 */ diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in index f8d3e3b6b8..2b5f5cafab 100644 --- a/src/include/pg_config.h.in +++ b/src/include/pg_config.h.in @@ -54,9 +54,6 @@ /* 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 want to use atomics if available. */ #undef HAVE_ATOMICS @@ -66,9 +63,6 @@ /* 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 @@ -84,9 +78,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 @@ -198,12 +189,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 diff --git a/src/interfaces/libpq/fe-secure-openssl.c b/src/interfaces/libpq/fe-secure-openssl.c index c98cfa6084..640edebcfe 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 -} - /* See pqcomm.h comments on OpenSSL implementation of ALPN (RFC 7301) */ static unsigned char alpn_protos[] = PG_ALPN_PROTOCOL_VECTOR; @@ -1615,8 +1460,6 @@ open_client_SSL(PGconn *conn) void pgtls_close(PGconn *conn) { - bool destroy_needed = false; - if (conn->ssl_in_use) { if (conn->ssl) @@ -1632,8 +1475,6 @@ pgtls_close(PGconn *conn) conn->ssl = NULL; conn->ssl_in_use = false; conn->ssl_handshake_started = false; - - destroy_needed = true; } if (conn->peer) @@ -1651,30 +1492,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; - } } @@ -1935,7 +1752,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(); @@ -1961,14 +1777,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; @@ -1976,13 +1784,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 3691e5ee96..434d6c449f 100644 --- a/src/interfaces/libpq/libpq-int.h +++ b/src/interfaces/libpq/libpq-int.h @@ -580,11 +580,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 */ -- 2.39.3 (Apple Git-146) [application/octet-stream] v9-0001-Doc-Use-past-tense-for-things-which-happened-in-t.patch (1.6K, ../../[email protected]/6-v9-0001-Doc-Use-past-tense-for-things-which-happened-in-t.patch) download | inline diff: From 9ad9e09523574bf33d8a832e03c31ea539cfe2dc Mon Sep 17 00:00:00 2001 From: Daniel Gustafsson <[email protected]> Date: Fri, 12 Apr 2024 11:36:08 +0200 Subject: [PATCH v9 1/5] Doc: Use past tense for things which happened in the past The paragraph on SSL compression is largely describing events which took place many years ago, so reword with past tense. Reviewed-by: Peter Eisentraut <[email protected]> Discussion: https://postgr.es/m/[email protected] --- doc/src/sgml/libpq.sgml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml index 9199d0d2e5..0db3667fdf 100644 --- a/doc/src/sgml/libpq.sgml +++ b/doc/src/sgml/libpq.sgml @@ -1840,11 +1840,11 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname <para> SSL compression is nowadays considered insecure and its use is no - longer recommended. <productname>OpenSSL</productname> 1.1.0 disables + longer recommended. <productname>OpenSSL</productname> 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. - <productname>PostgreSQL</productname> 14 disables compression + <productname>PostgreSQL</productname> 14 disabled compression completely in the backend. </para> -- 2.39.3 (Apple Git-146) ^ permalink raw reply [nested|flat] 25+ messages in thread
* Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~? @ 2024-04-18 10:53 Peter Eisentraut <[email protected]> parent: Daniel Gustafsson <[email protected]> 0 siblings, 2 replies; 25+ messages in thread From: Peter Eisentraut @ 2024-04-18 10:53 UTC (permalink / raw) To: Daniel Gustafsson <[email protected]>; Michael Paquier <[email protected]>; +Cc: Jacob Champion <[email protected]>; Thomas Munro <[email protected]>; Postgres hackers <[email protected]>; [email protected]; Tom Lane <[email protected]> On 16.04.24 10:17, Daniel Gustafsson wrote: > I forgot (and didn't check) that we backpatched 01e6f1a842f4, with that in mind > I agree that we should backpatch 0003 as well to put LibreSSL on par as much as > we can. 0004 is a fix for the LibreSSL support, not adding anything new, so > pushing that to master now makes sense. Unless objections are raised I'll push > 0001, 0003 and 0004 shortly. 0002 and 0005 can hopefully be addressed in the > July commitfest. Review of the latest batch: * v9-0001-Doc-Use-past-tense-for-things-which-happened-in-t.patch Ok 8 v9-0002-Remove-support-for-OpenSSL-1.0.2.patch Ok, but maybe make the punctuation consistent here: + # Function introduced in OpenSSL 1.0.2, not in LibreSSL. + ['SSL_CTX_set_cert_cb'], + + # Function introduced in OpenSSL 1.1.1, not in LibreSSL ['X509_get_signature_info'], * v9-0003-Support-disallowing-SSL-renegotiation-in-LibreSSL.patch ok * v9-0004-Support-SSL_R_VERSION_TOO_LOW-on-LibreSSL.patch Seems ok, but the reason isn't clear to me. Are there LibreSSL versions that have SSL_R_VERSION_TOO_LOW but not SSL_R_VERSION_TOO_HIGH? Maybe this could be explained better. Also, "OpenSSL 7.2" in the commit message probably meant "OpenBSD"? * v9-0005-Remove-pg_strong_random-initialization.patch I don't understand the reason for this phrase in the commit message: "1.1.1 is being increasingly phased out from production use". Did you mean 1.1.0 there? Conditionally sticking the RAND_poll() into pg_strong_random(), does that have the effect we want? It wouldn't reinitialize after a fork, AFAICT. If everything is addressed, I agree that 0001, 0003, and 0004 can go into PG17, the rest later. ^ permalink raw reply [nested|flat] 25+ messages in thread
* Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~? @ 2024-04-18 20:26 Daniel Gustafsson <[email protected]> parent: Peter Eisentraut <[email protected]> 1 sibling, 0 replies; 25+ messages in thread From: Daniel Gustafsson @ 2024-04-18 20:26 UTC (permalink / raw) To: Peter Eisentraut <[email protected]>; +Cc: Michael Paquier <[email protected]>; Jacob Champion <[email protected]>; Thomas Munro <[email protected]>; Postgres hackers <[email protected]>; [email protected]; Tom Lane <[email protected]> > On 18 Apr 2024, at 12:53, Peter Eisentraut <[email protected]> wrote: > Review of the latest batch: Thanks for reviewing! > 8 v9-0002-Remove-support-for-OpenSSL-1.0.2.patch > > Ok, but maybe make the punctuation consistent here: Fixed. > * v9-0004-Support-SSL_R_VERSION_TOO_LOW-on-LibreSSL.patch > > Seems ok, but the reason isn't clear to me. Are there LibreSSL versions that have SSL_R_VERSION_TOO_LOW but not SSL_R_VERSION_TOO_HIGH? Maybe this could be explained better. LibreSSL doesn't support SSL_R_VERSION_TOO_HIGH at all, they only support _TOO_LOW starting with the OpenBSD 7.2 release. I've expanded the commit message to document this. > Also, "OpenSSL 7.2" in the commit message probably meant "OpenBSD"? Ah yes, fixed. > * v9-0005-Remove-pg_strong_random-initialization.patch > > I don't understand the reason for this phrase in the commit message: "1.1.1 is being increasingly phased out from production use". Did you mean 1.1.0 there? Correct, I got lost among the version numbers it seems. Fixed. > Conditionally sticking the RAND_poll() into pg_strong_random(), does that have the effect we want? It wouldn't reinitialize after a fork, AFAICT. No I think you're right, my previous version would have worked (but was ugly) but this doesn't guarantee that. Thinking more about it maybe it's best to just keep the init function and have a version check for 1.1.0 there, making it an empty no-op for all other cases. When we move past 1.1.0 due to a new API requirement we can blow it all away. > If everything is addressed, I agree that 0001, 0003, and 0004 can go into PG17, the rest later. Agreed, 0002 and 0005 are clearly for the v18 cycle. -- Daniel Gustafsson Attachments: [application/octet-stream] v10-0001-Doc-Use-past-tense-for-things-which-happened-in-.patch (1.6K, ../../[email protected]/2-v10-0001-Doc-Use-past-tense-for-things-which-happened-in-.patch) download | inline diff: From 82f8a165c651dcdf9b35e208c8aa00fba8696dfe Mon Sep 17 00:00:00 2001 From: Daniel Gustafsson <[email protected]> Date: Thu, 18 Apr 2024 21:36:52 +0200 Subject: [PATCH v10 1/5] Doc: Use past tense for things which happened in the past The paragraph on SSL compression is largely describing events which took place many years ago, so reword with past tense. Reviewed-by: Peter Eisentraut <[email protected]> Discussion: https://postgr.es/m/[email protected] --- doc/src/sgml/libpq.sgml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml index 9199d0d2e5..0db3667fdf 100644 --- a/doc/src/sgml/libpq.sgml +++ b/doc/src/sgml/libpq.sgml @@ -1840,11 +1840,11 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname <para> SSL compression is nowadays considered insecure and its use is no - longer recommended. <productname>OpenSSL</productname> 1.1.0 disables + longer recommended. <productname>OpenSSL</productname> 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. - <productname>PostgreSQL</productname> 14 disables compression + <productname>PostgreSQL</productname> 14 disabled compression completely in the backend. </para> -- 2.39.3 (Apple Git-146) [application/octet-stream] v10-0002-Remove-support-for-OpenSSL-1.0.2.patch (25.7K, ../../[email protected]/3-v10-0002-Remove-support-for-OpenSSL-1.0.2.patch) download | inline diff: From 9f7aff6c60727ed431b638a4d0d4cde3994ae7c5 Mon Sep 17 00:00:00 2001 From: Daniel Gustafsson <[email protected]> Date: Thu, 18 Apr 2024 21:37:00 +0200 Subject: [PATCH v10 2/5] Remove support for OpenSSL 1.0.2 OpenSSL 1.0.2 has been EOL from upstream for some time, and is no longer the default OpenSSL version with any vendor which package PostgreSQL. By retiring support for 1.0.2 we can remove a lot of complexity from the tree which is no longer required. Reviewed-by: Jacob Champion <[email protected]> Reviewed-by: Peter Eisentraut <[email protected]> Reviewed-by: Michael Paquier <[email protected]> Discussion: https://postgr.es/m/[email protected] Discussion: https://postgr.es/m/CA+hUKGKh7QrYzu=8yWEUJvXtMVm_CNWH1L_TLWCbZMwbi1XP2Q@mail.gmail.com --- configure | 31 ++-- configure.ac | 12 +- contrib/pgcrypto/openssl.c | 8 - doc/src/sgml/installation.sgml | 2 +- meson.build | 23 +-- src/backend/libpq/be-secure-openssl.c | 16 +- src/common/Makefile | 3 +- src/common/hmac_openssl.c | 21 +-- src/common/meson.build | 1 - src/common/protocol_openssl.c | 117 -------------- src/include/common/openssl.h | 14 +- src/include/pg_config.h.in | 15 -- src/interfaces/libpq/fe-secure-openssl.c | 197 ----------------------- src/interfaces/libpq/libpq-int.h | 5 - 14 files changed, 28 insertions(+), 437 deletions(-) diff --git a/configure b/configure index cfbd2a096f..73e76070b0 100755 --- a/configure +++ b/configure @@ -12330,9 +12330,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 @@ -12564,33 +12564,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 : - cat >>confdefs.h <<_ACEOF -#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 -_ACEOF - -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 : + 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 HAVE_CRYPTO_LOCK 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 - # 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 67e738d92b..cf85ad409e 100644 --- a/configure.ac +++ b/configure.ac @@ -1335,8 +1335,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])]) @@ -1352,12 +1352,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]) 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..e35f52a4d0 100644 --- a/doc/src/sgml/installation.sgml +++ b/doc/src/sgml/installation.sgml @@ -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> diff --git a/meson.build b/meson.build index cdfd31377d..f9ec8b66a8 100644 --- a/meson.build +++ b/meson.build @@ -1272,26 +1272,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 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 + ['OPENSSL_init_ssl', {'required': true}], + + # Function introduced in OpenSSL 1.0.2, not in LibreSSL. + ['SSL_CTX_set_cert_cb'], + + # Function introduced in OpenSSL 1.1.1, not in LibreSSL. ['X509_get_signature_info'], ] @@ -1314,7 +1305,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 29c9af1aab..88153d4bda 100644 --- a/src/backend/libpq/be-secure-openssl.c +++ b/src/backend/libpq/be-secure-openssl.c @@ -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 @@ -104,13 +105,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; } @@ -933,7 +928,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(); @@ -956,14 +950,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..e55b024159 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) @@ -139,16 +134,11 @@ pg_hmac_create(pg_cryptohash_type type) * previous runs. */ ERR_clear_error(); - #ifdef USE_RESOWNER_FOR_HMAC 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 +152,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 +315,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 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 index ae378685e1..e69de29bb2 100644 --- a/src/common/protocol_openssl.c +++ b/src/common/protocol_openssl.c @@ -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/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 */ diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in index f8d3e3b6b8..2b5f5cafab 100644 --- a/src/include/pg_config.h.in +++ b/src/include/pg_config.h.in @@ -54,9 +54,6 @@ /* 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 want to use atomics if available. */ #undef HAVE_ATOMICS @@ -66,9 +63,6 @@ /* 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 @@ -84,9 +78,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 @@ -198,12 +189,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 diff --git a/src/interfaces/libpq/fe-secure-openssl.c b/src/interfaces/libpq/fe-secure-openssl.c index e7a4d006e1..640edebcfe 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 -} - /* See pqcomm.h comments on OpenSSL implementation of ALPN (RFC 7301) */ static unsigned char alpn_protos[] = PG_ALPN_PROTOCOL_VECTOR; @@ -1615,8 +1460,6 @@ open_client_SSL(PGconn *conn) void pgtls_close(PGconn *conn) { - bool destroy_needed = false; - if (conn->ssl_in_use) { if (conn->ssl) @@ -1632,8 +1475,6 @@ pgtls_close(PGconn *conn) conn->ssl = NULL; conn->ssl_in_use = false; conn->ssl_handshake_started = false; - - destroy_needed = true; } if (conn->peer) @@ -1651,30 +1492,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; - } } @@ -1935,7 +1752,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(); @@ -1961,14 +1777,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; @@ -1976,13 +1784,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 3691e5ee96..434d6c449f 100644 --- a/src/interfaces/libpq/libpq-int.h +++ b/src/interfaces/libpq/libpq-int.h @@ -580,11 +580,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 */ -- 2.39.3 (Apple Git-146) [application/octet-stream] v10-0003-Support-disallowing-SSL-renegotiation-in-LibreSS.patch (2.0K, ../../[email protected]/4-v10-0003-Support-disallowing-SSL-renegotiation-in-LibreSS.patch) download | inline diff: From 436f9bf6d4bf04eb8b47fea4fede6176be5e29e8 Mon Sep 17 00:00:00 2001 From: Daniel Gustafsson <[email protected]> Date: Thu, 18 Apr 2024 21:37:44 +0200 Subject: [PATCH v10 3/5] Support disallowing SSL renegotiation in LibreSSL LibreSSL doesn't support the SSL_OP_NO_RENEGOTIATION macro which is used by OpenSSL, instead it has invented a similar one for client- side renegotiation: SSL_OP_NO_CLIENT_RENEGOTIATION. This has been supported since LibreSSL 2.5.1 which by now can be considered well below the minimum requirement. Discussion: https://postgr.es/m/[email protected] --- src/backend/libpq/be-secure-openssl.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c index 88153d4bda..efd49ffca8 100644 --- a/src/backend/libpq/be-secure-openssl.c +++ b/src/backend/libpq/be-secure-openssl.c @@ -262,15 +262,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)) -- 2.39.3 (Apple Git-146) [application/octet-stream] v10-0004-Support-SSL_R_VERSION_TOO_LOW-on-LibreSSL.patch (1.4K, ../../[email protected]/5-v10-0004-Support-SSL_R_VERSION_TOO_LOW-on-LibreSSL.patch) download | inline diff: From 909a6c2c9de701931488ab28cc9500ff2326e43e Mon Sep 17 00:00:00 2001 From: Daniel Gustafsson <[email protected]> Date: Thu, 18 Apr 2024 21:37:57 +0200 Subject: [PATCH v10 4/5] Support SSL_R_VERSION_TOO_LOW on LibreSSL The SSL_R_VERSION_TOO_LOW error reason is supported in LibreSSL since LibreSSL 3.6.3, shipped in OpenBSD 7.2. SSL_R_VERSION_TOO_HIGH is on the other hand not supported in any version of LibreSSL. Previously we only checked for SSL_R_VERSION_TOO_HIGH and then applied both under that guard since OpenSSL has only ever supported both at the same time. This breaks the check into one per reason to allow SSL_R_VERSION_TOO_LOW to work when using LibreSSL. Reviewed-by: Peter Eisentraut <[email protected]> Discussion: https://postgr.es/m/[email protected] --- src/backend/libpq/be-secure-openssl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c index efd49ffca8..59c71b15b5 100644 --- a/src/backend/libpq/be-secure-openssl.c +++ b/src/backend/libpq/be-secure-openssl.c @@ -542,6 +542,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; -- 2.39.3 (Apple Git-146) [application/octet-stream] v10-0005-Remove-pg_strong_random-initialization.patch (1.9K, ../../[email protected]/6-v10-0005-Remove-pg_strong_random-initialization.patch) download | inline diff: From 0fc05de568f8699b6265efaf40aad9836b59166a Mon Sep 17 00:00:00 2001 From: Daniel Gustafsson <[email protected]> Date: Thu, 18 Apr 2024 21:39:33 +0200 Subject: [PATCH v10 5/5] Remove pg_strong_random initialization. The random number generator in OpenSSL 1.1.1 was redesigned to provide fork safety by default, thus removing the need for calling RAND_poll after forking to ensure that two processes cannot share the same state. Since we now support 1.1.0 as the minumum version, and 1.1.0 is being increasingly phased out from production use, only perform the RAND_poll initialization for installations running 1.1.0 by checkig the OpenSSL version number. LibreSSL changed random number generator when forking OpenSSL and has provided fork safety since version 2.0.2. This removes the overhead of initializing the RNG for strong random for the vast majority of users for whom it is no longer required. Discussion: https://postgr.es/m/CA+hUKGKh7QrYzu=8yWEUJvXtMVm_CNWH1L_TLWCbZMwbi1XP2Q@mail.gmail.com --- src/port/pg_strong_random.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/port/pg_strong_random.c b/src/port/pg_strong_random.c index 5f2b248425..a8efb2b188 100644 --- a/src/port/pg_strong_random.c +++ b/src/port/pg_strong_random.c @@ -50,17 +50,20 @@ #ifdef USE_OPENSSL +#include <openssl/opensslv.h> #include <openssl/rand.h> void pg_strong_random_init(void) { +#if (OPENSSL_VERSION_NUMBER < 0x10101000L) /* - * 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 not + * required on LibreSSL and no longer required in OpenSSL 1.1.1 and later + * versions. */ RAND_poll(); +#endif } bool -- 2.39.3 (Apple Git-146) ^ permalink raw reply [nested|flat] 25+ messages in thread
* Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~? @ 2024-04-19 05:37 Michael Paquier <[email protected]> parent: Peter Eisentraut <[email protected]> 1 sibling, 2 replies; 25+ messages in thread From: Michael Paquier @ 2024-04-19 05:37 UTC (permalink / raw) To: Peter Eisentraut <[email protected]>; +Cc: Daniel Gustafsson <[email protected]>; Jacob Champion <[email protected]>; Thomas Munro <[email protected]>; Postgres hackers <[email protected]>; [email protected]; Tom Lane <[email protected]> On Thu, Apr 18, 2024 at 12:53:43PM +0200, Peter Eisentraut wrote: > If everything is addressed, I agree that 0001, 0003, and 0004 can go into > PG17, the rest later. About the PG17 bits, would you agree about a backpatch? Or perhaps you disagree? -- Michael Attachments: [application/pgp-signature] signature.asc (833B, ../../[email protected]/2-signature.asc) download ^ permalink raw reply [nested|flat] 25+ messages in thread
* Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~? @ 2024-04-19 06:55 Daniel Gustafsson <[email protected]> parent: Michael Paquier <[email protected]> 1 sibling, 0 replies; 25+ messages in thread From: Daniel Gustafsson @ 2024-04-19 06:55 UTC (permalink / raw) To: Michael Paquier <[email protected]>; +Cc: Peter Eisentraut <[email protected]>; Jacob Champion <[email protected]>; Thomas Munro <[email protected]>; Postgres hackers <[email protected]>; [email protected]; Tom Lane <[email protected]> > On 19 Apr 2024, at 07:37, Michael Paquier <[email protected]> wrote: > > On Thu, Apr 18, 2024 at 12:53:43PM +0200, Peter Eisentraut wrote: >> If everything is addressed, I agree that 0001, 0003, and 0004 can go into >> PG17, the rest later. > > About the PG17 bits, would you agree about a backpatch? Or perhaps > you disagree? If we want to 0001 can be baclpatched to v15, 0004 to v13 and 0003 all the way. I don't have strong opinions either way. -- Daniel Gustafsson ^ permalink raw reply [nested|flat] 25+ messages in thread
* Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~? @ 2024-04-19 08:06 Peter Eisentraut <[email protected]> parent: Michael Paquier <[email protected]> 1 sibling, 1 reply; 25+ messages in thread From: Peter Eisentraut @ 2024-04-19 08:06 UTC (permalink / raw) To: Michael Paquier <[email protected]>; +Cc: Daniel Gustafsson <[email protected]>; Jacob Champion <[email protected]>; Thomas Munro <[email protected]>; Postgres hackers <[email protected]>; [email protected]; Tom Lane <[email protected]> On 19.04.24 07:37, Michael Paquier wrote: > On Thu, Apr 18, 2024 at 12:53:43PM +0200, Peter Eisentraut wrote: >> If everything is addressed, I agree that 0001, 0003, and 0004 can go into >> PG17, the rest later. > > About the PG17 bits, would you agree about a backpatch? Or perhaps > you disagree? I don't think any of these need to be backpatched, at least right now. 0001 is just a cosmetic documentation tweak, has no reason to be backpatched. 0003 adds new functionality for LibreSSL. While the code looks straightforward, we have little knowledge about how it works in practice. How is the buildfarm coverage of LibreSSL (with SSL tests enabled!)? If people are keen on this, it might be better to get it into PG17 and at least let to go through a few months of beta testing. 0004 effectively just enhances an error message for LibreSSL; there is little reason to backpatch this. ^ permalink raw reply [nested|flat] 25+ messages in thread
* Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~? @ 2024-04-23 20:08 Daniel Gustafsson <[email protected]> parent: Peter Eisentraut <[email protected]> 0 siblings, 1 reply; 25+ messages in thread From: Daniel Gustafsson @ 2024-04-23 20:08 UTC (permalink / raw) To: Peter Eisentraut <[email protected]>; +Cc: Michael Paquier <[email protected]>; Jacob Champion <[email protected]>; Thomas Munro <[email protected]>; Postgres hackers <[email protected]>; [email protected]; Tom Lane <[email protected]> > On 19 Apr 2024, at 10:06, Peter Eisentraut <[email protected]> wrote: > > On 19.04.24 07:37, Michael Paquier wrote: >> On Thu, Apr 18, 2024 at 12:53:43PM +0200, Peter Eisentraut wrote: >>> If everything is addressed, I agree that 0001, 0003, and 0004 can go into >>> PG17, the rest later. >> About the PG17 bits, would you agree about a backpatch? Or perhaps >> you disagree? > > I don't think any of these need to be backpatched, at least right now. > > 0001 is just a cosmetic documentation tweak, has no reason to be backpatched. > > 0003 adds new functionality for LibreSSL. While the code looks straightforward, we have little knowledge about how it works in practice. How is the buildfarm coverage of LibreSSL (with SSL tests enabled!)? If people are keen on this, it might be better to get it into PG17 and at least let to go through a few months of beta testing. > > 0004 effectively just enhances an error message for LibreSSL; there is little reason to backpatch this. Hearing no objections to this plan (and the posted v10), I'll go ahead with 0001, 0003 and 0004 into v17 tomorrow. -- Daniel Gustafsson ^ permalink raw reply [nested|flat] 25+ messages in thread
* Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~? @ 2024-04-23 22:20 Michael Paquier <[email protected]> parent: Daniel Gustafsson <[email protected]> 0 siblings, 1 reply; 25+ messages in thread From: Michael Paquier @ 2024-04-23 22:20 UTC (permalink / raw) To: Daniel Gustafsson <[email protected]>; +Cc: Peter Eisentraut <[email protected]>; Jacob Champion <[email protected]>; Thomas Munro <[email protected]>; Postgres hackers <[email protected]>; [email protected]; Tom Lane <[email protected]> On Tue, Apr 23, 2024 at 10:08:13PM +0200, Daniel Gustafsson wrote: > Hearing no objections to this plan (and the posted v10), I'll go ahead with > 0001, 0003 and 0004 into v17 tomorrow. WFM, thanks. -- Michael Attachments: [application/pgp-signature] signature.asc (833B, ../../[email protected]/2-signature.asc) download ^ permalink raw reply [nested|flat] 25+ messages in thread
* Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~? @ 2024-04-24 11:31 Daniel Gustafsson <[email protected]> parent: Michael Paquier <[email protected]> 0 siblings, 1 reply; 25+ messages in thread From: Daniel Gustafsson @ 2024-04-24 11:31 UTC (permalink / raw) To: Michael Paquier <[email protected]>; +Cc: Peter Eisentraut <[email protected]>; Jacob Champion <[email protected]>; Thomas Munro <[email protected]>; Postgres hackers <[email protected]>; [email protected]; Tom Lane <[email protected]> > On 24 Apr 2024, at 00:20, Michael Paquier <[email protected]> wrote: > > On Tue, Apr 23, 2024 at 10:08:13PM +0200, Daniel Gustafsson wrote: >> Hearing no objections to this plan (and the posted v10), I'll go ahead with >> 0001, 0003 and 0004 into v17 tomorrow. > > WFM, thanks. Done. Attached are the two remaining patches, rebased over HEAD, for removing support for OpenSSL 1.0.2 in v18. Parking them in the commitfest for now. -- Daniel Gustafsson Attachments: [application/octet-stream] v11-0002-Remove-pg_strong_random-initialization.patch (1.9K, ../../[email protected]/2-v11-0002-Remove-pg_strong_random-initialization.patch) download | inline diff: From 331207efef429954265bbb24687d71df91e2c9a9 Mon Sep 17 00:00:00 2001 From: Daniel Gustafsson <[email protected]> Date: Thu, 18 Apr 2024 21:39:33 +0200 Subject: [PATCH v11 2/2] Remove pg_strong_random initialization. The random number generator in OpenSSL 1.1.1 was redesigned to provide fork safety by default, thus removing the need for calling RAND_poll after forking to ensure that two processes cannot share the same state. Since we now support 1.1.0 as the minumum version, and 1.1.0 is being increasingly phased out from production use, only perform the RAND_poll initialization for installations running 1.1.0 by checkig the OpenSSL version number. LibreSSL changed random number generator when forking OpenSSL and has provided fork safety since version 2.0.2. This removes the overhead of initializing the RNG for strong random for the vast majority of users for whom it is no longer required. Discussion: https://postgr.es/m/CA+hUKGKh7QrYzu=8yWEUJvXtMVm_CNWH1L_TLWCbZMwbi1XP2Q@mail.gmail.com --- src/port/pg_strong_random.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/port/pg_strong_random.c b/src/port/pg_strong_random.c index 5f2b248425..a8efb2b188 100644 --- a/src/port/pg_strong_random.c +++ b/src/port/pg_strong_random.c @@ -50,17 +50,20 @@ #ifdef USE_OPENSSL +#include <openssl/opensslv.h> #include <openssl/rand.h> void pg_strong_random_init(void) { +#if (OPENSSL_VERSION_NUMBER < 0x10101000L) /* - * 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 not + * required on LibreSSL and no longer required in OpenSSL 1.1.1 and later + * versions. */ RAND_poll(); +#endif } bool -- 2.39.3 (Apple Git-146) [application/octet-stream] v11-0001-Remove-support-for-OpenSSL-1.0.2.patch (25.7K, ../../[email protected]/3-v11-0001-Remove-support-for-OpenSSL-1.0.2.patch) download | inline diff: From 626cdc6b1b6a1ed30b44b261c645c8a922360ba4 Mon Sep 17 00:00:00 2001 From: Daniel Gustafsson <[email protected]> Date: Thu, 18 Apr 2024 21:37:00 +0200 Subject: [PATCH v11 1/2] Remove support for OpenSSL 1.0.2 OpenSSL 1.0.2 has been EOL from upstream for some time, and is no longer the default OpenSSL version with any vendor which package PostgreSQL. By retiring support for 1.0.2 we can remove a lot of complexity from the tree which is no longer required. Reviewed-by: Jacob Champion <[email protected]> Reviewed-by: Peter Eisentraut <[email protected]> Reviewed-by: Michael Paquier <[email protected]> Discussion: https://postgr.es/m/[email protected] Discussion: https://postgr.es/m/CA+hUKGKh7QrYzu=8yWEUJvXtMVm_CNWH1L_TLWCbZMwbi1XP2Q@mail.gmail.com --- configure | 31 ++-- configure.ac | 12 +- contrib/pgcrypto/openssl.c | 8 - doc/src/sgml/installation.sgml | 2 +- meson.build | 23 +-- src/backend/libpq/be-secure-openssl.c | 16 +- src/common/Makefile | 3 +- src/common/hmac_openssl.c | 21 +-- src/common/meson.build | 1 - src/common/protocol_openssl.c | 117 -------------- src/include/common/openssl.h | 14 +- src/include/pg_config.h.in | 15 -- src/interfaces/libpq/fe-secure-openssl.c | 197 ----------------------- src/interfaces/libpq/libpq-int.h | 5 - 14 files changed, 28 insertions(+), 437 deletions(-) diff --git a/configure b/configure index cfbd2a096f..73e76070b0 100755 --- a/configure +++ b/configure @@ -12330,9 +12330,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 @@ -12564,33 +12564,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 : - cat >>confdefs.h <<_ACEOF -#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 -_ACEOF - -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 : + 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 HAVE_CRYPTO_LOCK 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 - # 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 67e738d92b..cf85ad409e 100644 --- a/configure.ac +++ b/configure.ac @@ -1335,8 +1335,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])]) @@ -1352,12 +1352,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]) 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..e35f52a4d0 100644 --- a/doc/src/sgml/installation.sgml +++ b/doc/src/sgml/installation.sgml @@ -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> diff --git a/meson.build b/meson.build index cdfd31377d..f9ec8b66a8 100644 --- a/meson.build +++ b/meson.build @@ -1272,26 +1272,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 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 + ['OPENSSL_init_ssl', {'required': true}], + + # Function introduced in OpenSSL 1.0.2, not in LibreSSL. + ['SSL_CTX_set_cert_cb'], + + # Function introduced in OpenSSL 1.1.1, not in LibreSSL. ['X509_get_signature_info'], ] @@ -1314,7 +1305,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 fc46a33539..59c71b15b5 100644 --- a/src/backend/libpq/be-secure-openssl.c +++ b/src/backend/libpq/be-secure-openssl.c @@ -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 @@ -104,13 +105,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; } @@ -940,7 +935,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(); @@ -963,14 +957,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..e55b024159 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) @@ -139,16 +134,11 @@ pg_hmac_create(pg_cryptohash_type type) * previous runs. */ ERR_clear_error(); - #ifdef USE_RESOWNER_FOR_HMAC 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 +152,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 +315,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 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 index ae378685e1..e69de29bb2 100644 --- a/src/common/protocol_openssl.c +++ b/src/common/protocol_openssl.c @@ -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/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 */ diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in index f8d3e3b6b8..2b5f5cafab 100644 --- a/src/include/pg_config.h.in +++ b/src/include/pg_config.h.in @@ -54,9 +54,6 @@ /* 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 want to use atomics if available. */ #undef HAVE_ATOMICS @@ -66,9 +63,6 @@ /* 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 @@ -84,9 +78,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 @@ -198,12 +189,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 diff --git a/src/interfaces/libpq/fe-secure-openssl.c b/src/interfaces/libpq/fe-secure-openssl.c index e7a4d006e1..640edebcfe 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 -} - /* See pqcomm.h comments on OpenSSL implementation of ALPN (RFC 7301) */ static unsigned char alpn_protos[] = PG_ALPN_PROTOCOL_VECTOR; @@ -1615,8 +1460,6 @@ open_client_SSL(PGconn *conn) void pgtls_close(PGconn *conn) { - bool destroy_needed = false; - if (conn->ssl_in_use) { if (conn->ssl) @@ -1632,8 +1475,6 @@ pgtls_close(PGconn *conn) conn->ssl = NULL; conn->ssl_in_use = false; conn->ssl_handshake_started = false; - - destroy_needed = true; } if (conn->peer) @@ -1651,30 +1492,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; - } } @@ -1935,7 +1752,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(); @@ -1961,14 +1777,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; @@ -1976,13 +1784,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 3691e5ee96..434d6c449f 100644 --- a/src/interfaces/libpq/libpq-int.h +++ b/src/interfaces/libpq/libpq-int.h @@ -580,11 +580,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 */ -- 2.39.3 (Apple Git-146) ^ permalink raw reply [nested|flat] 25+ messages in thread
* Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~? @ 2024-04-25 03:49 Michael Paquier <[email protected]> parent: Daniel Gustafsson <[email protected]> 0 siblings, 1 reply; 25+ messages in thread From: Michael Paquier @ 2024-04-25 03:49 UTC (permalink / raw) To: Daniel Gustafsson <[email protected]>; +Cc: Peter Eisentraut <[email protected]>; Jacob Champion <[email protected]>; Thomas Munro <[email protected]>; Postgres hackers <[email protected]>; [email protected]; Tom Lane <[email protected]> On Wed, Apr 24, 2024 at 01:31:12PM +0200, Daniel Gustafsson wrote: > Done. Attached are the two remaining patches, rebased over HEAD, for removing > support for OpenSSL 1.0.2 in v18. Parking them in the commitfest for now. You have mentioned once upthread the documentation of PQinitOpenSSL(): However, this is unnecessary when using <productname>OpenSSL</productname> version 1.1.0 or later, as duplicate initializations are no longer problematic. With 1.0.2's removal in place, this could be simplified more and the patch does not touch it. This relates also to pq_init_crypto_lib, which is gone with 0001. Of course, it is not possible to just remove PQinitOpenSSL() or old application may fail linking. Removing pq_init_crypto_lib reduces any confusion around this part of the initialization. 0002 looks OK here. -- Michael Attachments: [application/pgp-signature] signature.asc (833B, ../../[email protected]/2-signature.asc) download ^ permalink raw reply [nested|flat] 25+ messages in thread
* Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~? @ 2024-04-27 18:32 Daniel Gustafsson <[email protected]> parent: Michael Paquier <[email protected]> 0 siblings, 1 reply; 25+ messages in thread From: Daniel Gustafsson @ 2024-04-27 18:32 UTC (permalink / raw) To: Michael Paquier <[email protected]>; +Cc: Peter Eisentraut <[email protected]>; Jacob Champion <[email protected]>; Thomas Munro <[email protected]>; Postgres hackers <[email protected]>; [email protected]; Tom Lane <[email protected]> > On 25 Apr 2024, at 05:49, Michael Paquier <[email protected]> wrote: > > On Wed, Apr 24, 2024 at 01:31:12PM +0200, Daniel Gustafsson wrote: >> Done. Attached are the two remaining patches, rebased over HEAD, for removing >> support for OpenSSL 1.0.2 in v18. Parking them in the commitfest for now. > > You have mentioned once upthread the documentation of PQinitOpenSSL(): > However, this is unnecessary when using <productname>OpenSSL</productname> > version 1.1.0 or later, as duplicate initializations are no longer problematic. > > With 1.0.2's removal in place, this could be simplified more and the > patch does not touch it. This relates also to pq_init_crypto_lib, > which is gone with 0001. Of course, it is not possible to just remove > PQinitOpenSSL() or old application may fail linking. Removing > pq_init_crypto_lib reduces any confusion around this part of the > initialization. That's a good point, there is potential for more code removal here. The attached 0001 takes a stab at it while it's fresh in mind, I'll revisit before the July CF to see if there is more that can be done. -- Daniel Gustafsson ^ permalink raw reply [nested|flat] 25+ messages in thread
* Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~? @ 2024-04-27 18:33 Daniel Gustafsson <[email protected]> parent: Daniel Gustafsson <[email protected]> 0 siblings, 1 reply; 25+ messages in thread From: Daniel Gustafsson @ 2024-04-27 18:33 UTC (permalink / raw) To: Michael Paquier <[email protected]>; +Cc: Peter Eisentraut <[email protected]>; Jacob Champion <[email protected]>; Thomas Munro <[email protected]>; Postgres hackers <[email protected]>; [email protected]; Tom Lane <[email protected]> > On 27 Apr 2024, at 20:32, Daniel Gustafsson <[email protected]> wrote: > That's a good point, there is potential for more code removal here. The > attached 0001 takes a stab at it while it's fresh in mind, I'll revisit before > the July CF to see if there is more that can be done. ..and again with the attachment. Not enough coffee. -- Daniel Gustafsson Attachments: [application/octet-stream] v12-0002-Remove-pg_strong_random-initialization.patch (1.9K, ../../[email protected]/2-v12-0002-Remove-pg_strong_random-initialization.patch) download | inline diff: From 8cdf1101c57917e425feb08f6c26fc35a6be9611 Mon Sep 17 00:00:00 2001 From: Daniel Gustafsson <[email protected]> Date: Thu, 18 Apr 2024 21:39:33 +0200 Subject: [PATCH v12 2/2] Remove pg_strong_random initialization. The random number generator in OpenSSL 1.1.1 was redesigned to provide fork safety by default, thus removing the need for calling RAND_poll after forking to ensure that two processes cannot share the same state. Since we now support 1.1.0 as the minumum version, and 1.1.0 is being increasingly phased out from production use, only perform the RAND_poll initialization for installations running 1.1.0 by checkig the OpenSSL version number. LibreSSL changed random number generator when forking OpenSSL and has provided fork safety since version 2.0.2. This removes the overhead of initializing the RNG for strong random for the vast majority of users for whom it is no longer required. Discussion: https://postgr.es/m/CA+hUKGKh7QrYzu=8yWEUJvXtMVm_CNWH1L_TLWCbZMwbi1XP2Q@mail.gmail.com --- src/port/pg_strong_random.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/port/pg_strong_random.c b/src/port/pg_strong_random.c index 5f2b248425..a8efb2b188 100644 --- a/src/port/pg_strong_random.c +++ b/src/port/pg_strong_random.c @@ -50,17 +50,20 @@ #ifdef USE_OPENSSL +#include <openssl/opensslv.h> #include <openssl/rand.h> void pg_strong_random_init(void) { +#if (OPENSSL_VERSION_NUMBER < 0x10101000L) /* - * 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 not + * required on LibreSSL and no longer required in OpenSSL 1.1.1 and later + * versions. */ RAND_poll(); +#endif } bool -- 2.39.3 (Apple Git-146) [application/octet-stream] v12-0001-Remove-support-for-OpenSSL-1.0.2.patch (31.3K, ../../[email protected]/3-v12-0001-Remove-support-for-OpenSSL-1.0.2.patch) download | inline diff: From a9f6a2a2db3c12665fb96d01ad22056c4342e604 Mon Sep 17 00:00:00 2001 From: Daniel Gustafsson <[email protected]> Date: Thu, 18 Apr 2024 21:37:00 +0200 Subject: [PATCH v12 1/2] Remove support for OpenSSL 1.0.2 OpenSSL 1.0.2 has been EOL from upstream for some time, and is no longer the default OpenSSL version with any vendor which package PostgreSQL. By retiring support for 1.0.2 we can remove a lot of complexity from the tree which is no longer required. Reviewed-by: Jacob Champion <[email protected]> Reviewed-by: Peter Eisentraut <[email protected]> Reviewed-by: Michael Paquier <[email protected]> Discussion: https://postgr.es/m/[email protected] Discussion: https://postgr.es/m/CA+hUKGKh7QrYzu=8yWEUJvXtMVm_CNWH1L_TLWCbZMwbi1XP2Q@mail.gmail.com --- configure | 31 +-- configure.ac | 12 +- contrib/pgcrypto/openssl.c | 8 - doc/src/sgml/installation.sgml | 2 +- meson.build | 23 +-- src/backend/libpq/be-secure-openssl.c | 24 +-- src/common/Makefile | 3 +- src/common/hmac_openssl.c | 21 +- src/common/meson.build | 1 - src/common/protocol_openssl.c | 117 ----------- src/include/common/openssl.h | 14 +- src/include/pg_config.h.in | 15 -- src/interfaces/libpq/fe-connect.c | 18 -- src/interfaces/libpq/fe-secure-openssl.c | 246 ----------------------- src/interfaces/libpq/fe-secure.c | 35 +--- src/interfaces/libpq/libpq-int.h | 13 +- 16 files changed, 41 insertions(+), 542 deletions(-) diff --git a/configure b/configure index 89644f2249..1181a7347f 100755 --- a/configure +++ b/configure @@ -12330,9 +12330,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 @@ -12564,33 +12564,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 : - cat >>confdefs.h <<_ACEOF -#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 -_ACEOF - -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 : + 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 HAVE_CRYPTO_LOCK 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 - # 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 c7322e292c..2d5e2c2c2c 100644 --- a/configure.ac +++ b/configure.ac @@ -1335,8 +1335,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])]) @@ -1352,12 +1352,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]) 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..e35f52a4d0 100644 --- a/doc/src/sgml/installation.sgml +++ b/doc/src/sgml/installation.sgml @@ -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> diff --git a/meson.build b/meson.build index cdfd31377d..f9ec8b66a8 100644 --- a/meson.build +++ b/meson.build @@ -1272,26 +1272,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 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 + ['OPENSSL_init_ssl', {'required': true}], + + # Function introduced in OpenSSL 1.0.2, not in LibreSSL. + ['SSL_CTX_set_cert_cb'], + + # Function introduced in OpenSSL 1.1.1, not in LibreSSL. ['X509_get_signature_info'], ] @@ -1314,7 +1305,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 fc46a33539..3ba85490e5 100644 --- a/src/backend/libpq/be-secure-openssl.c +++ b/src/backend/libpq/be-secure-openssl.c @@ -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 @@ -940,7 +927,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(); @@ -963,14 +949,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..e55b024159 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) @@ -139,16 +134,11 @@ pg_hmac_create(pg_cryptohash_type type) * previous runs. */ ERR_clear_error(); - #ifdef USE_RESOWNER_FOR_HMAC 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 +152,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 +315,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 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 index ae378685e1..e69de29bb2 100644 --- a/src/common/protocol_openssl.c +++ b/src/common/protocol_openssl.c @@ -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/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 */ diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in index f8d3e3b6b8..2b5f5cafab 100644 --- a/src/include/pg_config.h.in +++ b/src/include/pg_config.h.in @@ -54,9 +54,6 @@ /* 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 want to use atomics if available. */ #undef HAVE_ATOMICS @@ -66,9 +63,6 @@ /* 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 @@ -84,9 +78,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 @@ -198,12 +189,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 diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c index ec20e3f3a9..f56c0712bb 100644 --- a/src/interfaces/libpq/fe-connect.c +++ b/src/interfaces/libpq/fe-connect.c @@ -3327,16 +3327,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 direct SSL is enabled, jump right into SSL handshake. We * will come back here after SSL encryption has been @@ -3510,14 +3500,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 e7a4d006e1..8927571076 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; @@ -1615,8 +1411,6 @@ open_client_SSL(PGconn *conn) void pgtls_close(PGconn *conn) { - bool destroy_needed = false; - if (conn->ssl_in_use) { if (conn->ssl) @@ -1632,8 +1426,6 @@ pgtls_close(PGconn *conn) conn->ssl = NULL; conn->ssl_in_use = false; conn->ssl_handshake_started = false; - - destroy_needed = true; } if (conn->peer) @@ -1651,30 +1443,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; - } } @@ -1935,7 +1703,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(); @@ -1961,14 +1728,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; @@ -1976,13 +1735,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 3691e5ee96..21df8623a7 100644 --- a/src/interfaces/libpq/libpq-int.h +++ b/src/interfaces/libpq/libpq-int.h @@ -580,11 +580,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 */ @@ -763,7 +758,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); @@ -786,19 +780,18 @@ 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); +extern void pgtls_init_library(bool do_ssl); /* * 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. + * if SSL is initialized. * * 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); +extern int pgtls_init(PGconn *conn, bool do_ssl); /* * Begin or continue negotiating a secure session. -- 2.39.3 (Apple Git-146) ^ permalink raw reply [nested|flat] 25+ messages in thread
* Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~? @ 2024-05-01 04:21 Michael Paquier <[email protected]> parent: Daniel Gustafsson <[email protected]> 0 siblings, 1 reply; 25+ messages in thread From: Michael Paquier @ 2024-05-01 04:21 UTC (permalink / raw) To: Daniel Gustafsson <[email protected]>; +Cc: Peter Eisentraut <[email protected]>; Jacob Champion <[email protected]>; Thomas Munro <[email protected]>; Postgres hackers <[email protected]>; [email protected]; Tom Lane <[email protected]> On Sat, Apr 27, 2024 at 08:33:55PM +0200, Daniel Gustafsson wrote: > > On 27 Apr 2024, at 20:32, Daniel Gustafsson <[email protected]> wrote: > > > That's a good point, there is potential for more code removal here. The > > attached 0001 takes a stab at it while it's fresh in mind, I'll revisit before > > the July CF to see if there is more that can be done. > > ..and again with the attachment. Not enough coffee. My remark was originally about pq_init_crypto_lib that does the locking initialization, and your new patch a bit more, as of: - /* 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; - } OPENSSL_init_ssl() has replaced SSL_library_init(), marked as deprecated, and even this step is mentioned as not required anymore with 1.1.0~: https://www.openssl.org/docs/man1.1.1/man3/OPENSSL_init_ssl.html Same with OPENSSL_init_crypto(), replacing OPENSSL_config(), again not required in 1.1.0~: https://www.openssl.org/docs/man1.1.1/man3/OPENSSL_init_crypto.html SSL_load_error_strings() is recommended as not to use in 1.1.0, replaced by the others: https://www.openssl.org/docs/man3.2/man3/SSL_load_error_strings.html While OpenSSL will be able to cope with that, how much of that applies to LibreSSL? SSL_load_error_strings(), OPENSSL_init_ssl(), OPENSSL_CONFIG() are OK based on the docs: https://man.archlinux.org/man/extra/libressl/libressl-OPENSSL_config.3.en https://man.archlinux.org/man/extra/libressl/libressl-OPENSSL_init_ssl.3.en https://man.archlinux.org/man/extra/libressl/libressl-ERR_load_crypto_strings.3.en So +1 to remove all this code after a closer lookup. I would recommend to update the documentation of PQinitSSL and PQinitOpenSSL to tell that these become useless and are deprecated. ERR_clear_error(); - #ifdef USE_RESOWNER_FOR_HMAC Some noise diff. -- Michael Attachments: [application/pgp-signature] signature.asc (833B, ../../[email protected]/2-signature.asc) download ^ permalink raw reply [nested|flat] 25+ messages in thread
* Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~? @ 2024-05-03 08:39 Daniel Gustafsson <[email protected]> parent: Michael Paquier <[email protected]> 0 siblings, 2 replies; 25+ messages in thread From: Daniel Gustafsson @ 2024-05-03 08:39 UTC (permalink / raw) To: Michael Paquier <[email protected]>; +Cc: Peter Eisentraut <[email protected]>; Jacob Champion <[email protected]>; Thomas Munro <[email protected]>; Postgres hackers <[email protected]>; [email protected]; Tom Lane <[email protected]> > On 1 May 2024, at 06:21, Michael Paquier <[email protected]> wrote: > My remark was originally about pq_init_crypto_lib that does the > locking initialization, and your new patch a bit more, as of: > > ... > > So +1 to remove all this code after a closer lookup. Thanks for review. > I would > recommend to update the documentation of PQinitSSL and PQinitOpenSSL > to tell that these become useless and are deprecated. They are no-ops when linking against v18, but writing an extension which targets all supported versions of postgres along with their respective supported OpenSSL versions make them still required, or am I missing something? > ERR_clear_error(); > - > #ifdef USE_RESOWNER_FOR_HMAC > > Some noise diff. Will fix with a new rebase when once the tree has settled down from the post-freeze fixups in this area. -- Daniel Gustafsson ^ permalink raw reply [nested|flat] 25+ messages in thread
* Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~? @ 2024-05-03 19:02 Peter Eisentraut <[email protected]> parent: Daniel Gustafsson <[email protected]> 1 sibling, 1 reply; 25+ messages in thread From: Peter Eisentraut @ 2024-05-03 19:02 UTC (permalink / raw) To: Daniel Gustafsson <[email protected]>; Michael Paquier <[email protected]>; +Cc: Jacob Champion <[email protected]>; Thomas Munro <[email protected]>; Postgres hackers <[email protected]>; [email protected]; Tom Lane <[email protected]> On 03.05.24 10:39, Daniel Gustafsson wrote: >> I would >> recommend to update the documentation of PQinitSSL and PQinitOpenSSL >> to tell that these become useless and are deprecated. > They are no-ops when linking against v18, but writing an extension which > targets all supported versions of postgres along with their respective > supported OpenSSL versions make them still required, or am I missing something? I don't think extensions come into play here, since this is libpq, so only the shared library interface compatibility matters. ^ permalink raw reply [nested|flat] 25+ messages in thread
* Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~? @ 2024-05-03 19:21 Tom Lane <[email protected]> parent: Peter Eisentraut <[email protected]> 0 siblings, 1 reply; 25+ messages in thread From: Tom Lane @ 2024-05-03 19:21 UTC (permalink / raw) To: Peter Eisentraut <[email protected]>; +Cc: Daniel Gustafsson <[email protected]>; Michael Paquier <[email protected]>; Jacob Champion <[email protected]>; Thomas Munro <[email protected]>; Postgres hackers <[email protected]>; [email protected] Peter Eisentraut <[email protected]> writes: > On 03.05.24 10:39, Daniel Gustafsson wrote: >> They are no-ops when linking against v18, but writing an extension which >> targets all supported versions of postgres along with their respective >> supported OpenSSL versions make them still required, or am I missing something? > I don't think extensions come into play here, since this is libpq, so > only the shared library interface compatibility matters. Yeah, server-side extensions don't really seem to be at hazard, but doesn't the argument apply to client-side applications and libraries that want to work across different PG/OpenSSL versions? regards, tom lane ^ permalink raw reply [nested|flat] 25+ messages in thread
* Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~? @ 2024-05-04 08:08 Daniel Gustafsson <[email protected]> parent: Tom Lane <[email protected]> 0 siblings, 0 replies; 25+ messages in thread From: Daniel Gustafsson @ 2024-05-04 08:08 UTC (permalink / raw) To: Tom Lane <[email protected]>; +Cc: Peter Eisentraut <[email protected]>; Michael Paquier <[email protected]>; Jacob Champion <[email protected]>; Thomas Munro <[email protected]>; Postgres hackers <[email protected]>; [email protected] > On 3 May 2024, at 21:21, Tom Lane <[email protected]> wrote: > > Peter Eisentraut <[email protected]> writes: >> On 03.05.24 10:39, Daniel Gustafsson wrote: >>> They are no-ops when linking against v18, but writing an extension which >>> targets all supported versions of postgres along with their respective >>> supported OpenSSL versions make them still required, or am I missing something? > >> I don't think extensions come into play here, since this is libpq, so >> only the shared library interface compatibility matters. > > Yeah, server-side extensions don't really seem to be at hazard, > but doesn't the argument apply to client-side applications and > libraries that want to work across different PG/OpenSSL versions? Right, I was using "extension" a bit carelessly, what I meant was client-side applications using libpq. -- Daniel Gustafsson ^ permalink raw reply [nested|flat] 25+ messages in thread
* Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~? @ 2024-05-06 23:31 Michael Paquier <[email protected]> parent: Daniel Gustafsson <[email protected]> 1 sibling, 1 reply; 25+ messages in thread From: Michael Paquier @ 2024-05-06 23:31 UTC (permalink / raw) To: Daniel Gustafsson <[email protected]>; +Cc: Peter Eisentraut <[email protected]>; Jacob Champion <[email protected]>; Thomas Munro <[email protected]>; Postgres hackers <[email protected]>; [email protected]; Tom Lane <[email protected]> On Fri, May 03, 2024 at 10:39:15AM +0200, Daniel Gustafsson wrote: > They are no-ops when linking against v18, but writing an extension which > targets all supported versions of postgres along with their respective > supported OpenSSL versions make them still required, or am I missing something? Yeah, that depends on how much version you expect your application to work on. Still it seems to me that there's value in mentioning that if your application does not care about anything older than OpenSSL 1.1.0, like PG 18 assuming that this patch is merged, then these calls are pointless for HEAD. The routine definitions would be around only for the .so compatibility. -- Michael Attachments: [application/pgp-signature] signature.asc (833B, ../../[email protected]/2-signature.asc) download ^ permalink raw reply [nested|flat] 25+ messages in thread
* Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~? @ 2024-05-07 10:36 Daniel Gustafsson <[email protected]> parent: Michael Paquier <[email protected]> 0 siblings, 2 replies; 25+ messages in thread From: Daniel Gustafsson @ 2024-05-07 10:36 UTC (permalink / raw) To: Michael Paquier <[email protected]>; +Cc: Peter Eisentraut <[email protected]>; Jacob Champion <[email protected]>; Thomas Munro <[email protected]>; Postgres hackers <[email protected]>; [email protected]; Tom Lane <[email protected]> > On 7 May 2024, at 01:31, Michael Paquier <[email protected]> wrote: > > On Fri, May 03, 2024 at 10:39:15AM +0200, Daniel Gustafsson wrote: >> They are no-ops when linking against v18, but writing an extension which >> targets all supported versions of postgres along with their respective >> supported OpenSSL versions make them still required, or am I missing something? > > Yeah, that depends on how much version you expect your application to > work on. Still it seems to me that there's value in mentioning that > if your application does not care about anything older than OpenSSL > 1.1.0, like PG 18 assuming that this patch is merged, then these calls > are pointless for HEAD. The routine definitions would be around only > for the .so compatibility. Fair enough. I've taken a stab at documenting that the functions are deprecated, while at the same time documenting when and how they can be used (and be useful). The attached also removes one additional comment in the testcode which is now obsolete (since removing 1.0.1 support really), and fixes the spurious whitespace you detected upthread. -- Daniel Gustafsson Attachments: [application/octet-stream] v13-0002-Remove-pg_strong_random-initialization.patch (1.9K, ../../[email protected]/2-v13-0002-Remove-pg_strong_random-initialization.patch) download | inline diff: From 07546ae71663b2be824b40f70d583195b10c9708 Mon Sep 17 00:00:00 2001 From: Daniel Gustafsson <[email protected]> Date: Thu, 18 Apr 2024 21:39:33 +0200 Subject: [PATCH v13 2/2] Remove pg_strong_random initialization. The random number generator in OpenSSL 1.1.1 was redesigned to provide fork safety by default, thus removing the need for calling RAND_poll after forking to ensure that two processes cannot share the same state. Since we now support 1.1.0 as the minumum version, and 1.1.0 is being increasingly phased out from production use, only perform the RAND_poll initialization for installations running 1.1.0 by checkig the OpenSSL version number. LibreSSL changed random number generator when forking OpenSSL and has provided fork safety since version 2.0.2. This removes the overhead of initializing the RNG for strong random for the vast majority of users for whom it is no longer required. Discussion: https://postgr.es/m/CA+hUKGKh7QrYzu=8yWEUJvXtMVm_CNWH1L_TLWCbZMwbi1XP2Q@mail.gmail.com --- src/port/pg_strong_random.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/port/pg_strong_random.c b/src/port/pg_strong_random.c index 5f2b248425..a8efb2b188 100644 --- a/src/port/pg_strong_random.c +++ b/src/port/pg_strong_random.c @@ -50,17 +50,20 @@ #ifdef USE_OPENSSL +#include <openssl/opensslv.h> #include <openssl/rand.h> void pg_strong_random_init(void) { +#if (OPENSSL_VERSION_NUMBER < 0x10101000L) /* - * 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 not + * required on LibreSSL and no longer required in OpenSSL 1.1.1 and later + * versions. */ RAND_poll(); +#endif } bool -- 2.39.3 (Apple Git-146) [application/octet-stream] v13-0001-Remove-support-for-OpenSSL-1.0.2.patch (35.6K, ../../[email protected]/3-v13-0001-Remove-support-for-OpenSSL-1.0.2.patch) download | inline diff: From 5fcf25d268a29022a8e4f1eea299cc01940fd96c Mon Sep 17 00:00:00 2001 From: Daniel Gustafsson <[email protected]> Date: Thu, 18 Apr 2024 21:37:00 +0200 Subject: [PATCH v13 1/2] Remove support for OpenSSL 1.0.2 OpenSSL 1.0.2 has been EOL from upstream for some time, and is no longer the default OpenSSL version with any vendor which package PostgreSQL. By retiring support for 1.0.2 we can remove a lot of complexity from the tree which is no longer required. Reviewed-by: Jacob Champion <[email protected]> Reviewed-by: Peter Eisentraut <[email protected]> Reviewed-by: Michael Paquier <[email protected]> Discussion: https://postgr.es/m/[email protected] Discussion: https://postgr.es/m/CA+hUKGKh7QrYzu=8yWEUJvXtMVm_CNWH1L_TLWCbZMwbi1XP2Q@mail.gmail.com --- configure | 31 +-- configure.ac | 12 +- contrib/pgcrypto/openssl.c | 8 - doc/src/sgml/installation.sgml | 2 +- doc/src/sgml/libpq.sgml | 36 ++-- meson.build | 23 +-- src/backend/libpq/be-secure-openssl.c | 24 +-- src/common/Makefile | 3 +- src/common/hmac_openssl.c | 20 +- src/common/meson.build | 1 - src/common/protocol_openssl.c | 117 ----------- src/include/common/openssl.h | 14 +- src/include/pg_config.h.in | 15 -- src/interfaces/libpq/fe-connect.c | 18 -- src/interfaces/libpq/fe-secure-openssl.c | 246 ----------------------- src/interfaces/libpq/fe-secure.c | 35 +--- src/interfaces/libpq/libpq-int.h | 13 +- src/test/ssl/t/001_ssltests.pl | 3 +- 18 files changed, 58 insertions(+), 563 deletions(-) diff --git a/configure b/configure index 89644f2249..1181a7347f 100755 --- a/configure +++ b/configure @@ -12330,9 +12330,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 @@ -12564,33 +12564,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 : - cat >>confdefs.h <<_ACEOF -#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 -_ACEOF - -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 : + 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 HAVE_CRYPTO_LOCK 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 - # 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 c7322e292c..2d5e2c2c2c 100644 --- a/configure.ac +++ b/configure.ac @@ -1335,8 +1335,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])]) @@ -1352,12 +1352,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]) 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 1b32d5ca62..daa7d19b77 100644 --- a/doc/src/sgml/installation.sgml +++ b/doc/src/sgml/installation.sgml @@ -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> diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml index 101c676e08..11c0ae0e3c 100644 --- a/doc/src/sgml/libpq.sgml +++ b/doc/src/sgml/libpq.sgml @@ -9830,9 +9830,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 @@ -9840,6 +9842,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> @@ -9855,21 +9861,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> @@ -9886,11 +9879,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"/> diff --git a/meson.build b/meson.build index 1c0579d5a6..12508612a6 100644 --- a/meson.build +++ b/meson.build @@ -1272,26 +1272,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 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 + ['OPENSSL_init_ssl', {'required': true}], + + # Function introduced in OpenSSL 1.0.2, not in LibreSSL. + ['SSL_CTX_set_cert_cb'], + + # Function introduced in OpenSSL 1.1.1, not in LibreSSL. ['X509_get_signature_info'], ] @@ -1314,7 +1305,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 60cf68aac4..85c700cb05 100644 --- a/src/backend/libpq/be-secure-openssl.c +++ b/src/backend/libpq/be-secure-openssl.c @@ -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 @@ -940,7 +927,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(); @@ -963,14 +949,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..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 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 index ae378685e1..e69de29bb2 100644 --- a/src/common/protocol_openssl.c +++ b/src/common/protocol_openssl.c @@ -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/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 */ diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in index f8d3e3b6b8..2b5f5cafab 100644 --- a/src/include/pg_config.h.in +++ b/src/include/pg_config.h.in @@ -54,9 +54,6 @@ /* 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 want to use atomics if available. */ #undef HAVE_ATOMICS @@ -66,9 +63,6 @@ /* 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 @@ -84,9 +78,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 @@ -198,12 +189,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 diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c index 81d278c395..20f1960319 100644 --- a/src/interfaces/libpq/fe-connect.c +++ b/src/interfaces/libpq/fe-connect.c @@ -3336,16 +3336,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 direct SSL is enabled, jump right into SSL handshake. We * will come back here after SSL encryption has been @@ -3523,14 +3513,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 fb6bb911f5..b9bfb8e37e 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; - } } @@ -1980,7 +1748,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(); @@ -2006,14 +1773,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; @@ -2021,13 +1780,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 3691e5ee96..21df8623a7 100644 --- a/src/interfaces/libpq/libpq-int.h +++ b/src/interfaces/libpq/libpq-int.h @@ -580,11 +580,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 */ @@ -763,7 +758,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); @@ -786,19 +780,18 @@ 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); +extern void pgtls_init_library(bool do_ssl); /* * 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. + * if SSL is initialized. * * 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); +extern int pgtls_init(PGconn *conn, bool do_ssl); /* * 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 94ff043c8e..c982aeb361 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 -- 2.39.3 (Apple Git-146) ^ permalink raw reply [nested|flat] 25+ messages in thread
* Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~? @ 2024-05-08 00:45 Michael Paquier <[email protected]> parent: Daniel Gustafsson <[email protected]> 1 sibling, 0 replies; 25+ messages in thread From: Michael Paquier @ 2024-05-08 00:45 UTC (permalink / raw) To: Daniel Gustafsson <[email protected]>; +Cc: Peter Eisentraut <[email protected]>; Jacob Champion <[email protected]>; Thomas Munro <[email protected]>; Postgres hackers <[email protected]>; [email protected]; Tom Lane <[email protected]> On Tue, May 07, 2024 at 12:36:24PM +0200, Daniel Gustafsson wrote: > Fair enough. I've taken a stab at documenting that the functions are > deprecated, while at the same time documenting when and how they can be used > (and be useful). The attached also removes one additional comment in the > testcode which is now obsolete (since removing 1.0.1 support really), and fixes > the spurious whitespace you detected upthread. + This function is deprecated and only present for backwards compatibility, + it does nothing. [...] + <xref linkend="libpq-PQinitSSL"/> and <xref linkend="libpq-PQinitOpenSSL"/> + are maintained for backwards compatibility, but are no longer required + since <productname>PostgreSQL</productname> 18. LGTM, thanks for doing this! -- Michael Attachments: [application/pgp-signature] signature.asc (833B, ../../[email protected]/2-signature.asc) download ^ permalink raw reply [nested|flat] 25+ messages in thread
* Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~? @ 2024-07-11 21:22 Peter Eisentraut <[email protected]> parent: Daniel Gustafsson <[email protected]> 1 sibling, 0 replies; 25+ messages in thread From: Peter Eisentraut @ 2024-07-11 21:22 UTC (permalink / raw) To: Daniel Gustafsson <[email protected]>; Michael Paquier <[email protected]>; +Cc: Jacob Champion <[email protected]>; Thomas Munro <[email protected]>; Postgres hackers <[email protected]>; [email protected]; Tom Lane <[email protected]> On 07.05.24 11:36, Daniel Gustafsson wrote: >> Yeah, that depends on how much version you expect your application to >> work on. Still it seems to me that there's value in mentioning that >> if your application does not care about anything older than OpenSSL >> 1.1.0, like PG 18 assuming that this patch is merged, then these calls >> are pointless for HEAD. The routine definitions would be around only >> for the .so compatibility. > > Fair enough. I've taken a stab at documenting that the functions are > deprecated, while at the same time documenting when and how they can be used > (and be useful). The attached also removes one additional comment in the > testcode which is now obsolete (since removing 1.0.1 support really), and fixes > the spurious whitespace you detected upthread. The 0001 patch removes the functions pgtls_init_library() and pgtls_init() but keeps the declarations in libpq-int.h. This should be fixed. ^ permalink raw reply [nested|flat] 25+ messages in thread
end of thread, other threads:[~2024-07-11 21:22 UTC | newest] Thread overview: 25+ messages (download: mbox mbox.gz follow: Atom feed) -- links below jump to the message on this page -- 2021-06-01 17:49 [PATCH 4/9] Remove the last vestiges of Exporter from PostgresNode Andrew Dunstan <[email protected]> 2024-04-15 05:04 Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~? Michael Paquier <[email protected]> 2024-04-15 09:07 ` Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~? Daniel Gustafsson <[email protected]> 2024-04-15 23:03 ` Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~? Michael Paquier <[email protected]> 2024-04-16 08:17 ` Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~? Daniel Gustafsson <[email protected]> 2024-04-18 10:53 ` Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~? Peter Eisentraut <[email protected]> 2024-04-18 20:26 ` Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~? Daniel Gustafsson <[email protected]> 2024-04-19 05:37 ` Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~? Michael Paquier <[email protected]> 2024-04-19 06:55 ` Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~? Daniel Gustafsson <[email protected]> 2024-04-19 08:06 ` Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~? Peter Eisentraut <[email protected]> 2024-04-23 20:08 ` Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~? Daniel Gustafsson <[email protected]> 2024-04-23 22:20 ` Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~? Michael Paquier <[email protected]> 2024-04-24 11:31 ` Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~? Daniel Gustafsson <[email protected]> 2024-04-25 03:49 ` Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~? Michael Paquier <[email protected]> 2024-04-27 18:32 ` Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~? Daniel Gustafsson <[email protected]> 2024-04-27 18:33 ` Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~? Daniel Gustafsson <[email protected]> 2024-05-01 04:21 ` Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~? Michael Paquier <[email protected]> 2024-05-03 08:39 ` Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~? Daniel Gustafsson <[email protected]> 2024-05-03 19:02 ` Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~? Peter Eisentraut <[email protected]> 2024-05-03 19:21 ` Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~? Tom Lane <[email protected]> 2024-05-04 08:08 ` Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~? Daniel Gustafsson <[email protected]> 2024-05-06 23:31 ` Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~? Michael Paquier <[email protected]> 2024-05-07 10:36 ` Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~? Daniel Gustafsson <[email protected]> 2024-05-08 00:45 ` Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~? Michael Paquier <[email protected]> 2024-07-11 21:22 ` Re: Cutting support for OpenSSL 1.0.1 and 1.0.2 in 17~? Peter Eisentraut <[email protected]>
This inbox is served by agora; see mirroring instructions for how to clone and mirror all data and code used for this inbox