Hi all,

$Subject says it all.  Based on an analysis of the code, I can note
the following when it comes to the removal of 1.0.1:
- A lot of code related to channel binding is now simplified as
X509_get_signature_nid() always exists, mostly around its CFLAGS.
- This removes the comments related to 1.0.1e introduced by 74242c2.

Then for 1.0.2, the following flags can be gone:
HAVE_ASN1_STRING_GET0_DATA
HAVE_BIO_GET_DATA
HAVE_BIO_METH_NEW
HAVE_HMAC_CTX_FREE
HAVE_HMAC_CTX_NEW

It would be nice to remove CRYPTO_lock(), but from what I can see the
function still exists in LibreSSL, meaning that libpq locking wouldn't
be thread-safe if these function's paths are removed.

Another related question is how much do we care about builds with
LibreSSL with MSVC?  This patch sets takes the simple path of assuming
that this has never been really tested, and if you look at the MSVC
scripts on HEAD we rely on a version number from OpenSSL, which is not
something LibreSSL copes nicely with already, as documented in
configure.ac.

OpenSSL 1.0.2 has been EOLd at the end of 2019, and 1.0.1 had its last
minor release in September 2019, so with Postgres 17 targetted in
September/October 2024, we would be five years behind that.

Last comes the buildfarm, and I suspect that a few animals are
building with 1.0.2.  Among what I have spotted:
- wobbegong and vulpes, on Fedora 27, though I could not find
references about the version used there.
- bonito, on Fedora 29.
- SUSE 12 SP{4,5} have 1.0.2 as their newer version.
- butterflyfish may not like that, if I recall correctly, as it should
have 1.0.2.

So, it seems to me that 1.0.1 would be a rather silent move for the
buildfarm, and 1.0.2 could lead to some noise.  Note as well that
1.1.0 support has been stopped by upstream at the same time as 1.0.1,
with a last minor release in September 2019, though that feels like a
huge jump at this stage.  On a code basis, removing 1.0.1 leads to the
most cleanup.  The removal of 1.0.2 would be nice, but the tweaks
needed for LibreSSL make it less appealing.

Attached are two patches to remove support for 1.0.1 and 1.0.2 for
now, kept separated for clarity, to be considered as something to do
at the beginning of the v17 cycle.  0001 is in a rather good shape
seen from here.

Now, for 0002 and the removal of 1.0.2, I am seeing two things once
OPENSSL_API_COMPAT is bumped from 0x10002000L to 0x10100000L:
- be-secure-openssl.c requires an extra openssl/bn.h, which is not a
big deal, from what I get.
- Much more interesting: OpenSSL_add_all_algorithms() has two macros
that get removed, see include/openssl/evp.h:
#  ifdef OPENSSL_LOAD_CONF
#   define OpenSSL_add_all_algorithms() \
    OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS \
                        | OPENSSL_INIT_ADD_ALL_DIGESTS \
                        | OPENSSL_INIT_LOAD_CONFIG, NULL)
#  else
#   define OpenSSL_add_all_algorithms() \
    OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS \
                        | OPENSSL_INIT_ADD_ALL_DIGESTS, NULL)
#  endif

The part where I am not quite sure of what to do is about
OPENSSL_LOAD_CONF.  We could call directly OPENSSL_init_crypto() and
add OPENSSL_INIT_LOAD_CONFIG if building with OPENSSL_LOAD_CONF, but
it feels a bit ugly to copy-paste this code from OpenSSL itself.
Note that patch 0002 still has OPENSSL_API_COMPAT at 0x10002000L.
OPENSSL_init_crypto() looks to be in LibreSSL, and it is new in
OpenSSL 1.1.0, so switching the minimum to OpenSSL 1.1.0 should not
require a new cflags on this one.

Thoughts?
--
Michael
From 553b9eb7e24250a92d7551cb28a301d9e63ba7ad Mon Sep 17 00:00:00 2001
From: Michael Paquier <mich...@paquier.xyz>
Date: Wed, 24 May 2023 16:22:02 +0900
Subject: [PATCH v1 1/2] Remove support for OpenSSL 1.0.1

A few notes about that:
- This simplifies a lot of code areas related to channel binding, as
X509_get_signature_nid() always exists.
- This removes the comments related to 1.0.1e introduced by 74242c2.
- Do we need to care about the case of building the Postgres code with
LibreSSL on Windows for the MSVC scripts, leading to the removal of the
check with HAVE_SSL_CTX_SET_CERT_CB?
---
 src/include/libpq/libpq-be.h             |  6 +---
 src/include/pg_config.h.in               |  3 --
 src/backend/libpq/auth-scram.c           | 20 ++++++------
 src/backend/libpq/be-secure-openssl.c    |  4 ---
 src/interfaces/libpq/fe-auth-scram.c     |  8 ++---
 src/interfaces/libpq/fe-auth.c           |  2 +-
 src/interfaces/libpq/fe-secure-openssl.c |  4 ---
 src/interfaces/libpq/libpq-int.h         |  6 +---
 src/test/ssl/t/002_scram.pl              | 41 ++++--------------------
 doc/src/sgml/installation.sgml           |  2 +-
 configure                                | 16 ++++-----
 configure.ac                             |  9 +++---
 meson.build                              |  5 ++-
 src/tools/msvc/Solution.pm               | 10 +-----
 14 files changed, 38 insertions(+), 98 deletions(-)

