0001-Compatibility-with-OpenSSL-3.0.0.patch

application/octet-stream

Filename: 0001-Compatibility-with-OpenSSL-3.0.0.patch
Type: application/octet-stream
Part: 1
Message: OpenSSL 3.0.0 compatibility

Patch

Format: format-patch
Series: patch 0001
Subject: Compatibility with OpenSSL 3.0.0
File+
src/backend/libpq/be-secure-openssl.c 58 23
src/common/cert_openssl.c 42 0
src/common/Makefile 2 1
src/include/common/openssl.h 6 0
src/interfaces/libpq/fe-secure-openssl.c 2 2
From 28ed04b053247ecbcb1f14045cd16f98864f2488 Mon Sep 17 00:00:00 2001
From: Daniel Gustafsson <daniel@yesql.se>
Date: Tue, 26 May 2020 20:21:30 +0200
Subject: [PATCH 1/2] Compatibility with OpenSSL 3.0.0

OpenSSL 3.0.0 deprecates a set of functions used in libpq:

SSL_CTX_load_verify_locations and X509_STORE_load_locations were
replaced with individual calls for file and directory, so replace
with the appropriate call since we only have configuration options
for files.

Usage of DH_check has been discouraged for a long time, and it was
finally deprecated with no direct replacement. Instead implement a
version using the EVP api which is the recommended alternative.
u
---
 src/backend/libpq/be-secure-openssl.c    | 81 +++++++++++++++++-------
 src/common/Makefile                      |  3 +-
 src/common/cert_openssl.c                | 42 ++++++++++++
 src/include/common/openssl.h             |  6 ++
 src/interfaces/libpq/fe-secure-openssl.c |  4 +-
 5 files changed, 110 insertions(+), 26 deletions(-)
 create mode 100644 src/common/cert_openssl.c

diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c
index 78a865d23b..32bdca30a1 100644
--- a/src/backend/libpq/be-secure-openssl.c
+++ b/src/backend/libpq/be-secure-openssl.c
@@ -266,7 +266,7 @@ be_tls_init(bool isServerStart)
 	 */
 	if (ssl_ca_file[0])
 	{
-		if (SSL_CTX_load_verify_locations(context, ssl_ca_file, NULL) != 1 ||
+		if (SSL_CTX_load_verify_file(context, ssl_ca_file) != 1 ||
 			(root_cert_list = SSL_load_client_CA_file(ssl_ca_file)) == NULL)
 		{
 			ereport(isServerStart ? FATAL : LOG,
@@ -289,7 +289,7 @@ be_tls_init(bool isServerStart)
 		if (cvstore)
 		{
 			/* Set the flags to check against the complete CRL chain */
-			if (X509_STORE_load_locations(cvstore, ssl_crl_file, NULL) == 1)
+			if (X509_STORE_load_file(cvstore, ssl_crl_file) == 1)
 			{
 				X509_STORE_set_flags(cvstore,
 									 X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
@@ -817,7 +817,6 @@ load_dh_file(char *filename, bool isServerStart)
 {
 	FILE	   *fp;
 	DH		   *dh = NULL;
-	int			codes;
 
 	/* attempt to open file.  It's not an error if it doesn't exist. */
 	if ((fp = AllocateFile(filename, "r")) == NULL)
@@ -841,30 +840,66 @@ load_dh_file(char *filename, bool isServerStart)
 		return NULL;
 	}
 
-	/* make sure the DH parameters are usable */
-	if (DH_check(dh, &codes) == 0)
+#if OPENSSL_VERSION_MAJOR < 3
 	{
-		ereport(isServerStart ? FATAL : LOG,
-				(errcode(ERRCODE_CONFIG_FILE_ERROR),
-				 errmsg("invalid DH parameters: %s",
-						SSLerrmessage(ERR_get_error()))));
-		return NULL;
-	}
-	if (codes & DH_CHECK_P_NOT_PRIME)
-	{
-		ereport(isServerStart ? FATAL : LOG,
-				(errcode(ERRCODE_CONFIG_FILE_ERROR),
-				 errmsg("invalid DH parameters: p is not prime")));
-		return NULL;
+		int			codes;
+
+		/* make sure the DH parameters are usable */
+		if (DH_check(dh, &codes) == 0)
+		{
+			ereport(isServerStart ? FATAL : LOG,
+					(errcode(ERRCODE_CONFIG_FILE_ERROR),
+					 errmsg("invalid DH parameters: %s",
+							SSLerrmessage(ERR_get_error()))));
+			return NULL;
+		}
+		if (codes & DH_CHECK_P_NOT_PRIME)
+		{
+			ereport(isServerStart ? FATAL : LOG,
+					(errcode(ERRCODE_CONFIG_FILE_ERROR),
+					 errmsg("invalid DH parameters: p is not prime")));
+			return NULL;
+		}
+		if ((codes & DH_NOT_SUITABLE_GENERATOR) &&
+			(codes & DH_CHECK_P_NOT_SAFE_PRIME))
+		{
+			ereport(isServerStart ? FATAL : LOG,
+					(errcode(ERRCODE_CONFIG_FILE_ERROR),
+					 errmsg("invalid DH parameters: neither suitable generator or safe prime")));
+			return NULL;
+		}
 	}
-	if ((codes & DH_NOT_SUITABLE_GENERATOR) &&
-		(codes & DH_CHECK_P_NOT_SAFE_PRIME))
+#else
 	{
-		ereport(isServerStart ? FATAL : LOG,
-				(errcode(ERRCODE_CONFIG_FILE_ERROR),
-				 errmsg("invalid DH parameters: neither suitable generator or safe prime")));
-		return NULL;
+		EVP_PKEY	   *pkey;
+		EVP_PKEY_CTX   *pkey_ctx = NULL;
+		unsigned long	err = 0;
+
+		pkey = EVP_PKEY_new();
+
+		if (!EVP_PKEY_set1_DH(pkey, dh))
+			err = ERR_get_error();
+		else
+		{
+			pkey_ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL);
+
+			if (!EVP_PKEY_param_check(pkey_ctx))
+				err = ERR_get_error();
+		}
+
+		EVP_PKEY_CTX_free(pkey_ctx);
+		EVP_PKEY_free(pkey);
+
+		if (err)
+		{
+			ereport(isServerStart ? FATAL : LOG,
+					(errcode(ERRCODE_CONFIG_FILE_ERROR),
+					 errmsg("invalid DH parameters: %s",
+							SSLerrmessage(err))));
+			return NULL;
+		}
 	}
+#endif
 
 	return dh;
 }
diff --git a/src/common/Makefile b/src/common/Makefile
index d0be882cca..482561f63e 100644
--- a/src/common/Makefile
+++ b/src/common/Makefile
@@ -80,7 +80,8 @@ OBJS_COMMON = \
 ifeq ($(with_openssl),yes)
 OBJS_COMMON += \
 	protocol_openssl.o \
-	sha2_openssl.o
+	sha2_openssl.o \
+	cert_openssl.o
 else
 OBJS_COMMON += sha2.o
 endif
diff --git a/src/common/cert_openssl.c b/src/common/cert_openssl.c
new file mode 100644
index 0000000000..2149e7eb36
--- /dev/null
+++ b/src/common/cert_openssl.c
@@ -0,0 +1,42 @@
+/*-------------------------------------------------------------------------
+ *
+ * protocol_openssl.c
+ *	  OpenSSL certificate functionality shared between frontend and backend
+ *
+ * This should only be used if code is compiled with OpenSSL support.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ *		  src/common/cert_openssl.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef FRONTEND
+#include "postgres.h"
+#else
+#include "postgres_fe.h"
+#endif
+
+#include "common/openssl.h"
+
+/*
+ * SSL_CTX_load_verify_locations and X509_STORE_load_locations were deprecated
+ * in OpenSSL 3.0.0 and replaced by their new _file counterparts.  Provide
+ * implementations of the replacement for OpenSSL versions 1.0.1 through 1.1.1
+ * where they are missing.
+ */
+#if OPENSSL_VERSION_MAJOR < 3
+int
+SSL_CTX_load_verify_file(SSL_CTX *ctx, const char *CAfile)
+{
+	return SSL_CTX_load_verify_locations(ctx, CAfile, NULL);
+}
+int
+X509_STORE_load_file(X509_STORE *ctx, const char *file)
+{
+	return X509_STORE_load_locations(ctx, file, NULL);
+}
+#endif
diff --git a/src/include/common/openssl.h b/src/include/common/openssl.h
index 47fa129994..d5dc2910bf 100644
--- a/src/include/common/openssl.h
+++ b/src/include/common/openssl.h
@@ -23,6 +23,12 @@ 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
 
+/* src/common/cert_openssl.c */
+#if OPENSSL_VERSION_MAJOR < 3
+extern int SSL_CTX_load_verify_file(SSL_CTX *ctx, const char *CAfile);
+int X509_STORE_load_file(X509_STORE *ctx, const char *file);
+#endif
+
 #endif
 
 #endif							/* COMMON_OPENSSL_H */
diff --git a/src/interfaces/libpq/fe-secure-openssl.c b/src/interfaces/libpq/fe-secure-openssl.c
index 2d813ef5f9..a1ad181976 100644
--- a/src/interfaces/libpq/fe-secure-openssl.c
+++ b/src/interfaces/libpq/fe-secure-openssl.c
@@ -922,7 +922,7 @@ initialize_SSL(PGconn *conn)
 	{
 		X509_STORE *cvstore;
 
-		if (SSL_CTX_load_verify_locations(SSL_context, fnbuf, NULL) != 1)
+		if (SSL_CTX_load_verify_file(SSL_context, fnbuf) != 1)
 		{
 			char	   *err = SSLerrmessage(ERR_get_error());
 
@@ -945,7 +945,7 @@ initialize_SSL(PGconn *conn)
 
 			/* Set the flags to check against the complete CRL chain */
 			if (fnbuf[0] != '\0' &&
-				X509_STORE_load_locations(cvstore, fnbuf, NULL) == 1)
+				X509_STORE_load_file(cvstore, fnbuf) == 1)
 			{
 				X509_STORE_set_flags(cvstore,
 									 X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
-- 
2.21.1 (Apple Git-122.3)