Skip to content

Commit e73e67c

Browse files
committed
Add settings to control SSL/TLS protocol version
For example: ssl_min_protocol_version = 'TLSv1.1' ssl_max_protocol_version = 'TLSv1.2' Reviewed-by: Steve Singer <steve@ssinger.info> Discussion: https://www.postgresql.org/message-id/flat/1822da87-b862-041a-9fc2-d0310c3da173@2ndquadrant.com
1 parent 2d9140e commit e73e67c

File tree

6 files changed

+214
-2
lines changed

6 files changed

+214
-2
lines changed

doc/src/sgml/config.sgml

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1291,6 +1291,50 @@ include_dir 'conf.d'
12911291
</listitem>
12921292
</varlistentry>
12931293

1294+
<varlistentry id="guc-ssl-min-protocol-version" xreflabel="ssl_min_protocol_version">
1295+
<term><varname>ssl_min_protocol_version</varname> (<type>enum</type>)
1296+
<indexterm>
1297+
<primary><varname>ssl_min_protocol_version</varname> configuration parameter</primary>
1298+
</indexterm>
1299+
</term>
1300+
<listitem>
1301+
<para>
1302+
Sets the minimum SSL/TLS protocol version to use. Valid values are
1303+
currently: <literal>TLSv1</literal>, <literal>TLSv1.1</literal>,
1304+
<literal>TLSv1.2</literal>, <literal>TLSv1.3</literal>. Older
1305+
versions of the <productname>OpenSSL</productname> library do not
1306+
support all values; an error will be raised if an unsupported setting
1307+
is chosen. Protocol versions before TLS 1.0, namely SSL version 2 and
1308+
3, are always disabled.
1309+
</para>
1310+
1311+
<para>
1312+
The default is <literal>TLSv1</literal>, mainly to support older
1313+
versions of the <productname>OpenSSL</productname> library. You might
1314+
want to set this to a higher value if all software components can
1315+
support the newer protocol versions.
1316+
</para>
1317+
</listitem>
1318+
</varlistentry>
1319+
1320+
<varlistentry id="guc-ssl-max-protocol-version" xreflabel="ssl_max_protocol_version">
1321+
<term><varname>ssl_max_protocol_version</varname> (<type>enum</type>)
1322+
<indexterm>
1323+
<primary><varname>ssl_max_protocol_version</varname> configuration parameter</primary>
1324+
</indexterm>
1325+
</term>
1326+
<listitem>
1327+
<para>
1328+
Sets the maximum SSL/TLS protocol version to use. Valid values are as
1329+
for <xref linkend="guc-ssl-min-protocol-version"/>, with addition of
1330+
an empty string, which allows any protocol version. The default is to
1331+
allow any version. Setting the maximum protocol version is mainly
1332+
useful for testing or if some component has issues working with a
1333+
newer protocol.
1334+
</para>
1335+
</listitem>
1336+
</varlistentry>
1337+
12941338
<varlistentry id="guc-ssl-dh-params-file" xreflabel="ssl_dh_params_file">
12951339
<term><varname>ssl_dh_params_file</varname> (<type>string</type>)
12961340
<indexterm>

src/backend/libpq/be-secure-openssl.c

Lines changed: 121 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,12 @@ static bool SSL_initialized = false;
6767
static bool dummy_ssl_passwd_cb_called = false;
6868
static bool ssl_is_server_start;
6969

70+
static int ssl_protocol_version_to_openssl(int v, const char *guc_name);
71+
#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
72+
static int SSL_CTX_set_min_proto_version(SSL_CTX *ctx, int version);
73+
static int SSL_CTX_set_max_proto_version(SSL_CTX *ctx, int version);
74+
#endif
75+
7076

7177
/* ------------------------------------------------------------ */
7278
/* Public interface */
@@ -183,8 +189,14 @@ be_tls_init(bool isServerStart)
183189
goto error;
184190
}
185191

