Move OpenSSL routines for min/max protocol setting to src/common/
authorMichael Paquier <michael@paquier.xyz>
Fri, 17 Jan 2020 01:06:17 +0000 (10:06 +0900)
committerMichael Paquier <michael@paquier.xyz>
Fri, 17 Jan 2020 01:06:17 +0000 (10:06 +0900)
Two routines have been added in OpenSSL 1.1.0 to set the protocol bounds
allowed within a given SSL context:
- SSL_CTX_set_min_proto_version
- SSL_CTX_set_max_proto_version

As Postgres supports OpenSSL down to 1.0.1 (as of HEAD), equivalent
replacements exist in the tree, which are only available for the
backend.  A follow-up patch is planned to add control of the SSL
protocol bounds for libpq, so move those routines to src/common/ so as
libpq can use them.

Author: Daniel Gustafsson
Discussion: https://postgr.es/m/4F246AE3-A7AE-471E-BD3D-C799D3748E03@yesql.se

src/backend/libpq/be-secure-openssl.c
src/common/Makefile
src/common/protocol_openssl.c [new file with mode: 0644]
src/include/common/openssl.h [new file with mode: 0644]
src/tools/msvc/Mkvcbuild.pm

index 62f1fcab2b031539e060068225b0c89a81f401c6..0cc59f1be147357dd7bc0e57b9cb1f6cc3a13e0f 100644 (file)
@@ -36,6 +36,7 @@
 #include <openssl/ec.h>
 #endif
 
+#include "common/openssl.h"
 #include "libpq/libpq.h"
 #include "miscadmin.h"
 #include "pgstat.h"
@@ -69,11 +70,6 @@ static bool ssl_is_server_start;
 
 static int     ssl_protocol_version_to_openssl(int v, const char *guc_name,
                                                                                        int loglevel);
-#ifndef SSL_CTX_set_min_proto_version
-static int     SSL_CTX_set_min_proto_version(SSL_CTX *ctx, int version);
-static int     SSL_CTX_set_max_proto_version(SSL_CTX *ctx, int version);
-#endif
-
 
 /* ------------------------------------------------------------ */
 /*                                              Public interface                                               */
@@ -1314,96 +1310,3 @@ ssl_protocol_version_to_openssl(int v, const char *guc_name, int loglevel)
                                        GetConfigOption(guc_name, false, false))));
        return -1;
 }
-
-/*
- * Replacements for APIs present in newer versions of OpenSSL
- */
-#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
-
-static 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 */
-}
-
-static int
-SSL_CTX_set_max_proto_version(SSL_CTX *ctx, int version)
-{
-       int                     ssl_options = 0;
-
-       AssertArg(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 */
index 5b44340afdd5c2fa35fbc0d2b9a7c4fb6aea00f3..44ca68fa6c377138a37eeb9ccfa621ca15f077be 100644 (file)
@@ -75,7 +75,9 @@ OBJS_COMMON = \
        wchar.o
 
 ifeq ($(with_openssl),yes)
-OBJS_COMMON += sha2_openssl.o
+OBJS_COMMON += \
+       protocol_openssl.o \
+       sha2_openssl.o
 else
 OBJS_COMMON += sha2.o
 endif
diff --git a/src/common/protocol_openssl.c b/src/common/protocol_openssl.c
new file mode 100644 (file)
index 0000000..bf6c624
--- /dev/null
@@ -0,0 +1,117 @@
+/*-------------------------------------------------------------------------
+ *
+ * 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-2020, 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;
+
+       AssertArg(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
new file mode 100644 (file)
index 0000000..47fa129
--- /dev/null
@@ -0,0 +1,28 @@
+/*-------------------------------------------------------------------------
+ *
+ * openssl.h
+ *       OpenSSL supporting functionality shared between frontend and backend
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ *               src/include/common/openssl.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef COMMON_OPENSSL_H
+#define COMMON_OPENSSL_H
+
+#ifdef USE_OPENSSL
+#include <openssl/ssl.h>
+
+/* 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
+
+#endif                                                 /* COMMON_OPENSSL_H */
index 67b9f238b212201824d261e55ffea17d21291734..c735d529ca8c7b8db0fff74a7440043a9621761c 100644 (file)
@@ -130,6 +130,7 @@ sub mkvcbuild
        if ($solution->{options}->{openssl})
        {
                push(@pgcommonallfiles, 'sha2_openssl.c');
+               push(@pgcommonallfiles, 'protocol_openssl.c');
        }
        else
        {