diff --git a/src/test/ssl/ServerSetup.pm b/src/test/ssl/ServerSetup.pm index f63c81cfc6..ad2e036602 100644 --- a/src/test/ssl/ServerSetup.pm +++ b/src/test/ssl/ServerSetup.pm @@ -26,9 +26,52 @@ use Test::More; use Exporter 'import'; our @EXPORT = qw( - configure_test_server_for_ssl switch_server_cert + configure_test_server_for_ssl + run_test_psql + switch_server_cert + test_connect_fails + test_connect_ok ); +# Define a couple of helper functions to test connecting to the server. + +# Attempt connection to server with given connection string. +sub run_test_psql +{ + my $connstr = $_[0]; + my $logstring = $_[1]; + + my $cmd = [ + 'psql', '-X', '-A', '-t', '-c', "SELECT 'connected with $connstr'", + '-d', "$connstr" ]; + + my $result = run_log($cmd); + return $result; +} + +# +# The first argument is a base connection string to use for connection. +# The second argument is a complementary connection string, and it's also +# printed out as the test case name. +sub test_connect_ok +{ + my $common_connstr = $_[0]; + my $connstr = $_[1]; + + my $result = + run_test_psql("$common_connstr $connstr", "(should succeed)"); + ok($result, $connstr); +} + +sub test_connect_fails +{ + my $common_connstr = $_[0]; + my $connstr = $_[1]; + + my $result = run_test_psql("$common_connstr $connstr", "(should fail)"); + ok(!$result, "$connstr (should fail)"); +} + # Copy a set of files, taking into account wildcards sub copy_files { diff --git a/src/test/ssl/t/001_ssltests.pl b/src/test/ssl/t/001_ssltests.pl index 32df273929..890e3051a2 100644 --- a/src/test/ssl/t/001_ssltests.pl +++ b/src/test/ssl/t/001_ssltests.pl @@ -13,44 +13,9 @@ use File::Copy; # postgresql-ssl-regression.test. my $SERVERHOSTADDR = '127.0.0.1'; -# Define a couple of helper functions to test connecting to the server. - +# Allocation of base connection string shared among multiple tests. my $common_connstr; -sub run_test_psql -{ - my $connstr = $_[0]; - my $logstring = $_[1]; - - my $cmd = [ - 'psql', '-X', '-A', '-t', '-c', "SELECT 'connected with $connstr'", - '-d', "$connstr" ]; - - my $result = run_log($cmd); - return $result; -} - -# -# The first argument is a (part of a) connection string, and it's also printed -# out as the test case name. It is appended to $common_connstr global variable, -# which also contains a libpq connection string. -sub test_connect_ok -{ - my $connstr = $_[0]; - - my $result = - run_test_psql("$common_connstr $connstr", "(should succeed)"); - ok($result, $connstr); -} - -sub test_connect_fails -{ - my $connstr = $_[0]; - - my $result = run_test_psql("$common_connstr $connstr", "(should fail)"); - ok(!$result, "$connstr (should fail)"); -} - # The client's private key must not be world-readable, so take a copy # of the key stored in the code tree and update its permissions. copy("ssl/client.key", "ssl/client_tmp.key"); @@ -83,50 +48,59 @@ $common_connstr = # The server should not accept non-SSL connections note "test that the server doesn't accept non-SSL connections"; -test_connect_fails("sslmode=disable"); +test_connect_fails($common_connstr, "sslmode=disable"); # Try without a root cert. In sslmode=require, this should work. In verify-ca # or verify-full mode it should fail note "connect without server root cert"; -test_connect_ok("sslrootcert=invalid sslmode=require"); -test_connect_fails("sslrootcert=invalid sslmode=verify-ca"); -test_connect_fails("sslrootcert=invalid sslmode=verify-full"); +test_connect_ok($common_connstr, "sslrootcert=invalid sslmode=require"); +test_connect_fails($common_connstr, "sslrootcert=invalid sslmode=verify-ca"); +test_connect_fails($common_connstr, "sslrootcert=invalid sslmode=verify-full"); # Try with wrong root cert, should fail. (we're using the client CA as the # root, but the server's key is signed by the server CA) note "connect without wrong server root cert"; -test_connect_fails("sslrootcert=ssl/client_ca.crt sslmode=require"); -test_connect_fails("sslrootcert=ssl/client_ca.crt sslmode=verify-ca"); -test_connect_fails("sslrootcert=ssl/client_ca.crt sslmode=verify-full"); +test_connect_fails($common_connstr, + "sslrootcert=ssl/client_ca.crt sslmode=require"); +test_connect_fails($common_connstr, + "sslrootcert=ssl/client_ca.crt sslmode=verify-ca"); +test_connect_fails($common_connstr, + "sslrootcert=ssl/client_ca.crt sslmode=verify-full"); # Try with just the server CA's cert. This fails because the root file # must contain the whole chain up to the root CA. note "connect with server CA cert, without root CA"; -test_connect_fails("sslrootcert=ssl/server_ca.crt sslmode=verify-ca"); +test_connect_fails($common_connstr, + "sslrootcert=ssl/server_ca.crt sslmode=verify-ca"); # And finally, with the correct root cert. note "connect with correct server CA cert file"; -test_connect_ok("sslrootcert=ssl/root+server_ca.crt sslmode=require"); -test_connect_ok("sslrootcert=ssl/root+server_ca.crt sslmode=verify-ca"); -test_connect_ok("sslrootcert=ssl/root+server_ca.crt sslmode=verify-full"); +test_connect_ok($common_connstr, + "sslrootcert=ssl/root+server_ca.crt sslmode=require"); +test_connect_ok($common_connstr, + "sslrootcert=ssl/root+server_ca.crt sslmode=verify-ca"); +test_connect_ok($common_connstr, + "sslrootcert=ssl/root+server_ca.crt sslmode=verify-full"); # Test with cert root file that contains two certificates. The client should # be able to pick the right one, regardless of the order in the file. -test_connect_ok("sslrootcert=ssl/both-cas-1.crt sslmode=verify-ca"); -test_connect_ok("sslrootcert=ssl/both-cas-2.crt sslmode=verify-ca"); +test_connect_ok($common_connstr, + "sslrootcert=ssl/both-cas-1.crt sslmode=verify-ca"); +test_connect_ok($common_connstr, + "sslrootcert=ssl/both-cas-2.crt sslmode=verify-ca"); note "testing sslcrl option with a non-revoked cert"; # Invalid CRL filename is the same as no CRL, succeeds -test_connect_ok( +test_connect_ok($common_connstr, "sslrootcert=ssl/root+server_ca.crt sslmode=verify-ca sslcrl=invalid"); # A CRL belonging to a different CA is not accepted, fails -test_connect_fails( +test_connect_fails($common_connstr, "sslrootcert=ssl/root+server_ca.crt sslmode=verify-ca sslcrl=ssl/client.crl"); # With the correct CRL, succeeds (this cert is not revoked) -test_connect_ok( +test_connect_ok($common_connstr, "sslrootcert=ssl/root+server_ca.crt sslmode=verify-ca sslcrl=ssl/root+server.crl" ); @@ -136,9 +110,9 @@ note "test mismatch between hostname and server certificate"; $common_connstr = "user=ssltestuser dbname=trustdb sslcert=invalid sslrootcert=ssl/root+server_ca.crt hostaddr=$SERVERHOSTADDR sslmode=verify-full"; -test_connect_ok("sslmode=require host=wronghost.test"); -test_connect_ok("sslmode=verify-ca host=wronghost.test"); -test_connect_fails("sslmode=verify-full host=wronghost.test"); +test_connect_ok($common_connstr, "sslmode=require host=wronghost.test"); +test_connect_ok($common_connstr, "sslmode=verify-ca host=wronghost.test"); +test_connect_fails($common_connstr, "sslmode=verify-full host=wronghost.test"); # Test Subject Alternative Names. switch_server_cert($node, 'server-multiple-alt-names'); @@ -147,12 +121,13 @@ note "test hostname matching with X.509 Subject Alternative Names"; $common_connstr = "user=ssltestuser dbname=trustdb sslcert=invalid sslrootcert=ssl/root+server_ca.crt hostaddr=$SERVERHOSTADDR sslmode=verify-full"; -test_connect_ok("host=dns1.alt-name.pg-ssltest.test"); -test_connect_ok("host=dns2.alt-name.pg-ssltest.test"); -test_connect_ok("host=foo.wildcard.pg-ssltest.test"); +test_connect_ok($common_connstr, "host=dns1.alt-name.pg-ssltest.test"); +test_connect_ok($common_connstr, "host=dns2.alt-name.pg-ssltest.test"); +test_connect_ok($common_connstr, "host=foo.wildcard.pg-ssltest.test"); -test_connect_fails("host=wronghost.alt-name.pg-ssltest.test"); -test_connect_fails("host=deep.subdomain.wildcard.pg-ssltest.test"); +test_connect_fails($common_connstr, "host=wronghost.alt-name.pg-ssltest.test"); +test_connect_fails($common_connstr, + "host=deep.subdomain.wildcard.pg-ssltest.test"); # Test certificate with a single Subject Alternative Name. (this gives a # slightly different error message, that's all) @@ -162,10 +137,11 @@ note "test hostname matching with a single X.509 Subject Alternative Name"; $common_connstr = "user=ssltestuser dbname=trustdb sslcert=invalid sslrootcert=ssl/root+server_ca.crt hostaddr=$SERVERHOSTADDR sslmode=verify-full"; -test_connect_ok("host=single.alt-name.pg-ssltest.test"); +test_connect_ok($common_connstr, "host=single.alt-name.pg-ssltest.test"); -test_connect_fails("host=wronghost.alt-name.pg-ssltest.test"); -test_connect_fails("host=deep.subdomain.wildcard.pg-ssltest.test"); +test_connect_fails($common_connstr, "host=wronghost.alt-name.pg-ssltest.test"); +test_connect_fails($common_connstr, + "host=deep.subdomain.wildcard.pg-ssltest.test"); # Test server certificate with a CN and SANs. Per RFCs 2818 and 6125, the CN # should be ignored when the certificate has both. @@ -175,9 +151,9 @@ note "test certificate with both a CN and SANs"; $common_connstr = "user=ssltestuser dbname=trustdb sslcert=invalid sslrootcert=ssl/root+server_ca.crt hostaddr=$SERVERHOSTADDR sslmode=verify-full"; -test_connect_ok("host=dns1.alt-name.pg-ssltest.test"); -test_connect_ok("host=dns2.alt-name.pg-ssltest.test"); -test_connect_fails("host=common-name.pg-ssltest.test"); +test_connect_ok($common_connstr, "host=dns1.alt-name.pg-ssltest.test"); +test_connect_ok($common_connstr, "host=dns2.alt-name.pg-ssltest.test"); +test_connect_fails($common_connstr, "host=common-name.pg-ssltest.test"); # Finally, test a server certificate that has no CN or SANs. Of course, that's # not a very sensible certificate, but libpq should handle it gracefully. @@ -185,8 +161,10 @@ switch_server_cert($node, 'server-no-names'); $common_connstr = "user=ssltestuser dbname=trustdb sslcert=invalid sslrootcert=ssl/root+server_ca.crt hostaddr=$SERVERHOSTADDR"; -test_connect_ok("sslmode=verify-ca host=common-name.pg-ssltest.test"); -test_connect_fails("sslmode=verify-full host=common-name.pg-ssltest.test"); +test_connect_ok($common_connstr, + "sslmode=verify-ca host=common-name.pg-ssltest.test"); +test_connect_fails($common_connstr, + "sslmode=verify-full host=common-name.pg-ssltest.test"); # Test that the CRL works note "testing client-side CRL"; @@ -196,8 +174,9 @@ $common_connstr = "user=ssltestuser dbname=trustdb sslcert=invalid hostaddr=$SERVERHOSTADDR host=common-name.pg-ssltest.test"; # Without the CRL, succeeds. With it, fails. -test_connect_ok("sslrootcert=ssl/root+server_ca.crt sslmode=verify-ca"); -test_connect_fails( +test_connect_ok($common_connstr, + "sslrootcert=ssl/root+server_ca.crt sslmode=verify-ca"); +test_connect_fails($common_connstr, "sslrootcert=ssl/root+server_ca.crt sslmode=verify-ca sslcrl=ssl/root+server.crl" ); @@ -210,18 +189,18 @@ $common_connstr = "sslrootcert=ssl/root+server_ca.crt sslmode=require dbname=certdb hostaddr=$SERVERHOSTADDR"; # no client cert -test_connect_fails("user=ssltestuser sslcert=invalid"); +test_connect_fails($common_connstr, "user=ssltestuser sslcert=invalid"); # correct client cert -test_connect_ok( +test_connect_ok($common_connstr, "user=ssltestuser sslcert=ssl/client.crt sslkey=ssl/client_tmp.key"); # client cert belonging to another user -test_connect_fails( +test_connect_fails($common_connstr, "user=anotheruser sslcert=ssl/client.crt sslkey=ssl/client_tmp.key"); # revoked client cert -test_connect_fails( +test_connect_fails($common_connstr, "user=ssltestuser sslcert=ssl/client-revoked.crt sslkey=ssl/client-revoked.key" ); @@ -230,8 +209,9 @@ switch_server_cert($node, 'server-cn-only', 'root_ca'); $common_connstr = "user=ssltestuser dbname=certdb sslkey=ssl/client_tmp.key sslrootcert=ssl/root+server_ca.crt hostaddr=$SERVERHOSTADDR"; -test_connect_ok("sslmode=require sslcert=ssl/client+client_ca.crt"); -test_connect_fails("sslmode=require sslcert=ssl/client.crt"); +test_connect_ok($common_connstr, + "sslmode=require sslcert=ssl/client+client_ca.crt"); +test_connect_fails($common_connstr, "sslmode=require sslcert=ssl/client.crt"); # clean up unlink "ssl/client_tmp.key";