186-
/* disallow SSL v2/v3 */
187-
SSL_CTX_set_options(context, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
192+
if (ssl_min_protocol_version)
193+
SSL_CTX_set_min_proto_version(context,
194+
ssl_protocol_version_to_openssl(ssl_min_protocol_version,
195+
"ssl_min_protocol_version"));
196+
if (ssl_max_protocol_version)
197+
SSL_CTX_set_max_proto_version(context,
198+
ssl_protocol_version_to_openssl(ssl_max_protocol_version,
199+
"ssl_max_protocol_version"));
188200

189201
/* disallow SSL session tickets */
190202
#ifdef SSL_OP_NO_TICKET /* added in OpenSSL 0.9.8f */
@@ -1209,3 +1221,110 @@ X509_NAME_to_cstring(X509_NAME *name)
12091221

12101222
return result;
12111223
}
1224+
1225+
/*
1226+
* Convert TLS protocol version GUC enum to OpenSSL values
1227+
*
1228+
* This is a straightforward one-to-one mapping, but doing it this way makes
1229+
* guc.c independent of OpenSSL availability and version.
1230+
*
1231+
* If a version is passed that is not supported by the current OpenSSL
1232+
* version, then we throw an error, so that subsequent code can assume it's
1233+
* working with a supported version.
1234+
*/
1235+
static int
1236+
ssl_protocol_version_to_openssl(int v, const char *guc_name)
1237+
{
1238+
switch (v)
1239+
{
1240+
case PG_TLS_ANY:
1241+
return 0;
1242+
case PG_TLS1_VERSION:
1243+
return TLS1_VERSION;
1244+
case PG_TLS1_1_VERSION:
1245+
#ifdef TLS1_1_VERSION
1246+
return TLS1_1_VERSION;
1247+
#else
1248+
goto error;
1249+
#endif
1250+
case PG_TLS1_2_VERSION:
1251+
#ifdef TLS1_2_VERSION
1252+
return TLS1_2_VERSION;
1253+
#else
1254+
goto error;
1255+
#endif
1256+
case PG_TLS1_3_VERSION:
1257+
#ifdef TLS1_3_VERSION
1258+
return TLS1_3_VERSION;
1259+
#else
1260+
goto error;
1261+
#endif
1262+
}
1263+
1264+
error:
1265+
pg_attribute_unused();
1266+
ereport(ERROR,
1267+
(errmsg("%s setting %s not supported by this build",
1268+
guc_name,
1269+
GetConfigOption(guc_name, false, false))));
1270+
return -1;
1271+
}
1272+
1273+
/*
1274+
* Replacements for APIs present in newer versions of OpenSSL
1275+
*/
1276+
#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
1277+
1278+
/*
1279+
* OpenSSL versions that support TLS 1.3 shouldn't get here because they
1280+
* already have these functions. So we don't have to keep updating the below
1281+
* code for every new TLS version, and eventually it can go away. But let's
1282+
* just check this to make sure ...
1283+
*/
1284+
#ifdef TLS1_3_VERSION
1285+
#error OpenSSL version mismatch
1286+
#endif
1287+
1288+
static int
1289+
SSL_CTX_set_min_proto_version(SSL_CTX *ctx, int version)
1290+
{
1291+
int ssl_options = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;
1292+
1293+
if (version > TLS1_VERSION)
1294+
ssl_options |= SSL_OP_NO_TLSv1;
1295+
#ifdef TLS1_1_VERSION
1296+
if (version > TLS1_1_VERSION)
1297+
ssl_options |= SSL_OP_NO_TLSv1_1;
1298+
#endif
1299+
#ifdef TLS1_2_VERSION
1300+
if (version > TLS1_2_VERSION)
1301+
ssl_options |= SSL_OP_NO_TLSv1_2;
1302+
#endif
1303+
1304+
SSL_CTX_set_options(ctx, ssl_options);
1305+
1306+
return 1; /* success */
1307+
}
1308+
1309+
static int
1310+
SSL_CTX_set_max_proto_version(SSL_CTX *ctx, int version)
1311+
{
1312+
int ssl_options = 0;
1313+
1314+
AssertArg(version != 0);
1315+
1316+
#ifdef TLS1_1_VERSION
1317+
if (version < TLS1_1_VERSION)
1318+
ssl_options |= SSL_OP_NO_TLSv1_1;
1319+
#endif
1320+
#ifdef TLS1_2_VERSION
1321+
if (version < TLS1_2_VERSION)
1322+
ssl_options |= SSL_OP_NO_TLSv1_2;
1323+
#endif
1324+
1325+
SSL_CTX_set_options(ctx, ssl_options);
1326+
1327+
return 1; /* success */
1328+
}
1329+
1330+
#endif /* OPENSSL_VERSION_NUMBER */

