Skip to content

Commit 41aadee

Browse files
committed
Add GUC checks for ssl_min_protocol_version and ssl_max_protocol_version
Mixing incorrect bounds set in the SSL context leads to confusing error messages generated by OpenSSL which are hard to act on. New checks are added within the GUC machinery to improve the user experience as they apply to any SSL implementation, not only OpenSSL, and doing the checks beforehand avoids the creation of a SSL during a reload (or startup) which we know will never be used anyway. Backpatch down to 12, as those parameters have been introduced by e73e67c. Author: Michael Paquier Reviewed-by: Daniel Gustafsson Discussion: https://postgr.es/m/20200114035420.GE1515@paquier.xyz Backpatch-through: 12
1 parent 4b754d6 commit 41aadee

File tree

2 files changed

+68
-3
lines changed

2 files changed

+68
-3
lines changed

src/backend/utils/misc/guc.c

+49-2
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,10 @@ static const char *show_log_file_mode(void);
204204
static const char *show_data_directory_mode(void);
205205
static bool check_backtrace_functions(char **newval, void **extra, GucSource source);
206206
static void assign_backtrace_functions(const char *newval, void *extra);
207+
static bool check_ssl_min_protocol_version(int *newval, void **extra,
208+
GucSource source);
209+
static bool check_ssl_max_protocol_version(int *newval, void **extra,
210+
GucSource source);
207211
static bool check_recovery_target_timeline(char **newval, void **extra, GucSource source);
208212
static void assign_recovery_target_timeline(const char *newval, void *extra);
209213
static bool check_recovery_target(char **newval, void **extra, GucSource source);
@@ -4594,7 +4598,7 @@ static struct config_enum ConfigureNamesEnum[] =
45944598
&ssl_min_protocol_version,
45954599
PG_TLS1_2_VERSION,
45964600
ssl_protocol_versions_info + 1, /* don't allow PG_TLS_ANY */
4597-
NULL, NULL, NULL
4601+
check_ssl_min_protocol_version, NULL, NULL
45984602
},
45994603

46004604
{
@@ -4606,7 +4610,7 @@ static struct config_enum ConfigureNamesEnum[] =
46064610
&ssl_max_protocol_version,
46074611
PG_TLS_ANY,
46084612
ssl_protocol_versions_info,
4609-
NULL, NULL, NULL
4613+
check_ssl_max_protocol_version, NULL, NULL
46104614
},
46114615

46124616
/* End-of-list marker */
@@ -11603,6 +11607,49 @@ assign_backtrace_functions(const char *newval, void *extra)
1160311607
backtrace_symbol_list = (char *) extra;
1160411608
}
1160511609

11610+
static bool
11611+
check_ssl_min_protocol_version(int *newval, void **extra, GucSource source)
11612+
{
11613+
int new_ssl_min_protocol_version = *newval;
11614+
11615+
/* PG_TLS_ANY is not supported for the minimum bound */
11616+
Assert(new_ssl_min_protocol_version > PG_TLS_ANY);
11617+
11618+
if (ssl_max_protocol_version &&
11619+
new_ssl_min_protocol_version > ssl_max_protocol_version)
11620+
{
11621+
GUC_check_errhint("\"%s\" cannot be higher than \"%s\".",
11622+
"ssl_min_protocol_version",
11623+
"ssl_max_protocol_version");
11624+
GUC_check_errcode(ERRCODE_INVALID_PARAMETER_VALUE);
11625+
return false;
11626+
}
11627+
11628+
return true;
11629+
}
11630+
11631+
static bool
11632+
check_ssl_max_protocol_version(int *newval, void **extra, GucSource source)
11633+
{
11634+
int new_ssl_max_protocol_version = *newval;
11635+
11636+
/* if PG_TLS_ANY, there is no need to check the bounds */
11637+
if (new_ssl_max_protocol_version == PG_TLS_ANY)
11638+
return true;
11639+
11640+
if (ssl_min_protocol_version &&
11641+
ssl_min_protocol_version > new_ssl_max_protocol_version)
11642+
{
11643+
GUC_check_errhint("\"%s\" cannot be lower than \"%s\".",
11644+
"ssl_max_protocol_version",
11645+
"ssl_min_protocol_version");
11646+
GUC_check_errcode(ERRCODE_INVALID_PARAMETER_VALUE);
11647+
return false;
11648+
}
11649+
11650+
return true;
11651+
}
11652+
1160611653
static bool
1160711654
check_recovery_target_timeline(char **newval, void **extra, GucSource source)
1160811655
{

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

+19-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
if ($ENV{with_openssl} eq 'yes')
1515
{
16-
plan tests => 84;
16+
plan tests => 86;
1717
}
1818
else
1919
{
@@ -97,6 +97,24 @@
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(
103+
'postgresql.conf',
104+
qq{ssl_min_protocol_version='TLSv1.2'
105+
ssl_max_protocol_version='TLSv1.1'});
106+
command_fails(
107+
[ 'pg_ctl', '-D', $node->data_dir, '-l', $node->logfile, 'restart' ],
108+
'restart fails with incorrect SSL protocol bounds');
109+
# Go back to the defaults, this works.
110+
$node->append_conf(
111+
'postgresql.conf',
112+
qq{ssl_min_protocol_version='TLSv1.2'
113+
ssl_max_protocol_version=''});
114+
command_ok(
115+
[ 'pg_ctl', '-D', $node->data_dir, '-l', $node->logfile, 'restart' ],
116+
'restart succeeds with correct SSL protocol bounds');
117+
100118
### Run client-side tests.
101119
###
102120
### Test that libpq accepts/rejects the connection correctly, depending

0 commit comments

Comments
 (0)