diff --git a/src/include/libpq/libpq-be.h b/src/include/libpq/libpq-be.h
index 3b2ce9908f..b80757eabf 100644
--- a/src/include/libpq/libpq-be.h
+++ b/src/include/libpq/libpq-be.h
@@ -305,12 +305,8 @@ extern void be_tls_get_peer_serial(Port *port, char *ptr, size_t len);
  *
  * The result is a palloc'd hash of the server certificate with its
  * size, and NULL if there is no certificate available.
- *
- * This is not supported with old versions of OpenSSL that don't have
- * the X509_get_signature_nid() function.
  */
-#if defined(USE_OPENSSL) && (defined(HAVE_X509_GET_SIGNATURE_NID) || defined(HAVE_X509_GET_SIGNATURE_INFO))
-#define HAVE_BE_TLS_GET_CERTIFICATE_HASH
+#ifdef USE_OPENSSL
 extern char *be_tls_get_certificate_hash(Port *port, size_t *len);
 #endif
 
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index 6d572c3820..ca3a49c552 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -529,9 +529,6 @@
 /* Define to 1 if you have the `X509_get_signature_info' function. */
 #undef HAVE_X509_GET_SIGNATURE_INFO
 
-/* Define to 1 if you have the `X509_get_signature_nid' function. */
-#undef HAVE_X509_GET_SIGNATURE_NID
-
 /* Define to 1 if the assembler supports X86_64's POPCNTQ instruction. */
 #undef HAVE_X86_64_POPCNTQ
 
diff --git a/src/backend/libpq/auth-scram.c b/src/backend/libpq/auth-scram.c
index 9b286aa4d7..2729a9d60c 100644
--- a/src/backend/libpq/auth-scram.c
+++ b/src/backend/libpq/auth-scram.c
@@ -209,10 +209,9 @@ scram_get_mechanisms(Port *port, StringInfo buf)
 	/*
 	 * Advertise the mechanisms in decreasing order of importance.  So the
 	 * channel-binding variants go first, if they are supported.  Channel
-	 * binding is only supported with SSL, and only if the SSL implementation
-	 * has a function to get the certificate's hash.
+	 * binding is only supported with SSL.
 	 */
-#ifdef HAVE_BE_TLS_GET_CERTIFICATE_HASH
+#ifdef USE_OPENSSL
 	if (port->ssl_in_use)
 	{
 		appendStringInfoString(buf, SCRAM_SHA_256_PLUS_NAME);
@@ -251,13 +250,12 @@ scram_init(Port *port, const char *selected_mech, const char *shadow_pass)
 	/*
 	 * Parse the selected mechanism.
 	 *
-	 * Note that if we don't support channel binding, either because the SSL
-	 * implementation doesn't support it or we're not using SSL at all, we
-	 * would not have advertised the PLUS variant in the first place.  If the
-	 * client nevertheless tries to select it, it's a protocol violation like
-	 * selecting any other SASL mechanism we don't support.
+	 * Note that if we don't support channel binding if we're not using SSL at
+	 * all, we would not have advertised the PLUS variant in the first place.
+	 * If the client nevertheless tries to select it, it's a protocol
+	 * violation like selecting any other SASL mechanism we don't support.
 	 */
-#ifdef HAVE_BE_TLS_GET_CERTIFICATE_HASH
+#ifdef USE_OPENSSL
 	if (strcmp(selected_mech, SCRAM_SHA_256_PLUS_NAME) == 0 && port->ssl_in_use)
 		state->channel_binding_in_use = true;
 	else
@@ -1010,7 +1008,7 @@ read_client_first_message(scram_state *state, const char *input)
 						 errmsg("malformed SCRAM message"),
 						 errdetail("The client selected SCRAM-SHA-256-PLUS, but the SCRAM message does not include channel binding data.")));
 