src/backend/libpq/be-secure.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ char *SSLECDHCurve;
6060
/* GUC variable: if false, prefer client ciphers */
6161
bool SSLPreferServerCiphers;
6262

63+
int ssl_min_protocol_version;
64+
int ssl_max_protocol_version;
65+
6366
/* ------------------------------------------------------------ */
6467
/* Procedures common to all secure sessions */
6568
/* ------------------------------------------------------------ */

src/backend/utils/misc/guc.c

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,15 @@ static const struct config_enum_entry password_encryption_options[] = {
428428
{NULL, 0, false}
429429
};
430430

431+
const struct config_enum_entry ssl_protocol_versions_info[] = {
432+
{"", PG_TLS_ANY, false},
433+
{"TLSv1", PG_TLS1_VERSION, false},
434+
{"TLSv1.1", PG_TLS1_1_VERSION, false},
435+
{"TLSv1.2", PG_TLS1_2_VERSION, false},
436+
{"TLSv1.3", PG_TLS1_3_VERSION, false},
437+
{NULL, 0, false}
438+
};
439+
431440
/*
432441
* Options for enum values stored in other modules
433442
*/
@@ -4193,6 +4202,30 @@ static struct config_enum ConfigureNamesEnum[] =
41934202
NULL, NULL, NULL
41944203
},
41954204

4205+
{
4206+
{"ssl_min_protocol_version", PGC_SIGHUP, CONN_AUTH_SSL,
4207+
gettext_noop("Sets the minimum SSL/TLS protocol version to use."),
4208+
NULL,
4209+
GUC_SUPERUSER_ONLY
4210+
},
4211+
&ssl_min_protocol_version,
4212+
PG_TLS1_VERSION,
4213+
ssl_protocol_versions_info + 1 /* don't allow PG_TLS_ANY */,
4214+
NULL, NULL, NULL
4215+
},
4216+
4217+
{
4218+
{"ssl_max_protocol_version", PGC_SIGHUP, CONN_AUTH_SSL,
4219+
gettext_noop("Sets the maximum SSL/TLS protocol version to use."),
4220+
NULL,
4221+
GUC_SUPERUSER_ONLY
4222+
},
4223+
&ssl_max_protocol_version,
4224+
PG_TLS_ANY,
4225+
ssl_protocol_versions_info,
4226+
NULL, NULL, NULL
4227+
},
4228+
41964229
/* End-of-list marker */
41974230
{
41984231
{NULL, 0, 0, NULL, NULL}, NULL, 0, NULL, NULL, NULL, NULL

src/backend/utils/misc/postgresql.conf.sample

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,8 @@
103103
#ssl_ciphers = 'HIGH:MEDIUM:+3DES:!aNULL' # allowed SSL ciphers
104104
#ssl_prefer_server_ciphers = on
105105
#ssl_ecdh_curve = 'prime256v1'
106+
#ssl_min_protocol_version = 'TLSv1'
107+
#ssl_max_protocol_version = ''
106108
#ssl_dh_params_file = ''
107109
#ssl_passphrase_command = ''
108110
#ssl_passphrase_command_supports_reload = off

src/include/libpq/libpq.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,17 @@ extern WaitEventSet *FeBeWaitSet;
102102
extern char *SSLCipherSuites;
103103
extern char *SSLECDHCurve;
104104
extern bool SSLPreferServerCiphers;
105+
extern int ssl_min_protocol_version;
106+
extern int ssl_max_protocol_version;
107+
108+
enum ssl_protocol_versions
109+
{
110+
PG_TLS_ANY = 0,
111+
PG_TLS1_VERSION,
112+
PG_TLS1_1_VERSION,
113+
PG_TLS1_2_VERSION,
114+
PG_TLS1_3_VERSION,
115+
};
105116

106117
/*
107118
* prototypes for functions in be-secure-common.c

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy