diff options
Diffstat (limited to 'src/test/ssl/t/003_sslinfo.pl')
-rw-r--r-- | src/test/ssl/t/003_sslinfo.pl | 165 |
1 files changed, 165 insertions, 0 deletions
diff --git a/src/test/ssl/t/003_sslinfo.pl b/src/test/ssl/t/003_sslinfo.pl new file mode 100644 index 0000000..87fb18a --- /dev/null +++ b/src/test/ssl/t/003_sslinfo.pl @@ -0,0 +1,165 @@ + +# Copyright (c) 2021-2022, PostgreSQL Global Development Group + +use strict; +use warnings; +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; +use Test::More; + +use File::Copy; + +use FindBin; +use lib $FindBin::RealBin; + +use SSL::Server; + +if ($ENV{with_ssl} ne 'openssl') +{ + plan skip_all => 'OpenSSL not supported by this build'; +} + +#### Some configuration +my $ssl_server = SSL::Server->new(); + +sub sslkey +{ + return $ssl_server->sslkey(@_); +} + +sub switch_server_cert +{ + $ssl_server->switch_server_cert(@_); +} + +# This is the hostname used to connect to the server. This cannot be a +# hostname, because the server certificate is always for the domain +# postgresql-ssl-regression.test. +my $SERVERHOSTADDR = '127.0.0.1'; +# This is the pattern to use in pg_hba.conf to match incoming connections. +my $SERVERHOSTCIDR = '127.0.0.1/32'; + +# Allocation of base connection string shared among multiple tests. +my $common_connstr; + +#### Set up the server. + +note "setting up data directory"; +my $node = PostgreSQL::Test::Cluster->new('primary'); +$node->init; + +# PGHOST is enforced here to set up the node, subsequent connections +# will use a dedicated connection string. +$ENV{PGHOST} = $node->host; +$ENV{PGPORT} = $node->port; +$node->start; + +$ssl_server->configure_test_server_for_ssl($node, $SERVERHOSTADDR, + $SERVERHOSTCIDR, 'trust', extensions => [qw(sslinfo)]); + +# We aren't using any CRL's in this suite so we can keep using server-revoked +# as server certificate for simple client.crt connection much like how the +# 001 test does. +switch_server_cert($node, certfile => 'server-revoked'); + +# 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 = + "$default_ssl_connstr sslrootcert=ssl/root+server_ca.crt sslmode=require dbname=certdb hostaddr=$SERVERHOSTADDR host=localhost " + . "user=ssltestuser sslcert=ssl/client_ext.crt " + . sslkey('client_ext.key'); + +# Make sure we can connect even though previous test suites have established this +$node->connect_ok( + $common_connstr, + "certificate authorization succeeds with correct client cert in PEM format", +); + +my $result; + +$result = $node->safe_psql( + "certdb", + "SELECT ssl_is_used();", + connstr => $common_connstr); +is($result, 't', "ssl_is_used() for TLS connection"); + +$result = $node->safe_psql( + "certdb", + "SELECT ssl_version();", + connstr => $common_connstr + . " ssl_min_protocol_version=TLSv1.2 " + . "ssl_max_protocol_version=TLSv1.2"); +is($result, 'TLSv1.2', "ssl_version() correctly returning TLS protocol"); + +$result = $node->safe_psql( + "certdb", + "SELECT ssl_cipher() = cipher FROM pg_stat_ssl WHERE pid = pg_backend_pid();", + connstr => $common_connstr); +is($result, 't', "ssl_cipher() compared with pg_stat_ssl"); + +$result = $node->safe_psql( + "certdb", + "SELECT ssl_client_cert_present();", + connstr => $common_connstr); +is($result, 't', "ssl_client_cert_present() for connection with cert"); + +$result = $node->safe_psql( + "trustdb", + "SELECT ssl_client_cert_present();", + connstr => + "$default_ssl_connstr sslrootcert=ssl/root+server_ca.crt sslmode=require " + . "dbname=trustdb hostaddr=$SERVERHOSTADDR user=ssltestuser host=localhost" +); +is($result, 'f', "ssl_client_cert_present() for connection without cert"); + +$result = $node->safe_psql( + "certdb", + "SELECT ssl_client_serial() = client_serial FROM pg_stat_ssl WHERE pid = pg_backend_pid();", + connstr => $common_connstr); +is($result, 't', "ssl_client_serial() compared with pg_stat_ssl"); + +# Must not use safe_psql since we expect an error here +$result = $node->psql( + "certdb", + "SELECT ssl_client_dn_field('invalid');", + connstr => $common_connstr); +is($result, '3', "ssl_client_dn_field() for an invalid field"); + +$result = $node->safe_psql( + "trustdb", + "SELECT ssl_client_dn_field('commonName');", + connstr => + "$default_ssl_connstr sslrootcert=ssl/root+server_ca.crt sslmode=require " + . "dbname=trustdb hostaddr=$SERVERHOSTADDR user=ssltestuser host=localhost" +); +is($result, '', "ssl_client_dn_field() for connection without cert"); + +$result = $node->safe_psql( + "certdb", + "SELECT '/CN=' || ssl_client_dn_field('commonName') = client_dn FROM pg_stat_ssl WHERE pid = pg_backend_pid();", + connstr => $common_connstr); +is($result, 't', "ssl_client_dn_field() for commonName"); + +$result = $node->safe_psql( + "certdb", + "SELECT ssl_issuer_dn() = issuer_dn FROM pg_stat_ssl WHERE pid = pg_backend_pid();", + connstr => $common_connstr); +is($result, 't', "ssl_issuer_dn() for connection with cert"); + +$result = $node->safe_psql( + "certdb", + "SELECT '/CN=' || ssl_issuer_field('commonName') = issuer_dn FROM pg_stat_ssl WHERE pid = pg_backend_pid();", + connstr => $common_connstr); +is($result, 't', "ssl_issuer_field() for commonName"); + +$result = $node->safe_psql( + "certdb", + "SELECT value, critical FROM ssl_extension_info() WHERE name = 'basicConstraints';", + connstr => $common_connstr); +is($result, 'CA:FALSE|t', 'extract extension from cert'); + +done_testing(); |