From 8e278b65766446f29085fe686723961c4b216e6f Mon Sep 17 00:00:00 2001 From: Michael Paquier Date: Mon, 3 Jul 2023 13:20:27 +0900 Subject: [PATCH] Remove support for OpenSSL 1.0.1 Here are some notes about this change: - As X509_get_signature_nid() should always exist (OpenSSL and LibreSSL), hence HAVE_X509_GET_SIGNATURE_NID is now gone. - OPENSSL_API_COMPAT is bumped to 0x10002000L. - One comment related to 1.0.1e introduced by 74242c2 is removed. Upstream OpenSSL still provides long-term support for 1.0.2 in a closed fashion, so removing it is out of scope for a few years, at least. Reviewed-by: Jacob Champion, Daniel Gustafsson Discussion: https://postgr.es/m/ZG3JNursG69dz1lr@paquier.xyz --- configure | 16 ++++----- configure.ac | 8 ++--- doc/src/sgml/installation.sgml | 2 +- meson.build | 7 ++-- src/backend/libpq/auth-scram.c | 20 ++++++------ src/backend/libpq/be-secure-openssl.c | 4 --- src/include/libpq/libpq-be.h | 6 ---- src/include/pg_config.h.in | 3 -- 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 ++++-------------------- src/tools/msvc/Solution.pm | 10 +----- 14 files changed, 37 insertions(+), 100 deletions(-) diff --git a/configure b/configure index 8e5006bd4f..997d42d8f7 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 0e8158a5e6..6052675fb8 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,9 @@ 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 + # Function 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]) + 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/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. OpenSSL is also required for random number generation on platforms that do not have /dev/urandom (except Windows). The minimum - required version is 1.0.1. + required version is 1.0.2. diff --git a/meson.build b/meson.build index e408967fd4..aaa9daf266 100644 --- a/meson.build +++ b/meson.build @@ -1266,9 +1266,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 + # Functions 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 @@ -1310,7 +1309,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/backend/libpq/auth-scram.c b/src/backend/libpq/auth-scram.c index 9b286aa4d7..118d15b1a1 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_SSL 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, or 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_SSL 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_SSL 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_SSL 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/include/libpq/libpq-be.h b/src/include/libpq/libpq-be.h index 3b2ce9908f..a0b74c8095 100644 --- a/src/include/libpq/libpq-be.h +++ b/src/include/libpq/libpq-be.h @@ -305,14 +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 extern char *be_tls_get_certificate_hash(Port *port, size_t *len); -#endif /* init hook for SSL, the default sets the password callback if appropriate */ #ifdef USE_OPENSSL 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/interfaces/libpq/fe-auth-scram.c b/src/interfaces/libpq/fe-auth-scram.c index 6b779ec7ff..61e6cd84d2 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_SSL 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_SSL 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_SSL */ } -#ifdef HAVE_PGTLS_GET_PEER_CERTIFICATE_HASH +#ifdef USE_SSL 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 88fd0f3d80..f8e09d3b41 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_SSL /* * 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 0045f83cbf..b70d4aee6a 100644 --- a/src/interfaces/libpq/libpq-int.h +++ b/src/interfaces/libpq/libpq-int.h @@ -833,14 +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 extern char *pgtls_get_peer_certificate_hash(PGconn *conn, size_t *len); -#endif /* * Verify that the server certificate matches the host name we connected to. 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/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.39.5