Commit fdb1be49 authored by Michael Paquier's avatar Michael Paquier

Fix failures in SSL tests caused by out-of-tree keys and certificates

This issue is environment-sensitive, where the SSL tests could fail in
various way by feeding on defaults provided by sslcert, sslkey,
sslrootkey, sslrootcert, sslcrl and sslcrldir coming from a local setup,
as of ~/.postgresql/ by default.  Horiguchi-san has reported two
failures, but more advanced testing from me (aka inclusion of garbage
SSL configuration in ~/.postgresql/ for all the configuration
parameters) has showed dozens of failures that can be triggered in the
whole test suite.

History has showed that we are not good when it comes to address such
issues, fixing them locally like in dd877998, and such problems keep
appearing.  This commit strengthens the entire test suite to put an end
to this set of problems by embedding invalid default values in all the
connection strings used in the tests.  The invalid values are prefixed
in each connection string, relying on the follow-up values passed in the
connection string to enforce any invalid value previously set.  Note
that two tests related to CRLs are required to fail with certain pre-set
configurations, but we can rely on enforcing an empty value instead
after the invalid set of values.

Reported-by: Kyotaro Horiguchi
Reviewed-by: Andrew Dunstan, Daniel Gustafsson, Kyotaro Horiguchi
Discussion: https://postgr.es/m/20220316.163658.1122740600489097632.horikyota.ntt@gmail.com
backpatch-through: 10
parent 48b6035f
...@@ -134,8 +134,13 @@ note "running client tests"; ...@@ -134,8 +134,13 @@ note "running client tests";
switch_server_cert($node, 'server-cn-only'); switch_server_cert($node, 'server-cn-only');
# Set of default settings for SSL parameters in connection string. This
# makes the tests protected against any defaults the environment may have
# in ~/.postgresql/.
my $default_ssl_connstr = "sslkey=invalid sslcert=invalid sslrootcert=invalid sslcrl=invalid sslcrldir=invalid";
$common_connstr = $common_connstr =
"user=ssltestuser dbname=trustdb sslcert=invalid hostaddr=$SERVERHOSTADDR host=common-name.pg-ssltest.test"; "$default_ssl_connstr user=ssltestuser dbname=trustdb hostaddr=$SERVERHOSTADDR host=common-name.pg-ssltest.test";
# The server should not accept non-SSL connections. # The server should not accept non-SSL connections.
$node->connect_fails( $node->connect_fails(
...@@ -212,9 +217,10 @@ $node->connect_fails( ...@@ -212,9 +217,10 @@ $node->connect_fails(
"CRL belonging to a different CA", "CRL belonging to a different CA",
expected_stderr => qr/SSL error: certificate verify failed/); expected_stderr => qr/SSL error: certificate verify failed/);
# The same for CRL directory # The same for CRL directory. sslcrl='' is added here to override the
# invalid default, so as this does not interfere with this case.
$node->connect_fails( $node->connect_fails(
"$common_connstr sslrootcert=ssl/root+server_ca.crt sslmode=verify-ca sslcrldir=ssl/client-crldir", "$common_connstr sslcrl='' sslrootcert=ssl/root+server_ca.crt sslmode=verify-ca sslcrldir=ssl/client-crldir",
"directory CRL belonging to a different CA", "directory CRL belonging to a different CA",
expected_stderr => qr/SSL error: certificate verify failed/); expected_stderr => qr/SSL error: certificate verify failed/);
...@@ -231,7 +237,7 @@ $node->connect_ok( ...@@ -231,7 +237,7 @@ $node->connect_ok(
# Check that connecting with verify-full fails, when the hostname doesn't # Check that connecting with verify-full fails, when the hostname doesn't
# match the hostname in the server's certificate. # match the hostname in the server's certificate.
$common_connstr = $common_connstr =
"user=ssltestuser dbname=trustdb sslcert=invalid sslrootcert=ssl/root+server_ca.crt hostaddr=$SERVERHOSTADDR"; "$default_ssl_connstr user=ssltestuser dbname=trustdb sslrootcert=ssl/root+server_ca.crt hostaddr=$SERVERHOSTADDR";
$node->connect_ok("$common_connstr sslmode=require host=wronghost.test", $node->connect_ok("$common_connstr sslmode=require host=wronghost.test",
"mismatch between host name and server certificate sslmode=require"); "mismatch between host name and server certificate sslmode=require");
...@@ -249,7 +255,7 @@ $node->connect_fails( ...@@ -249,7 +255,7 @@ $node->connect_fails(
switch_server_cert($node, 'server-multiple-alt-names'); switch_server_cert($node, 'server-multiple-alt-names');
$common_connstr = $common_connstr =
"user=ssltestuser dbname=trustdb sslcert=invalid sslrootcert=ssl/root+server_ca.crt hostaddr=$SERVERHOSTADDR sslmode=verify-full"; "$default_ssl_connstr user=ssltestuser dbname=trustdb sslrootcert=ssl/root+server_ca.crt hostaddr=$SERVERHOSTADDR sslmode=verify-full";
$node->connect_ok( $node->connect_ok(
"$common_connstr host=dns1.alt-name.pg-ssltest.test", "$common_connstr host=dns1.alt-name.pg-ssltest.test",
...@@ -278,7 +284,7 @@ $node->connect_fails( ...@@ -278,7 +284,7 @@ $node->connect_fails(
switch_server_cert($node, 'server-single-alt-name'); switch_server_cert($node, 'server-single-alt-name');
$common_connstr = $common_connstr =
"user=ssltestuser dbname=trustdb sslcert=invalid sslrootcert=ssl/root+server_ca.crt hostaddr=$SERVERHOSTADDR sslmode=verify-full"; "$default_ssl_connstr user=ssltestuser dbname=trustdb sslrootcert=ssl/root+server_ca.crt hostaddr=$SERVERHOSTADDR sslmode=verify-full";
$node->connect_ok( $node->connect_ok(
"$common_connstr host=single.alt-name.pg-ssltest.test", "$common_connstr host=single.alt-name.pg-ssltest.test",
...@@ -302,7 +308,7 @@ $node->connect_fails( ...@@ -302,7 +308,7 @@ $node->connect_fails(
switch_server_cert($node, 'server-cn-and-alt-names'); switch_server_cert($node, 'server-cn-and-alt-names');
$common_connstr = $common_connstr =
"user=ssltestuser dbname=trustdb sslcert=invalid sslrootcert=ssl/root+server_ca.crt hostaddr=$SERVERHOSTADDR sslmode=verify-full"; "$default_ssl_connstr user=ssltestuser dbname=trustdb sslrootcert=ssl/root+server_ca.crt hostaddr=$SERVERHOSTADDR sslmode=verify-full";
$node->connect_ok("$common_connstr host=dns1.alt-name.pg-ssltest.test", $node->connect_ok("$common_connstr host=dns1.alt-name.pg-ssltest.test",
"certificate with both a CN and SANs 1"); "certificate with both a CN and SANs 1");
...@@ -319,7 +325,7 @@ $node->connect_fails( ...@@ -319,7 +325,7 @@ $node->connect_fails(
# not a very sensible certificate, but libpq should handle it gracefully. # not a very sensible certificate, but libpq should handle it gracefully.
switch_server_cert($node, 'server-no-names'); switch_server_cert($node, 'server-no-names');
$common_connstr = $common_connstr =
"user=ssltestuser dbname=trustdb sslcert=invalid sslrootcert=ssl/root+server_ca.crt hostaddr=$SERVERHOSTADDR"; "$default_ssl_connstr user=ssltestuser dbname=trustdb sslrootcert=ssl/root+server_ca.crt hostaddr=$SERVERHOSTADDR";
$node->connect_ok( $node->connect_ok(
"$common_connstr sslmode=verify-ca host=common-name.pg-ssltest.test", "$common_connstr sslmode=verify-ca host=common-name.pg-ssltest.test",
...@@ -335,7 +341,7 @@ $node->connect_fails( ...@@ -335,7 +341,7 @@ $node->connect_fails(
switch_server_cert($node, 'server-revoked'); switch_server_cert($node, 'server-revoked');
$common_connstr = $common_connstr =
"user=ssltestuser dbname=trustdb sslcert=invalid hostaddr=$SERVERHOSTADDR host=common-name.pg-ssltest.test"; "$default_ssl_connstr user=ssltestuser dbname=trustdb hostaddr=$SERVERHOSTADDR host=common-name.pg-ssltest.test";
# Without the CRL, succeeds. With it, fails. # Without the CRL, succeeds. With it, fails.
$node->connect_ok( $node->connect_ok(
...@@ -345,8 +351,10 @@ $node->connect_fails( ...@@ -345,8 +351,10 @@ $node->connect_fails(
"$common_connstr sslrootcert=ssl/root+server_ca.crt sslmode=verify-ca sslcrl=ssl/root+server.crl", "$common_connstr sslrootcert=ssl/root+server_ca.crt sslmode=verify-ca sslcrl=ssl/root+server.crl",
"does not connect with client-side CRL file", "does not connect with client-side CRL file",
expected_stderr => qr/SSL error: certificate verify failed/); expected_stderr => qr/SSL error: certificate verify failed/);
# sslcrl='' is added here to override the invalid default, so as this
# does not interfere with this case.
$node->connect_fails( $node->connect_fails(
"$common_connstr sslrootcert=ssl/root+server_ca.crt sslmode=verify-ca sslcrldir=ssl/root+server-crldir", "$common_connstr sslcrl='' sslrootcert=ssl/root+server_ca.crt sslmode=verify-ca sslcrldir=ssl/root+server-crldir",
"does not connect with client-side CRL directory", "does not connect with client-side CRL directory",
expected_stderr => qr/SSL error: certificate verify failed/); expected_stderr => qr/SSL error: certificate verify failed/);
...@@ -388,7 +396,7 @@ $node->connect_fails( ...@@ -388,7 +396,7 @@ $node->connect_fails(
note "running server tests"; note "running server tests";
$common_connstr = $common_connstr =
"sslrootcert=ssl/root+server_ca.crt sslmode=require dbname=certdb hostaddr=$SERVERHOSTADDR host=localhost"; "$default_ssl_connstr sslrootcert=ssl/root+server_ca.crt sslmode=require dbname=certdb hostaddr=$SERVERHOSTADDR host=localhost";
# no client cert # no client cert
$node->connect_fails( $node->connect_fails(
...@@ -538,7 +546,7 @@ $node->connect_fails( ...@@ -538,7 +546,7 @@ $node->connect_fails(
# works, iff username matches Common Name # works, iff username matches Common Name
# fails, iff username doesn't match Common Name. # fails, iff username doesn't match Common Name.
$common_connstr = $common_connstr =
"sslrootcert=ssl/root+server_ca.crt sslmode=require dbname=verifydb hostaddr=$SERVERHOSTADDR host=localhost"; "$default_ssl_connstr sslrootcert=ssl/root+server_ca.crt sslmode=require dbname=verifydb hostaddr=$SERVERHOSTADDR host=localhost";
$node->connect_ok( $node->connect_ok(
"$common_connstr user=ssltestuser sslcert=ssl/client.crt sslkey=ssl/client_tmp.key", "$common_connstr user=ssltestuser sslcert=ssl/client.crt sslkey=ssl/client_tmp.key",
...@@ -565,7 +573,7 @@ $node->connect_ok( ...@@ -565,7 +573,7 @@ $node->connect_ok(
# intermediate client_ca.crt is provided by client, and isn't in server's ssl_ca_file # intermediate client_ca.crt is provided by client, and isn't in server's ssl_ca_file
switch_server_cert($node, 'server-cn-only', 'root_ca'); switch_server_cert($node, 'server-cn-only', 'root_ca');
$common_connstr = $common_connstr =
"user=ssltestuser dbname=certdb sslkey=ssl/client_tmp.key sslrootcert=ssl/root+server_ca.crt hostaddr=$SERVERHOSTADDR host=localhost"; "$default_ssl_connstr user=ssltestuser dbname=certdb sslkey=ssl/client_tmp.key sslrootcert=ssl/root+server_ca.crt hostaddr=$SERVERHOSTADDR host=localhost";
$node->connect_ok( $node->connect_ok(
"$common_connstr sslmode=require sslcert=ssl/client+client_ca.crt", "$common_connstr sslmode=require sslcert=ssl/client+client_ca.crt",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment