Skip to content

Commit 79dfa8a

Browse files
committed
Add bound checks for ssl_min_protocol_version and ssl_max_protocol_version
Mixing incorrect bounds in the SSL context leads to confusing error messages generated by OpenSSL which are hard to act on. New range checks are added when both min/max parameters are loaded in the context of a SSL reload to improve the error reporting. Note that this does not make use of the GUC hook machinery contrary to 41aadee, as there is no way to ensure a consistent range check (except if there is a way one day to define range types for GUC parameters?). Hence, this patch applies only to OpenSSL, and uses a logic similar to other parameters to trigger an error when reloading the SSL context in a session. Author: Michael Paquier Reviewed-by: Daniel Gustafsson Discussion: https://postgr.es/m/20200114035420.GE1515@paquier.xyz
1 parent de93963 commit 79dfa8a

File tree

2 files changed

+62
-21
lines changed

2 files changed

+62
-21
lines changed

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

Lines changed: 45 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,7 @@ static bool SSL_initialized = false;
6868
static bool dummy_ssl_passwd_cb_called = false;
6969
static bool ssl_is_server_start;
7070

71-
static int ssl_protocol_version_to_openssl(int v, const char *guc_name,
72-
int loglevel);
71+
static int ssl_protocol_version_to_openssl(int v);
7372

7473
/* ------------------------------------------------------------ */
7574
/* Public interface */
@@ -80,6 +79,8 @@ be_tls_init(bool isServerStart)
8079
{
8180
STACK_OF(X509_NAME) *root_cert_list = NULL;
8281
SSL_CTX *context;
82+
int ssl_ver_min = -1;
83+
int ssl_ver_max = -1;
8384

8485
/* This stuff need be done only once. */
8586
if (!SSL_initialized)
@@ -188,13 +189,19 @@ be_tls_init(bool isServerStart)
188189

189190
if (ssl_min_protocol_version)
190191
{
191-
int ssl_ver = ssl_protocol_version_to_openssl(ssl_min_protocol_version,
192-
"ssl_min_protocol_version",
193-
isServerStart ? FATAL : LOG);
192+
ssl_ver_min = ssl_protocol_version_to_openssl(ssl_min_protocol_version);
194193

195-
if (ssl_ver == -1)
194+
if (ssl_ver_min == -1)
195+
{
196+
ereport(isServerStart ? FATAL : LOG,
197+
(errmsg("\"%s\" setting \"%s\" not supported by this build",
198+
"ssl_min_protocol_version",
199+
GetConfigOption("ssl_min_protocol_version",
200+
false, false))));
196201
goto error;
197-
if (!SSL_CTX_set_min_proto_version(context, ssl_ver))
202+
}
203+
204+
if (!SSL_CTX_set_min_proto_version(context, ssl_ver_min))
198205
{
199206
ereport(isServerStart ? FATAL : LOG,
200207
(errmsg("could not set minimum SSL protocol version")));
@@ -204,20 +211,43 @@ be_tls_init(bool isServerStart)
204211

205212
if (ssl_max_protocol_version)
206213
{
207-
int ssl_ver = ssl_protocol_version_to_openssl(ssl_max_protocol_version,
208-
"ssl_max_protocol_version",
209-
isServerStart ? FATAL : LOG);
214+
ssl_ver_max = ssl_protocol_version_to_openssl(ssl_max_protocol_version);
210215

211-
if (ssl_ver == -1)
216+
if (ssl_ver_max == -1)
217+
{
218+
ereport(isServerStart ? FATAL : LOG,
219+
(errmsg("\"%s\" setting \"%s\" not supported by this build",
220+
"ssl_max_protocol_version",
221+
GetConfigOption("ssl_max_protocol_version",
222+
false, false))));
212223
goto error;
213-
if (!SSL_CTX_set_max_proto_version(context, ssl_ver))
224+
}
225+
226+
if (!SSL_CTX_set_max_proto_version(context, ssl_ver_max))
214227
{
215228
ereport(isServerStart ? FATAL : LOG,
216229
(errmsg("could not set maximum SSL protocol version")));
217230
goto error;
218231
}
219232
}
220233

234+
/* Check compatibility of min/max protocols */
235+
if (ssl_min_protocol_version &&
236+
ssl_max_protocol_version)
237+
{
238+
/*
239+
* No need to check for invalid values (-1) for each protocol number
240+
* as the code above would have already generated an error.
241+
*/
242+
if (ssl_ver_min > ssl_ver_max)
243+
ereport(isServerStart ? FATAL : LOG,
244+
(errmsg("could not set SSL protocol version range"),
245+
errdetail("\"%s\" cannot be higher than \"%s\"",
246+
"ssl_min_protocol_version",
247+
"ssl_max_protocol_version")));
248+
goto error;
249+
}
250+
221251
/* disallow SSL session tickets */
222252
SSL_CTX_set_options(context, SSL_OP_NO_TICKET);
223253

@@ -1271,15 +1301,14 @@ X509_NAME_to_cstring(X509_NAME *name)
12711301
* guc.c independent of OpenSSL availability and version.
12721302
*
12731303
* If a version is passed that is not supported by the current OpenSSL
1274-
* version, then we log with the given loglevel and return (if we return) -1.
1275-
* If a nonnegative value is returned, subsequent code can assume it's working
1276-
* with a supported version.
1304+
* version, then we return -1. If a nonnegative value is returned,
1305+
* subsequent code can assume it's working with a supported version.
12771306
*
12781307
* Note: this is rather similar to libpq's routine in fe-secure-openssl.c,
12791308
* so make sure to update both routines if changing this one.
12801309
*/
12811310
static int
1282-
ssl_protocol_version_to_openssl(int v, const char *guc_name, int loglevel)
1311+
ssl_protocol_version_to_openssl(int v)
12831312
{
12841313
switch (v)
12851314
{
@@ -1307,9 +1336,5 @@ ssl_protocol_version_to_openssl(int v, const char *guc_name, int loglevel)
13071336
#endif
13081337
}
13091338

1310-
ereport(loglevel,
1311-
(errmsg("%s setting %s not supported by this build",
1312-
guc_name,
1313-
GetConfigOption(guc_name, false, false))));
13141339
return -1;
13151340
}

src/test/ssl/t/001_ssltests.pl

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
if ($ENV{with_openssl} eq 'yes')
1515
{
16-
plan tests => 91;
16+
plan tests => 93;
1717
}
1818
else
1919
{
@@ -97,6 +97,22 @@
9797
'restart succeeds with password-protected key file');
9898
$node->_update_pid(1);
9999

100+
# Test compatibility of SSL protocols.
101+
# TLSv1.1 is lower than TLSv1.2, so it won't work.
102+
$node->append_conf('postgresql.conf',
103+
qq{ssl_min_protocol_version='TLSv1.2'
104+
ssl_max_protocol_version='TLSv1.1'});
105+
command_fails(
106+
[ 'pg_ctl', '-D', $node->data_dir, '-l', $node->logfile, 'restart' ],
107+
'restart fails with incorrect SSL protocol bounds');
108+
# Go back to the defaults, this works.
109+
$node->append_conf('postgresql.conf',
110+
qq{ssl_min_protocol_version='TLSv1.2'
111+
ssl_max_protocol_version=''});
112+
command_ok(
113+
[ 'pg_ctl', '-D', $node->data_dir, '-l', $node->logfile, 'restart' ],
114+
'restart succeeds with correct SSL protocol bounds');
115+
100116
### Run client-side tests.
101117
###
102118
### Test that libpq accepts/rejects the connection correctly, depending

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