-#ifdef HAVE_BE_TLS_GET_CERTIFICATE_HASH
+#ifdef USE_OPENSSL
 			if (state->port->ssl_in_use)
 				ereport(ERROR,
 						(errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
@@ -1306,7 +1304,7 @@ read_client_final_message(scram_state *state, const char *input)
 	channel_binding = read_attr_value(&p, 'c');
 	if (state->channel_binding_in_use)
 	{
-#ifdef HAVE_BE_TLS_GET_CERTIFICATE_HASH
+#ifdef USE_OPENSSL
 		const char *cbind_data = NULL;
 		size_t		cbind_data_len = 0;
 		size_t		cbind_header_len;
diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c
index 05276ab95c..658b09988d 100644
--- a/src/backend/libpq/be-secure-openssl.c
+++ b/src/backend/libpq/be-secure-openssl.c
@@ -831,8 +831,6 @@ be_tls_write(Port *port, void *ptr, size_t len, int *waitfor)
  *
  * These functions are closely modelled on the standard socket BIO in OpenSSL;
  * see sock_read() and sock_write() in OpenSSL's crypto/bio/bss_sock.c.
- * XXX OpenSSL 1.0.1e considers many more errcodes than just EINTR as reasons
- * to retry; do we need to adopt their logic for that?
  */
 
 #ifndef HAVE_BIO_GET_DATA
@@ -1429,7 +1427,6 @@ be_tls_get_peer_serial(Port *port, char *ptr, size_t len)
 		ptr[0] = '\0';
 }
 
-#if defined(HAVE_X509_GET_SIGNATURE_NID) || defined(HAVE_X509_GET_SIGNATURE_INFO)
 char *
 be_tls_get_certificate_hash(Port *port, size_t *len)
 {
@@ -1488,7 +1485,6 @@ be_tls_get_certificate_hash(Port *port, size_t *len)
 
 	return cert_hash;
 }
-#endif
 
 /*
  * Convert an X509 subject name to a cstring.
diff --git a/src/interfaces/libpq/fe-auth-scram.c b/src/interfaces/libpq/fe-auth-scram.c
index 6b779ec7ff..441b776330 100644
--- a/src/interfaces/libpq/fe-auth-scram.c
+++ b/src/interfaces/libpq/fe-auth-scram.c
@@ -401,7 +401,7 @@ build_client_first_message(fe_scram_state *state)
 		Assert(conn->ssl_in_use);
 		appendPQExpBufferStr(&buf, "p=tls-server-end-point");
 	}
-#ifdef HAVE_PGTLS_GET_PEER_CERTIFICATE_HASH
+#ifdef USE_OPENSSL
 	else if (conn->channel_binding[0] != 'd' && /* disable */
 			 conn->ssl_in_use)
 	{
@@ -474,7 +474,7 @@ build_client_final_message(fe_scram_state *state)
 	 */
 	if (strcmp(state->sasl_mechanism, SCRAM_SHA_256_PLUS_NAME) == 0)
 	{
-#ifdef HAVE_PGTLS_GET_PEER_CERTIFICATE_HASH
+#ifdef USE_OPENSSL
 		char	   *cbind_data = NULL;
 		size_t		cbind_data_len = 0;
 		size_t		cbind_header_len;
@@ -540,9 +540,9 @@ build_client_final_message(fe_scram_state *state)
 		appendPQExpBufferStr(&conn->errorMessage,
 							 "channel binding not supported by this build\n");
 		return NULL;
-#endif							/* HAVE_PGTLS_GET_PEER_CERTIFICATE_HASH */
+#endif							/* USE_OPENSSL */
 	}
-#ifdef HAVE_PGTLS_GET_PEER_CERTIFICATE_HASH
+#ifdef USE_OPENSSL
 	else if (conn->channel_binding[0] != 'd' && /* disable */
 			 conn->ssl_in_use)
 		appendPQExpBufferStr(&buf, "c=eSws");	/* base64 of "y,," */
diff --git a/src/interfaces/libpq/fe-auth.c b/src/interfaces/libpq/fe-auth.c
index de0e13e50d..e730c1a34a 100644
--- a/src/interfaces/libpq/fe-auth.c
+++ b/src/interfaces/libpq/fe-auth.c
@@ -478,7 +478,7 @@ pg_SASL_init(PGconn *conn, int payloadlen)
 			{
 				/* The server has offered SCRAM-SHA-256-PLUS. */
 
-#ifdef HAVE_PGTLS_GET_PEER_CERTIFICATE_HASH
+#ifdef USE_OPENSSL
 				/*
 				 * The client supports channel binding, which is chosen if
 				 * channel_binding is not disabled.
diff --git a/src/interfaces/libpq/fe-secure-openssl.c b/src/interfaces/libpq/fe-secure-openssl.c
index 390c888c96..bea71660ab 100644
--- a/src/interfaces/libpq/fe-secure-openssl.c
+++ b/src/interfaces/libpq/fe-secure-openssl.c
@@ -364,7 +364,6 @@ pgtls_write(PGconn *conn, const void *ptr, size_t len)
 	return n;
 }
 
-#if defined(HAVE_X509_GET_SIGNATURE_NID) || defined(HAVE_X509_GET_SIGNATURE_INFO)
 char *
 pgtls_get_peer_certificate_hash(PGconn *conn, size_t *len)
 {
@@ -439,7 +438,6 @@ pgtls_get_peer_certificate_hash(PGconn *conn, size_t *len)
 
 	return cert_hash;
 }
-#endif							/* HAVE_X509_GET_SIGNATURE_NID */
 
 /* ------------------------------------------------------------ */
 /*						OpenSSL specific code					*/
@@ -1826,8 +1824,6 @@ PQsslAttribute(PGconn *conn, const char *attribute_name)
  *
  * These functions are closely modelled on the standard socket BIO in OpenSSL;
  * see sock_read() and sock_write() in OpenSSL's crypto/bio/bss_sock.c.
- * XXX OpenSSL 1.0.1e considers many more errcodes than just EINTR as reasons
- * to retry; do we need to adopt their logic for that?
  */
 
 #ifndef HAVE_BIO_GET_DATA
diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h
index f1854f9919..33bacd8e65 100644
--- a/src/interfaces/libpq/libpq-int.h
+++ b/src/interfaces/libpq/libpq-int.h
@@ -833,12 +833,8 @@ extern ssize_t pgtls_write(PGconn *conn, const void *ptr, size_t len);
  *
  * NULL is sent back to the caller in the event of an error, with an
  * error message for the caller to consume.
- *
- * This is not supported with old versions of OpenSSL that don't have
- * the X509_get_signature_nid() function.
  */
-#if defined(USE_OPENSSL) && (defined(HAVE_X509_GET_SIGNATURE_NID) || defined(HAVE_X509_GET_SIGNATURE_INFO))
-#define HAVE_PGTLS_GET_PEER_CERTIFICATE_HASH
+#ifdef USE_OPENSSL
 extern char *pgtls_get_peer_certificate_hash(PGconn *conn, size_t *len);
 #endif
 
diff --git a/src/test/ssl/t/002_scram.pl b/src/test/ssl/t/002_scram.pl
index 28c54bdb09..3a798e1a56 100644
--- a/src/test/ssl/t/002_scram.pl
+++ b/src/test/ssl/t/002_scram.pl
@@ -44,9 +44,6 @@ my $SERVERHOSTADDR = '127.0.0.1';
 # This is the pattern to use in pg_hba.conf to match incoming connections.
 my $SERVERHOSTCIDR = '127.0.0.1/32';
 
-# Determine whether build supports tls-server-end-point.
-my $supports_tls_server_end_point =
-  check_pg_config("#define HAVE_X509_GET_SIGNATURE_NID 1");
 # Determine whether build supports detection of hash algorithms for
 # RSA-PSS certificates.
 my $supports_rsapss_certs =
@@ -90,21 +87,9 @@ $node->connect_fails(
 	expected_stderr => qr/invalid channel_binding value: "invalid_value"/);
 $node->connect_ok("$common_connstr user=ssltestuser channel_binding=disable",
 	"SCRAM with SSL and channel_binding=disable");
-if ($supports_tls_server_end_point)
-{
-	$node->connect_ok(
-		"$common_connstr user=ssltestuser channel_binding=require",
-		"SCRAM with SSL and channel_binding=require");
-}
-else
-{
-	$node->connect_fails(
-		"$common_connstr user=ssltestuser channel_binding=require",
-		"SCRAM with SSL and channel_binding=require",
-		expected_stderr =>
-		  qr/channel binding is required, but server did not offer an authentication method that supports channel binding/
-	);
-}
+$node->connect_ok(
+	"$common_connstr user=ssltestuser channel_binding=require",
+	"SCRAM with SSL and channel_binding=require");
 
 # Now test when the user has an MD5-encrypted password; should fail
 $node->connect_fails(
@@ -152,22 +137,10 @@ $node->connect_fails(
 	expected_stderr =>
 	  qr/channel binding required but not supported by server's authentication request/
 );
-if ($supports_tls_server_end_point)
-{
-	$node->connect_ok(
-		"$common_connstr user=ssltestuser channel_binding=require require_auth=scram-sha-256",
-		"SCRAM with SSL, channel_binding=require, and require_auth=scram-sha-256"
-	);
-}
-else
-{
-	$node->connect_fails(
-		"$common_connstr user=ssltestuser channel_binding=require require_auth=scram-sha-256",
-		"SCRAM with SSL, channel_binding=require, and require_auth=scram-sha-256",
-		expected_stderr =>
-		  qr/channel binding is required, but server did not offer an authentication method that supports channel binding/
-	);
-}
+$node->connect_ok(
+	"$common_connstr user=ssltestuser channel_binding=require require_auth=scram-sha-256",
+	"SCRAM with SSL, channel_binding=require, and require_auth=scram-sha-256"
+);
 
 # Now test with a server certificate that uses the RSA-PSS algorithm.
 # This checks that the certificate can be loaded and that channel binding
diff --git a/doc/src/sgml/installation.sgml b/doc/src/sgml/installation.sgml
index 75dc81a0a9..e9d797417a 100644
--- a/doc/src/sgml/installation.sgml
+++ b/doc/src/sgml/installation.sgml
@@ -275,7 +275,7 @@ documentation.  See standalone-profile.xsl for details.
       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.1.
+      required version is 1.0.2.
      </para>
     </listitem>
 
diff --git a/configure b/configure
index 15daccc87f..dbb37f3b83 100755
--- a/configure
+++ b/configure
@@ -12744,9 +12744,9 @@ if test "$with_openssl" = yes ; then
 fi
 
 if test "$with_ssl" = openssl ; then
-    # Minimum required OpenSSL version is 1.0.1
+    # Minimum required OpenSSL version is 1.0.2
 
-$as_echo "#define OPENSSL_API_COMPAT 0x10001000L" >>confdefs.h
+$as_echo "#define OPENSSL_API_COMPAT 0x10002000L" >>confdefs.h
 
   if test "$PORTNAME" != "win32"; then
      { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CRYPTO_new_ex_data in -lcrypto" >&5
@@ -12961,15 +12961,13 @@ else
 fi
 
   fi
-  # Functions introduced in OpenSSL 1.0.2. LibreSSL does not have
-  # SSL_CTX_set_cert_cb().
-  for ac_func in X509_get_signature_nid SSL_CTX_set_cert_cb
+  # LibreSSL does not have SSL_CTX_set_cert_cb().
+  for ac_func in SSL_CTX_set_cert_cb
 do :
-  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+  ac_fn_c_check_func "$LINENO" "SSL_CTX_set_cert_cb" "ac_cv_func_SSL_CTX_set_cert_cb"
+if test "x$ac_cv_func_SSL_CTX_set_cert_cb" = xyes; then :
   cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+#define HAVE_SSL_CTX_SET_CERT_CB 1
 _ACEOF
 
 fi
diff --git a/configure.ac b/configure.ac
index 97f5be6c73..94ae1d33c2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1367,8 +1367,8 @@ fi
 
 if test "$with_ssl" = openssl ; then
   dnl Order matters!
-  # Minimum required OpenSSL version is 1.0.1
-  AC_DEFINE(OPENSSL_API_COMPAT, [0x10001000L],
+  # Minimum required OpenSSL version is 1.0.2
+  AC_DEFINE(OPENSSL_API_COMPAT, [0x10002000L],
             [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])])
@@ -1377,9 +1377,8 @@ if test "$with_ssl" = openssl ; then
      AC_SEARCH_LIBS(CRYPTO_new_ex_data, [eay32 crypto], [], [AC_MSG_ERROR([library 'eay32' or 'crypto' is required for OpenSSL])])
      AC_SEARCH_LIBS(SSL_new, [ssleay32 ssl], [], [AC_MSG_ERROR([library 'ssleay32' or 'ssl' is required for OpenSSL])])
   fi
-  # Functions introduced in OpenSSL 1.0.2. LibreSSL does not have
-  # SSL_CTX_set_cert_cb().
-  AC_CHECK_FUNCS([X509_get_signature_nid SSL_CTX_set_cert_cb])
+  # LibreSSL does not have SSL_CTX_set_cert_cb().
+  AC_CHECK_FUNCS([SSL_CTX_set_cert_cb])
   # Functions introduced in OpenSSL 1.1.0. We used to check for
   # OPENSSL_VERSION_NUMBER, but that didn't work with 1.1.0, because LibreSSL
   # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
diff --git a/meson.build b/meson.build
index 096044628c..5cf13e3b36 100644
--- a/meson.build
+++ b/meson.build
@@ -1268,9 +1268,8 @@ if sslopt in ['auto', 'openssl']
       ['CRYPTO_new_ex_data', {'required': true}],
       ['SSL_new', {'required': true}],
 
-      # Functions introduced in OpenSSL 1.0.2.
-      ['X509_get_signature_nid'],
-      ['SSL_CTX_set_cert_cb'], # not in LibreSSL
+      # Function 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
diff --git a/src/tools/msvc/Solution.pm b/src/tools/msvc/Solution.pm
index b6d31c3583..e6d8f9fedc 100644
--- a/src/tools/msvc/Solution.pm
+++ b/src/tools/msvc/Solution.pm
@@ -371,7 +371,6 @@ sub GenerateFiles
 		HAVE_UUID_UUID_H => undef,
 		HAVE_WCSTOMBS_L => 1,
 		HAVE_VISIBILITY_ATTRIBUTE => undef,
-		HAVE_X509_GET_SIGNATURE_NID => 1,
 		HAVE_X509_GET_SIGNATURE_INFO => undef,
 		HAVE_X86_64_POPCNTQ => undef,
 		HAVE__BOOL => undef,
@@ -488,6 +487,7 @@ sub GenerateFiles
 	if ($self->{options}->{openssl})
 	{
 		$define{USE_OPENSSL} = 1;
+		$define{HAVE_SSL_CTX_SET_CERT_CB} = 1;
 
 		my ($digit1, $digit2, $digit3) = $self->GetOpenSSLVersion();
 
@@ -509,14 +509,6 @@ sub GenerateFiles
 			$define{HAVE_HMAC_CTX_NEW} = 1;
 			$define{HAVE_OPENSSL_INIT_SSL} = 1;
 		}
-
-		# Symbols needed with OpenSSL 1.0.2 and above.
-		if (   ($digit1 >= '3' && $digit2 >= '0' && $digit3 >= '0')
-			|| ($digit1 >= '1' && $digit2 >= '1' && $digit3 >= '0')
-			|| ($digit1 >= '1' && $digit2 >= '0' && $digit3 >= '2'))
-		{
-			$define{HAVE_SSL_CTX_SET_CERT_CB} = 1;
-		}
 	}
 
 	$self->GenerateConfigHeader('src/include/pg_config.h', \%define, 1);
-- 
2.40.1

From 0bbb001513d07b47223b4dbd8950241c327ca731 Mon Sep 17 00:00:00 2001
From: Michael Paquier <mich...@paquier.xyz>
Date: Wed, 24 May 2023 17:08:24 +0900
Subject: [PATCH v1 2/2] Remove support for OpenSSL 1.0.2

This allows the removal of the following flags:
HAVE_ASN1_STRING_GET0_DATA
HAVE_BIO_GET_DATA
HAVE_BIO_METH_NEW
HAVE_HMAC_CTX_FREE
HAVE_HMAC_CTX_NEW

OpenSSL 1.1.0 has removed CRYPTO_lock(), but LibreSSL requires it.  On
the contrary, OPENSSL_init_ssl() is not in OpenSSL.
---
 src/include/pg_config.h.in               | 15 ------------
 src/backend/libpq/be-secure-openssl.c    | 14 ------------
 src/common/hmac_openssl.c                | 17 --------------
 src/interfaces/libpq/fe-secure-openssl.c | 22 ------------------
 src/interfaces/libpq/libpq-int.h         |  5 +---
 doc/src/sgml/installation.sgml           |  2 +-
 configure                                | 29 +++++++-----------------
 configure.ac                             | 21 ++++++++---------
 meson.build                              | 20 ++++++----------
 src/tools/msvc/Solution.pm               | 18 +--------------
 10 files changed, 27 insertions(+), 136 deletions(-)

diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index ca3a49c552..80b6ddec73 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -58,9 +58,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
 
@@ -70,12 +67,6 @@
 /* Define to 1 if you have the `backtrace_symbols' function. */
 #undef HAVE_BACKTRACE_SYMBOLS
 
-/* Define to 1 if you have the `BIO_get_data' function. */
-#undef HAVE_BIO_GET_DATA
-
-/* 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
 
@@ -214,12 +205,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/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c
index 658b09988d..61ad6b3476 100644
--- a/src/backend/libpq/be-secure-openssl.c
+++ b/src/backend/libpq/be-secure-openssl.c
@@ -833,11 +833,6 @@ be_tls_write(Port *port, void *ptr, size_t len, int *waitfor)
  * see sock_read() and sock_write() in OpenSSL's crypto/bio/bss_sock.c.
  */
 
-#ifndef HAVE_BIO_GET_DATA
-#define BIO_get_data(bio) (bio->ptr)
-#define BIO_set_data(bio, data) (bio->ptr = data)
-#endif
-
 static BIO_METHOD *my_bio_methods = NULL;
 
 static int
@@ -887,7 +882,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();
@@ -910,14 +904,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/hmac_openssl.c b/src/common/hmac_openssl.c
index 12be542fa2..068b098da6 100644
--- a/src/common/hmac_openssl.c
+++ b/src/common/hmac_openssl.c
@@ -41,11 +41,7 @@
  * a failure status back to the caller.
  */
 #ifndef FRONTEND
-#ifdef HAVE_HMAC_CTX_NEW
 #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)
@@ -113,14 +109,10 @@ pg_hmac_create(pg_cryptohash_type type)
 	 * previous runs.
 	 */
 	ERR_clear_error();
-#ifdef HAVE_HMAC_CTX_NEW
 #ifndef FRONTEND
 	ResourceOwnerEnlargeHMAC(CurrentResourceOwner);
 #endif
 	ctx->hmacctx = HMAC_CTX_new();
-#else
-	ctx->hmacctx = ALLOC(sizeof(HMAC_CTX));
-#endif
 
 	if (ctx->hmacctx == NULL)
 	{
@@ -134,14 +126,10 @@ pg_hmac_create(pg_cryptohash_type type)
 		return NULL;
 	}
 
-#ifdef HAVE_HMAC_CTX_NEW
 #ifndef FRONTEND
 	ctx->resowner = CurrentResourceOwner;
 	ResourceOwnerRememberHMAC(CurrentResourceOwner, PointerGetDatum(ctx));
 #endif
-#else
-	memset(ctx->hmacctx, 0, sizeof(HMAC_CTX));
-#endif							/* HAVE_HMAC_CTX_NEW */
 
 	return ctx;
 }
@@ -300,15 +288,10 @@ pg_hmac_free(pg_hmac_ctx *ctx)
 	if (ctx == NULL)
 		return;
 
-#ifdef HAVE_HMAC_CTX_FREE
 	HMAC_CTX_free(ctx->hmacctx);
 #ifndef FRONTEND
 	ResourceOwnerForgetHMAC(ctx->resowner, PointerGetDatum(ctx));
 #endif
-#else
-	explicit_bzero(ctx->hmacctx, sizeof(HMAC_CTX));
-	FREE(ctx->hmacctx);
-#endif
 
 	explicit_bzero(ctx, sizeof(pg_hmac_ctx));
 	FREE(ctx);
diff --git a/src/interfaces/libpq/fe-secure-openssl.c b/src/interfaces/libpq/fe-secure-openssl.c
index bea71660ab..123ba4d04c 100644
--- a/src/interfaces/libpq/fe-secure-openssl.c
+++ b/src/interfaces/libpq/fe-secure-openssl.c
@@ -511,11 +511,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. */
@@ -546,11 +542,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);
@@ -1826,11 +1818,6 @@ PQsslAttribute(PGconn *conn, const char *attribute_name)
  * see sock_read() and sock_write() in OpenSSL's crypto/bio/bss_sock.c.
  */
 
-#ifndef HAVE_BIO_GET_DATA
-#define BIO_get_data(bio) (bio->ptr)
-#define BIO_set_data(bio, data) (bio->ptr = data)
-#endif
-
 static BIO_METHOD *my_bio_methods;
 
 static int
@@ -1899,7 +1886,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();
@@ -1927,14 +1913,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/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h
index 33bacd8e65..d3a86876e0 100644
--- a/src/interfaces/libpq/libpq-int.h
+++ b/src/interfaces/libpq/libpq-int.h
@@ -564,10 +564,7 @@ struct pg_conn
 								 * 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. */
+								 * been done for this connection */
 #endif							/* USE_OPENSSL */
 #endif							/* USE_SSL */
 
diff --git a/doc/src/sgml/installation.sgml b/doc/src/sgml/installation.sgml
index e9d797417a..f2dc53dcb5 100644
--- a/doc/src/sgml/installation.sgml
+++ b/doc/src/sgml/installation.sgml
@@ -275,7 +275,7 @@ documentation.  See standalone-profile.xsl for details.
       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/configure b/configure
index dbb37f3b83..748977c3bb 100755
--- a/configure
+++ b/configure
@@ -12744,7 +12744,8 @@ 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.  API compatibility is kept at
+  # 1.0.2 for OpenSSL_add_all_algorithms().
 
 $as_echo "#define OPENSSL_API_COMPAT 0x10002000L" >>confdefs.h
 
@@ -12961,24 +12962,11 @@ else
 fi
 
   fi
-  # LibreSSL does not have SSL_CTX_set_cert_cb().
-  for ac_func in SSL_CTX_set_cert_cb
-do :
-  ac_fn_c_check_func "$LINENO" "SSL_CTX_set_cert_cb" "ac_cv_func_SSL_CTX_set_cert_cb"
-if test "x$ac_cv_func_SSL_CTX_set_cert_cb" = xyes; then :
-  cat >>confdefs.h <<_ACEOF
-#define HAVE_SSL_CTX_SET_CERT_CB 1
-_ACEOF
-
-fi
-done
-
-  # 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 not in LibreSSL.  We used to check for OPENSSL_VERSION_NUMBER,
+  # but that didn't work with OpenSSL 1.1.0, because LibreSSL defines
+  # OPENSSL_VERSION_NUMBER to claim version 2.0.0. So check for individual
   # functions.
-  for ac_func in OPENSSL_init_ssl BIO_get_data BIO_meth_new ASN1_STRING_get0_data HMAC_CTX_new HMAC_CTX_free
+  for ac_func in SSL_CTX_set_cert_cb 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"
@@ -12990,9 +12978,8 @@ _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.
+  # Function included in LibreSSL, not in OpenSSL.  This is required for
+  # thread safety.
   for ac_func in CRYPTO_lock
 do :
   ac_fn_c_check_func "$LINENO" "CRYPTO_lock" "ac_cv_func_CRYPTO_lock"
diff --git a/configure.ac b/configure.ac
index 94ae1d33c2..7f723289dd 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1367,7 +1367,8 @@ fi
 
 if test "$with_ssl" = openssl ; then
   dnl Order matters!
-  # Minimum required OpenSSL version is 1.0.2
+  # Minimum required OpenSSL version is 1.1.0.  API compatibility is kept at
+  # 1.0.2 for OpenSSL_add_all_algorithms().
   AC_DEFINE(OPENSSL_API_COMPAT, [0x10002000L],
             [Define to the OpenSSL API version in use. This avoids deprecation warnings from newer OpenSSL versions.])
   if test "$PORTNAME" != "win32"; then
@@ -1377,18 +1378,14 @@ if test "$with_ssl" = openssl ; then
      AC_SEARCH_LIBS(CRYPTO_new_ex_data, [eay32 crypto], [], [AC_MSG_ERROR([library 'eay32' or 'crypto' is required for OpenSSL])])
      AC_SEARCH_LIBS(SSL_new, [ssleay32 ssl], [], [AC_MSG_ERROR([library 'ssleay32' or 'ssl' is required for OpenSSL])])
   fi
-  # LibreSSL does not have SSL_CTX_set_cert_cb().
-  AC_CHECK_FUNCS([SSL_CTX_set_cert_cb])
-  # Functions introduced in OpenSSL 1.1.0. We used to check for
-  # OPENSSL_VERSION_NUMBER, but that didn't work with 1.1.0, because LibreSSL
-  # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
-  # doesn't have these OpenSSL 1.1.0 functions. So check for individual
+  # Functions not in LibreSSL.  We used to check for OPENSSL_VERSION_NUMBER,
+  # but that didn't work with OpenSSL 1.1.0, because LibreSSL defines
+  # OPENSSL_VERSION_NUMBER to claim version 2.0.0. So check for individual
   # functions.
-  AC_CHECK_FUNCS([OPENSSL_init_ssl BIO_get_data 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])
+  AC_CHECK_FUNCS([SSL_CTX_set_cert_cb OPENSSL_init_ssl])
+  # Function included in LibreSSL, not in OpenSSL.  This is required for
+  # thread safety.
+  AC_CHECK_FUNCS(CRYPTO_lock)
   # Function introduced in OpenSSL 1.1.1.
   AC_CHECK_FUNCS([X509_get_signature_info])
   AC_DEFINE([USE_OPENSSL], 1, [Define to 1 to build with OpenSSL support. (--with-ssl=openssl)])
diff --git a/meson.build b/meson.build
index 5cf13e3b36..c176a0fbea 100644
--- a/meson.build
+++ b/meson.build
@@ -1271,21 +1271,15 @@ if sslopt in ['auto', 'openssl']
       # Function 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 not in LibreSSL. 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. So check for individual
       # functions.
       ['OPENSSL_init_ssl'],
-      ['BIO_get_data'],
-      ['BIO_meth_new'],
-      ['ASN1_STRING_get0_data'],
-      ['HMAC_CTX_new'],
-      ['HMAC_CTX_free'],
+      ['SSL_CTX_set_cert_cb'],
 
-      # 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.
+      # Function included in LibreSSL, not in OpenSSL.  This is required for
+      # thread-safety.
       ['CRYPTO_lock'],
 
       # Function introduced in OpenSSL 1.1.1
@@ -1311,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', '0x10001000L',
+      cdata.set('OPENSSL_API_COMPAT', '0x10002000L',
                 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/tools/msvc/Solution.pm b/src/tools/msvc/Solution.pm
index e6d8f9fedc..84e2209e74 100644
--- a/src/tools/msvc/Solution.pm
+++ b/src/tools/msvc/Solution.pm
@@ -221,12 +221,9 @@ sub GenerateFiles
 		ENABLE_NLS => $self->{options}->{nls} ? 1 : undef,
 		ENABLE_THREAD_SAFETY => 1,
 		HAVE_APPEND_HISTORY => undef,
-		HAVE_ASN1_STRING_GET0_DATA => undef,
 		HAVE_ATOMICS => 1,
 		HAVE_ATOMIC_H => undef,
 		HAVE_BACKTRACE_SYMBOLS => undef,
-		HAVE_BIO_GET_DATA => undef,
-		HAVE_BIO_METH_NEW => undef,
 		HAVE_COMPUTED_GOTO => undef,
 		HAVE_COPYFILE => undef,
 		HAVE_COPYFILE_H => undef,
@@ -266,8 +263,6 @@ sub GenerateFiles
 		HAVE_GSSAPI_GSSAPI_EXT_H => undef,
 		HAVE_GSSAPI_GSSAPI_H => undef,
 		HAVE_GSSAPI_H => undef,
-		HAVE_HMAC_CTX_FREE => undef,
-		HAVE_HMAC_CTX_NEW => undef,
 		HAVE_HISTORY_H => undef,
 		HAVE_HISTORY_TRUNCATE_FILE => undef,
 		HAVE_IFADDRS_H => undef,
@@ -488,6 +483,7 @@ sub GenerateFiles
 	{
 		$define{USE_OPENSSL} = 1;
 		$define{HAVE_SSL_CTX_SET_CERT_CB} = 1;
+		$define{HAVE_OPENSSL_INIT_SSL} = 1;
 
 		my ($digit1, $digit2, $digit3) = $self->GetOpenSSLVersion();
 
@@ -497,18 +493,6 @@ sub GenerateFiles
 		{
 			$define{HAVE_X509_GET_SIGNATURE_INFO} = 1;
 		}
-
-		# Symbols needed with OpenSSL 1.1.0 and above.
-		if (   ($digit1 >= '3' && $digit2 >= '0' && $digit3 >= '0')
-			|| ($digit1 >= '1' && $digit2 >= '1' && $digit3 >= '0'))
-		{
-			$define{HAVE_ASN1_STRING_GET0_DATA} = 1;
-			$define{HAVE_BIO_GET_DATA} = 1;
-			$define{HAVE_BIO_METH_NEW} = 1;
-			$define{HAVE_HMAC_CTX_FREE} = 1;
-			$define{HAVE_HMAC_CTX_NEW} = 1;
-			$define{HAVE_OPENSSL_INIT_SSL} = 1;
-		}
 	}
 
 	$self->GenerateConfigHeader('src/include/pg_config.h', \%define, 1);
-- 
2.40.1

Attachment: signature.asc
Description: PGP signature

Reply via email to