diff options
author | Heikki Linnakangas <heikki.linnakangas@iki.fi> | 2024-04-12 19:52:37 +0300 |
---|---|---|
committer | Heikki Linnakangas <heikki.linnakangas@iki.fi> | 2024-04-12 19:52:37 +0300 |
commit | 65dfe9d167e925cd8892dedb51dde29f69b7388d (patch) | |
tree | e26827607d829f497918f22d68a5ac140ca5cafe /src/test | |
parent | 084cae55131f71f32e15a6b2b7897aa1c7382c0a (diff) | |
download | postgresql-65dfe9d167e925cd8892dedb51dde29f69b7388d.tar.gz postgresql-65dfe9d167e925cd8892dedb51dde29f69b7388d.zip |
Move libpq encryption negotiation tests
The test targets libpq's options, so 'src/test/interfaces/libpq/t' is
a more natural place for it.
While doing this, I noticed that I had missed adding the
libpq_encryption subdir to the Makefile. That's why this commit only
needs to remove it from the meson.build file.
Per Peter Eisentraut's suggestion.
Discussion: https://www.postgresql.org/message-id/09d4bf5d-d0fa-4c66-a1d7-5ec757609646@eisentraut.org
Diffstat (limited to 'src/test')
-rw-r--r-- | src/test/libpq_encryption/Makefile | 25 | ||||
-rw-r--r-- | src/test/libpq_encryption/README | 31 | ||||
-rw-r--r-- | src/test/libpq_encryption/meson.build | 18 | ||||
-rw-r--r-- | src/test/libpq_encryption/t/001_negotiate_encryption.pl | 724 | ||||
-rw-r--r-- | src/test/meson.build | 1 |
5 files changed, 0 insertions, 799 deletions
diff --git a/src/test/libpq_encryption/Makefile b/src/test/libpq_encryption/Makefile deleted file mode 100644 index 3ad3da7031b..00000000000 --- a/src/test/libpq_encryption/Makefile +++ /dev/null @@ -1,25 +0,0 @@ -#------------------------------------------------------------------------- -# -# Makefile for src/test/libpq_encryption -# -# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group -# Portions Copyright (c) 1994, Regents of the University of California -# -# src/test/libpq_encryption/Makefile -# -#------------------------------------------------------------------------- - -subdir = src/test/libpq_encryption -top_builddir = ../../.. -include $(top_builddir)/src/Makefile.global - -export with_ssl with_gssapi with_krb_srvnam - -check: - $(prove_check) - -installcheck: - $(prove_installcheck) - -clean distclean: - rm -rf tmp_check diff --git a/src/test/libpq_encryption/README b/src/test/libpq_encryption/README deleted file mode 100644 index 8ceb1945277..00000000000 --- a/src/test/libpq_encryption/README +++ /dev/null @@ -1,31 +0,0 @@ -src/test/libpq_encryption/README - -Tests for negotiating network encryption method -=============================================== - -This directory contains a test suite for the libpq options to -negotiate encryption with the server. This requires reconfiguring a -test server, enabling/disabling SSL and GSSAPI, and is therefore kept -separate and not run by default. - -CAUTION: The test server run by this test is configured to listen for TCP -connections on localhost. Any user on the same host is able to log in to the -test server while the tests are running. Do not run this suite on a multi-user -system where you don't trust all local users! Also, this test suite creates a -KDC server that listens for TCP/IP connections on localhost without any real -access control. - -Running the tests -================= - -NOTE: You must have given the --enable-tap-tests argument to configure. - -Run - make check PG_TEST_EXTRA=libpq_encryption - -You can use "make installcheck" if you previously did "make install". -In that case, the code in the installation tree is tested. With -"make check", a temporary installation tree is built from the current -sources and then tested. - -See src/test/perl/README for more info about running these tests. diff --git a/src/test/libpq_encryption/meson.build b/src/test/libpq_encryption/meson.build deleted file mode 100644 index ac1db10d742..00000000000 --- a/src/test/libpq_encryption/meson.build +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group - -tests += { - 'name': 'libpq_encryption', - 'sd': meson.current_source_dir(), - 'bd': meson.current_build_dir(), - 'tap': { - 'tests': [ - 't/001_negotiate_encryption.pl', - ], - 'env': { - 'with_ssl': ssl_library, - 'OPENSSL': openssl.found() ? openssl.path() : '', - 'with_gssapi': gssapi.found() ? 'yes' : 'no', - 'with_krb_srvnam': 'postgres', - }, - }, -} diff --git a/src/test/libpq_encryption/t/001_negotiate_encryption.pl b/src/test/libpq_encryption/t/001_negotiate_encryption.pl deleted file mode 100644 index d07d9498bbc..00000000000 --- a/src/test/libpq_encryption/t/001_negotiate_encryption.pl +++ /dev/null @@ -1,724 +0,0 @@ - -# Copyright (c) 2021-2024, PostgreSQL Global Development Group - -# OVERVIEW -# -------- -# -# Test negotiation of SSL and GSSAPI encryption -# -# We test all combinations of: -# -# - all the libpq client options that affect the protocol negotiations -# (gssencmode, sslmode, sslnegotiation) -# - server accepting or rejecting the authentication due to -# pg_hba.conf entries -# - SSL and GSS enabled/disabled in the server -# -# That's a lot of combinations, so we use a table-driven approach. -# Each combination is represented by a line in a table. The line lists -# the options specifying the test case, and an expected outcome. The -# expected outcome includes whether the connection succeeds or fails, -# and whether it uses SSL, GSS or no encryption. It also includes a -# condensed trace of what steps were taken during the negotiation. -# That can catch cases like useless retries, or if the encryption -# methods are attempted in wrong order, even when it doesn't affect -# the final outcome. -# -# TEST TABLE FORMAT -# ----------------- -# -# Example of the test table format: -# -# # USER GSSENCMODE SSLMODE EVENTS -> OUTCOME -# testuser disable allow connect, authok -> plain -# . . prefer connect, sslaccept, authok -> ssl -# testuser require * connect, gssreject -> fail -# -# USER, GSSENCMODE and SSLMODE fields are the libpq 'user', -# 'gssencmode' and 'sslmode' options used in the test. As a shorthand, -# a single dot ('.') can be used in the USER, GSSENCMODE, and SSLMODE -# fields, to indicate "same as on previous line". A '*' can be used -# as a wildcard; it is expanded to mean all possible values of that -# field. -# -# The EVENTS field is a condensed trace of expected steps during the -# negotiation: -# -# connect: a TCP connection was established -# reconnect: TCP connection was disconnected, and a new one was established -# sslaccept: client requested SSL encryption and server accepted it -# sslreject: client requested SSL encryption but server rejected it -# gssaccept: client requested GSSAPI encryption and server accepted it -# gssreject: client requested GSSAPI encryption but server rejected it -# authok: client sent startup packet and authentication was performed successfully -# authfail: client sent startup packet but server rejected the authentication -# -# The event trace can be used to verify that the client negotiated the -# connection properly in more detail than just by looking at the -# outcome. For example, if the client opens spurious extra TCP -# connections, that would show up in the EVENTS. -# -# The OUTCOME field indicates the expected result of the test: -# -# plain: an unencrypted connection was established -# ssl: SSL connection was established -# gss: GSSAPI encrypted connection was established -# fail: the connection attempt failed -# -# Empty lines are ignored. '#' can be used to mark the rest of the -# line as a comment. - -use strict; -use warnings FATAL => 'all'; -use PostgreSQL::Test::Utils; -use PostgreSQL::Test::Cluster; -use PostgreSQL::Test::Kerberos; -use File::Basename; -use File::Copy; -use Test::More; - -if (!$ENV{PG_TEST_EXTRA} || $ENV{PG_TEST_EXTRA} !~ /\blibpq_encryption\b/) -{ - plan skip_all => - 'Potentially unsafe test libpq_encryption not enabled in PG_TEST_EXTRA'; -} - -my $ssl_supported = $ENV{with_ssl} eq 'openssl'; -my $gss_supported = $ENV{with_gssapi} eq 'yes'; - -### -### Prepare test server for GSSAPI and SSL authentication, with a few -### different test users and helper functions. We don't actually -### enable SSL and kerberos in the server yet, we will do that later. -### - -my $host = 'enc-test-localhost.postgresql.example.com'; -my $hostaddr = '127.0.0.1'; -my $servercidr = '127.0.0.1/32'; - -my $node = PostgreSQL::Test::Cluster->new('node'); -$node->init; -$node->append_conf( - 'postgresql.conf', qq{ -listen_addresses = '$hostaddr' - -# Capturing the EVENTS that occur during tests requires these settings -log_connections = on -log_disconnections = on -trace_connection_negotiation = on -lc_messages = 'C' -}); -my $pgdata = $node->data_dir; - -my $dbname = 'postgres'; -my $username = 'enctest'; -my $application = '001_negotiate_encryption.pl'; - -my $gssuser_password = 'secret1'; - -my $krb; - -if ($gss_supported != 0) -{ - note "setting up Kerberos"; - - my $realm = 'EXAMPLE.COM'; - $krb = PostgreSQL::Test::Kerberos->new($host, $hostaddr, $realm); - $node->append_conf('postgresql.conf', "krb_server_keyfile = '$krb->{keytab}'\n"); -} - -if ($ssl_supported != 0) -{ - my $certdir = dirname(__FILE__) . "/../../ssl/ssl"; - - copy "$certdir/server-cn-only.crt", "$pgdata/server.crt" - || die "copying server.crt: $!"; - copy "$certdir/server-cn-only.key", "$pgdata/server.key" - || die "copying server.key: $!"; - chmod(0600, "$pgdata/server.key") - or die "failed to change permissions on server keys: $!"; - - # Start with SSL disabled. - $node->append_conf('postgresql.conf', "ssl = off\n"); -} - -$node->start; - -$node->safe_psql('postgres', 'CREATE USER localuser;'); -$node->safe_psql('postgres', 'CREATE USER testuser;'); -$node->safe_psql('postgres', 'CREATE USER ssluser;'); -$node->safe_psql('postgres', 'CREATE USER nossluser;'); -$node->safe_psql('postgres', 'CREATE USER gssuser;'); -$node->safe_psql('postgres', 'CREATE USER nogssuser;'); - -my $unixdir = $node->safe_psql('postgres', 'SHOW unix_socket_directories;'); -chomp($unixdir); - -# Helper function that returns the encryption method in use in the -# connection. -$node->safe_psql('postgres', q{ -CREATE FUNCTION current_enc() RETURNS text LANGUAGE plpgsql AS $$ -DECLARE - ssl_in_use bool; - gss_in_use bool; -BEGIN - ssl_in_use = (SELECT ssl FROM pg_stat_ssl WHERE pid = pg_backend_pid()); - gss_in_use = (SELECT encrypted FROM pg_stat_gssapi WHERE pid = pg_backend_pid()); - - raise log 'ssl % gss %', ssl_in_use, gss_in_use; - - IF ssl_in_use AND gss_in_use THEN - RETURN 'ssl+gss'; -- shouldn't happen - ELSIF ssl_in_use THEN - RETURN 'ssl'; - ELSIF gss_in_use THEN - RETURN 'gss'; - ELSE - RETURN 'plain'; - END IF; -END; -$$; -}); - -# Only accept SSL connections from $servercidr. Our tests don't depend on this -# but seems best to keep it as narrow as possible for security reasons. -open my $hba, '>', "$pgdata/pg_hba.conf" or die $!; -print $hba qq{ -# TYPE DATABASE USER ADDRESS METHOD OPTIONS -local postgres localuser trust -host postgres testuser $servercidr trust -hostnossl postgres nossluser $servercidr trust -hostnogssenc postgres nogssuser $servercidr trust -}; - -print $hba qq{ -hostssl postgres ssluser $servercidr trust -} if ($ssl_supported != 0); - -print $hba qq{ -hostgssenc postgres gssuser $servercidr trust -} if ($gss_supported != 0); -close $hba; -$node->reload; - -# Ok, all prepared. Run the tests. - -my @all_test_users = ('testuser', 'ssluser', 'nossluser', 'gssuser', 'nogssuser'); -my @all_gssencmodes = ('disable', 'prefer', 'require'); -my @all_sslmodes = ('disable', 'allow', 'prefer', 'require'); -my @all_sslnegotiations = ('postgres', 'direct', 'requiredirect'); - -my $server_config = { - server_ssl => 0, - server_gss => 0, -}; - -### -### Run tests with GSS and SSL disabled in the server -### -my $test_table; -if ($ssl_supported) { - $test_table = q{ -# USER GSSENCMODE SSLMODE SSLNEGOTIATION EVENTS -> OUTCOME -testuser disable disable * connect, authok -> plain -. . allow * connect, authok -> plain -. . prefer postgres connect, sslreject, authok -> plain -. . . direct connect, directsslreject, reconnect, sslreject, authok -> plain -. . . requiredirect connect, directsslreject, reconnect, authok -> plain -. . require postgres connect, sslreject -> fail -. . . direct connect, directsslreject, reconnect, sslreject -> fail -. . . requiredirect connect, directsslreject -> fail -. prefer disable * connect, authok -> plain -. . allow * connect, authok -> plain -. . prefer postgres connect, sslreject, authok -> plain -. . . direct connect, directsslreject, reconnect, sslreject, authok -> plain -. . . requiredirect connect, directsslreject, reconnect, authok -> plain -. . require postgres connect, sslreject -> fail -. . . direct connect, directsslreject, reconnect, sslreject -> fail -. . . requiredirect connect, directsslreject -> fail - }; -} else { - # Compiled without SSL support - $test_table = q{ -# USER GSSENCMODE SSLMODE SSLNEGOTIATION EVENTS -> OUTCOME -testuser disable disable postgres connect, authok -> plain -. . allow postgres connect, authok -> plain -. . prefer postgres connect, authok -> plain -. prefer disable postgres connect, authok -> plain -. . allow postgres connect, authok -> plain -. . prefer postgres connect, authok -> plain - -# Without SSL support, sslmode=require and sslnegotiation=direct/requiredirect -# are not accepted at all. -. * require * - -> fail -. * * direct - -> fail -. * * requiredirect - -> fail - }; -} - -# All attempts with gssencmode=require fail without connecting because -# no credential cache has been configured in the client. (Or if GSS -# support is not compiled in, they will fail because of that.) -$test_table .= q{ -testuser require * * - -> fail -}; - -note("Running tests with SSL and GSS disabled in the server"); -test_matrix($node, $server_config, - ['testuser'], \@all_gssencmodes, \@all_sslmodes, \@all_sslnegotiations, - parse_table($test_table)); - - -### -### Run tests with GSS disabled and SSL enabled in the server -### -SKIP: -{ - skip "SSL not supported by this build" if $ssl_supported == 0; - - $test_table = q{ -# USER GSSENCMODE SSLMODE SSLNEGOTIATION EVENTS -> OUTCOME -testuser disable disable * connect, authok -> plain -. . allow * connect, authok -> plain -. . prefer postgres connect, sslaccept, authok -> ssl -. . . direct connect, directsslaccept, authok -> ssl -. . . requiredirect connect, directsslaccept, authok -> ssl -. . require postgres connect, sslaccept, authok -> ssl -. . . direct connect, directsslaccept, authok -> ssl -. . . requiredirect connect, directsslaccept, authok -> ssl -ssluser . disable * connect, authfail -> fail -. . allow postgres connect, authfail, reconnect, sslaccept, authok -> ssl -. . . direct connect, authfail, reconnect, directsslaccept, authok -> ssl -. . . requiredirect connect, authfail, reconnect, directsslaccept, authok -> ssl -. . prefer postgres connect, sslaccept, authok -> ssl -. . . direct connect, directsslaccept, authok -> ssl -. . . requiredirect connect, directsslaccept, authok -> ssl -. . require postgres connect, sslaccept, authok -> ssl -. . . direct connect, directsslaccept, authok -> ssl -. . . requiredirect connect, directsslaccept, authok -> ssl -nossluser . disable * connect, authok -> plain -. . allow postgres connect, authok -> plain -. . . direct connect, authok -> plain -. . . requiredirect connect, authok -> plain -. . prefer postgres connect, sslaccept, authfail, reconnect, authok -> plain -. . . direct connect, directsslaccept, authfail, reconnect, authok -> plain -. . . requiredirect connect, directsslaccept, authfail, reconnect, authok -> plain -. . require postgres connect, sslaccept, authfail -> fail -. . require direct connect, directsslaccept, authfail -> fail -. . require requiredirect connect, directsslaccept, authfail -> fail -}; - - # Enable SSL in the server - $node->adjust_conf('postgresql.conf', 'ssl', 'on'); - $node->reload; - $server_config->{server_ssl} = 1; - - note("Running tests with SSL enabled in server"); - test_matrix($node, $server_config, - ['testuser', 'ssluser', 'nossluser'], - ['disable'], \@all_sslmodes, \@all_sslnegotiations, - parse_table($test_table)); - - # Disable SSL again - $node->adjust_conf('postgresql.conf', 'ssl', 'off'); - $node->reload; - $server_config->{server_ssl} = 0; -} - -### -### Run tests with GSS enabled, SSL disabled in the server -### -SKIP: -{ - skip "GSSAPI/Kerberos not supported by this build" if $gss_supported == 0; - - $krb->create_principal('gssuser', $gssuser_password); - $krb->create_ticket('gssuser', $gssuser_password); - $server_config->{server_gss} = 1; - - $test_table = q{ -# USER GSSENCMODE SSLMODE SSLNEGOTIATION EVENTS -> OUTCOME -testuser disable disable * connect, authok -> plain -. . allow * connect, authok -> plain -. . prefer postgres connect, sslreject, authok -> plain -. . . direct connect, directsslreject, reconnect, sslreject, authok -> plain -. . . requiredirect connect, directsslreject, reconnect, authok -> plain -. . require postgres connect, sslreject -> fail -. . . direct connect, directsslreject, reconnect, sslreject -> fail -. . . requiredirect connect, directsslreject -> fail -. prefer * * connect, gssaccept, authok -> gss -. require * * connect, gssaccept, authok -> gss - -gssuser disable disable * connect, authfail -> fail -. . allow postgres connect, authfail, reconnect, sslreject -> fail -. . . direct connect, authfail, reconnect, directsslreject, reconnect, sslreject -> fail -. . . requiredirect connect, authfail, reconnect, directsslreject -> fail -. . prefer postgres connect, sslreject, authfail -> fail -. . . direct connect, directsslreject, reconnect, sslreject, authfail -> fail -. . . requiredirect connect, directsslreject, reconnect, authfail -> fail -. . require postgres connect, sslreject -> fail -. . . direct connect, directsslreject, reconnect, sslreject -> fail -. . . requiredirect connect, directsslreject -> fail -. prefer * * connect, gssaccept, authok -> gss -. require * * connect, gssaccept, authok -> gss - -nogssuser disable disable * connect, authok -> plain -. . allow postgres connect, authok -> plain -. . . direct connect, authok -> plain -. . . requiredirect connect, authok -> plain -. . prefer postgres connect, sslreject, authok -> plain -. . . direct connect, directsslreject, reconnect, sslreject, authok -> plain -. . . requiredirect connect, directsslreject, reconnect, authok -> plain -. . require postgres connect, sslreject -> fail -. . . direct connect, directsslreject, reconnect, sslreject -> fail -. . . requiredirect connect, directsslreject -> fail -. prefer disable * connect, gssaccept, authfail, reconnect, authok -> plain -. . allow postgres connect, gssaccept, authfail, reconnect, authok -> plain -. . . direct connect, gssaccept, authfail, reconnect, authok -> plain -. . . requiredirect connect, gssaccept, authfail, reconnect, authok -> plain -. . prefer postgres connect, gssaccept, authfail, reconnect, sslreject, authok -> plain -. . . direct connect, gssaccept, authfail, reconnect, directsslreject, reconnect, sslreject, authok -> plain -. . . requiredirect connect, gssaccept, authfail, reconnect, directsslreject, reconnect, authok -> plain -. . require postgres connect, gssaccept, authfail, reconnect, sslreject -> fail -. . . direct connect, gssaccept, authfail, reconnect, directsslreject, reconnect, sslreject -> fail -. . . requiredirect connect, gssaccept, authfail, reconnect, directsslreject -> fail -. require disable * connect, gssaccept, authfail -> fail -. . allow * connect, gssaccept, authfail -> fail -. . prefer * connect, gssaccept, authfail -> fail -. . require * connect, gssaccept, authfail -> fail # If both GSSAPI and sslmode are required, and GSS is not available -> fail - }; - - # The expected events and outcomes above assume that SSL support - # is enabled. When libpq is compiled without SSL support, all - # attempts to connect with sslmode=require or - # sslnegotition=direct/requiredirectwould fail immediately without - # even connecting to the server. Skip those, because we tested - # them earlier already. - my ($sslmodes, $sslnegotiations); - if ($ssl_supported != 0) { - ($sslmodes, $sslnegotiations) = (\@all_sslmodes, \@all_sslnegotiations); - } else { - ($sslmodes, $sslnegotiations) = (['disable'], ['postgres']); - } - - note("Running tests with GSS enabled in server"); - test_matrix($node, $server_config, - ['testuser', 'gssuser', 'nogssuser'], - \@all_gssencmodes, $sslmodes, $sslnegotiations, - parse_table($test_table)); -} - -### -### Tests with both GSS and SSL enabled in the server -### -SKIP: -{ - skip "GSSAPI/Kerberos or SSL not supported by this build" unless ($ssl_supported && $gss_supported); - - # Sanity check that GSSAPI is still enabled from previous test. - connect_test($node, 'user=testuser gssencmode=prefer sslmode=prefer', 'connect, gssaccept, authok -> gss'); - - # Enable SSL - $node->adjust_conf('postgresql.conf', 'ssl', 'on'); - $node->reload; - $server_config->{server_ssl} = 1; - - $test_table = q{ -# USER GSSENCMODE SSLMODE SSLNEGOTIATION EVENTS -> OUTCOME -testuser disable disable * connect, authok -> plain -. . allow * connect, authok -> plain -. . prefer postgres connect, sslaccept, authok -> ssl -. . . direct connect, directsslaccept, authok -> ssl -. . . requiredirect connect, directsslaccept, authok -> ssl -. . require postgres connect, sslaccept, authok -> ssl -. . . direct connect, directsslaccept, authok -> ssl -. . . requiredirect connect, directsslaccept, authok -> ssl -. prefer disable * connect, gssaccept, authok -> gss -. . allow * connect, gssaccept, authok -> gss -. . prefer * connect, gssaccept, authok -> gss -. . require * connect, gssaccept, authok -> gss # If both GSS and SSL is possible, GSS is chosen over SSL, even if sslmode=require -. require disable * connect, gssaccept, authok -> gss -. . allow * connect, gssaccept, authok -> gss -. . prefer * connect, gssaccept, authok -> gss -. . require * connect, gssaccept, authok -> gss # If both GSS and SSL is possible, GSS is chosen over SSL, even if sslmode=require - -gssuser disable disable * connect, authfail -> fail -. . allow postgres connect, authfail, reconnect, sslaccept, authfail -> fail -. . . direct connect, authfail, reconnect, directsslaccept, authfail -> fail -. . . requiredirect connect, authfail, reconnect, directsslaccept, authfail -> fail -. . prefer postgres connect, sslaccept, authfail, reconnect, authfail -> fail -. . . direct connect, directsslaccept, authfail, reconnect, authfail -> fail -. . . requiredirect connect, directsslaccept, authfail, reconnect, authfail -> fail -. . require postgres connect, sslaccept, authfail -> fail -. . . direct connect, directsslaccept, authfail -> fail -. . . requiredirect connect, directsslaccept, authfail -> fail -. prefer disable * connect, gssaccept, authok -> gss -. . allow * connect, gssaccept, authok -> gss -. . prefer * connect, gssaccept, authok -> gss -. . require * connect, gssaccept, authok -> gss # GSS is chosen over SSL, even though sslmode=require -. require disable * connect, gssaccept, authok -> gss -. . allow * connect, gssaccept, authok -> gss -. . prefer * connect, gssaccept, authok -> gss -. . require * connect, gssaccept, authok -> gss # If both GSS and SSL is possible, GSS is chosen over SSL, even if sslmode=require - -ssluser disable disable * connect, authfail -> fail -. . allow postgres connect, authfail, reconnect, sslaccept, authok -> ssl -. . . direct connect, authfail, reconnect, directsslaccept, authok -> ssl -. . . requiredirect connect, authfail, reconnect, directsslaccept, authok -> ssl -. . prefer postgres connect, sslaccept, authok -> ssl -. . . direct connect, directsslaccept, authok -> ssl -. . . requiredirect connect, directsslaccept, authok -> ssl -. . require postgres connect, sslaccept, authok -> ssl -. . . direct connect, directsslaccept, authok -> ssl -. . . requiredirect connect, directsslaccept, authok -> ssl -. prefer disable * connect, gssaccept, authfail, reconnect, authfail -> fail -. . allow postgres connect, gssaccept, authfail, reconnect, authfail, reconnect, sslaccept, authok -> ssl -. . . direct connect, gssaccept, authfail, reconnect, authfail, reconnect, directsslaccept, authok -> ssl -. . . requiredirect connect, gssaccept, authfail, reconnect, authfail, reconnect, directsslaccept, authok -> ssl -. . prefer postgres connect, gssaccept, authfail, reconnect, sslaccept, authok -> ssl -. . . direct connect, gssaccept, authfail, reconnect, directsslaccept, authok -> ssl -. . . requiredirect connect, gssaccept, authfail, reconnect, directsslaccept, authok -> ssl -. . require postgres connect, gssaccept, authfail, reconnect, sslaccept, authok -> ssl -. . . direct connect, gssaccept, authfail, reconnect, directsslaccept, authok -> ssl -. . . requiredirect connect, gssaccept, authfail, reconnect, directsslaccept, authok -> ssl -. require disable * connect, gssaccept, authfail -> fail -. . allow * connect, gssaccept, authfail -> fail -. . prefer * connect, gssaccept, authfail -> fail -. . require * connect, gssaccept, authfail -> fail # If both GSS and SSL are required, the sslmode=require is effectively ignored and GSS is required - -nogssuser disable disable * connect, authok -> plain -. . allow postgres connect, authok -> plain -. . . direct connect, authok -> plain -. . . requiredirect connect, authok -> plain -. . prefer postgres connect, sslaccept, authok -> ssl -. . . direct connect, directsslaccept, authok -> ssl -. . . requiredirect connect, directsslaccept, authok -> ssl -. . require postgres connect, sslaccept, authok -> ssl -. . . direct connect, directsslaccept, authok -> ssl -. . . requiredirect connect, directsslaccept, authok -> ssl -. prefer disable * connect, gssaccept, authfail, reconnect, authok -> plain -. . allow * connect, gssaccept, authfail, reconnect, authok -> plain -. . prefer postgres connect, gssaccept, authfail, reconnect, sslaccept, authok -> ssl -. . . direct connect, gssaccept, authfail, reconnect, directsslaccept, authok -> ssl -. . . requiredirect connect, gssaccept, authfail, reconnect, directsslaccept, authok -> ssl -. . require postgres connect, gssaccept, authfail, reconnect, sslaccept, authok -> ssl -. . . direct connect, gssaccept, authfail, reconnect, directsslaccept, authok -> ssl -. . . requiredirect connect, gssaccept, authfail, reconnect, directsslaccept, authok -> ssl -. require disable * connect, gssaccept, authfail -> fail -. . allow * connect, gssaccept, authfail -> fail -. . prefer * connect, gssaccept, authfail -> fail -. . require * connect, gssaccept, authfail -> fail # If both GSS and SSL are required, the sslmode=require is effectively ignored and GSS is required - -nossluser disable disable * connect, authok -> plain -. . allow * connect, authok -> plain -. . prefer postgres connect, sslaccept, authfail, reconnect, authok -> plain -. . . direct connect, directsslaccept, authfail, reconnect, authok -> plain -. . . requiredirect connect, directsslaccept, authfail, reconnect, authok -> plain -. . require postgres connect, sslaccept, authfail -> fail -. . . direct connect, directsslaccept, authfail -> fail -. . . requiredirect connect, directsslaccept, authfail -> fail -. prefer * * connect, gssaccept, authok -> gss -. require * * connect, gssaccept, authok -> gss - }; - - note("Running tests with both GSS and SSL enabled in server"); - test_matrix($node, $server_config, - ['testuser', 'gssuser', 'ssluser', 'nogssuser', 'nossluser'], - \@all_gssencmodes, \@all_sslmodes, \@all_sslnegotiations, - parse_table($test_table)); -} - -### -### Test negotiation over unix domain sockets. -### -SKIP: -{ - skip "Unix domain sockets not supported" unless ($unixdir ne ""); - - # libpq doesn't attempt SSL or GSSAPI over Unix domain - # sockets. The server would reject them too. - connect_test($node, "user=localuser gssencmode=prefer sslmode=prefer host=$unixdir", 'connect, authok -> plain'); - connect_test($node, "user=localuser gssencmode=require sslmode=prefer host=$unixdir", '- -> fail'); -} - -done_testing(); - - -### Helper functions - -# Test the cube of parameters: user, gssencmode, sslmode, and sslnegotitation -sub test_matrix -{ - local $Test::Builder::Level = $Test::Builder::Level + 1; - - my ($pg_node, $node_conf, - $test_users, $gssencmodes, $sslmodes, $sslnegotiations, %expected) = @_; - - foreach my $test_user (@{$test_users}) - { - foreach my $gssencmode (@{$gssencmodes}) - { - foreach my $client_mode (@{$sslmodes}) - { - # sslnegotiation only makes a difference if SSL is enabled. This saves a few combinations. - my ($key, $expected_events); - foreach my $negotiation (@{$sslnegotiations}) - { - $key = "$test_user $gssencmode $client_mode $negotiation"; - $expected_events = $expected{$key}; - if (!defined($expected_events)) { - $expected_events = "<line missing from expected output table>"; - } - connect_test($pg_node, "user=$test_user gssencmode=$gssencmode sslmode=$client_mode sslnegotiation=$negotiation", $expected_events); - } - } - } - } -} - -# Try to establish a connection to the server using libpq. Verify the -# negotiation events and outcome. -sub connect_test -{ - local $Test::Builder::Level = $Test::Builder::Level + 1; - - my ($node, $connstr, $expected_events_and_outcome) = @_; - - my $test_name = " '$connstr' -> $expected_events_and_outcome"; - - my $connstr_full = ""; - $connstr_full .= "dbname=postgres " unless $connstr =~ m/dbname=/; - $connstr_full .= "host=$host hostaddr=$hostaddr " unless $connstr =~ m/host=/; - $connstr_full .= $connstr; - - # Get the current size of the logfile before running the test. - # After the test, we can then check just the new lines that have - # appeared. (This is the same approach that the $node->log_contains - # function uses). - my $log_location = -s $node->logfile; - - # XXX: Pass command with -c, because I saw intermittent test - # failures like this: - # - # ack Broken pipe: write( 13, 'SELECT current_enc()' ) at /usr/local/lib/perl5/site_perl/IPC/Run/IO.pm line 550. - # - # I think that happens if the connection fails before we write the - # query to its stdin. This test gets a lot of connection failures - # on purpose. - my ($ret, $stdout, $stderr) = $node->psql( - 'postgres', - '', - extra_params => ['-w', '-c', 'SELECT current_enc()'], - connstr => "$connstr_full", - on_error_stop => 0); - - my $outcome = $ret == 0 ? $stdout : 'fail'; - - # Parse the EVENTS from the log file. - my $log_contents = - PostgreSQL::Test::Utils::slurp_file($node->logfile, $log_location); - my @events = parse_log_events($log_contents); - - # Check that the events and outcome match the expected events and - # outcome - my $events_and_outcome = join(', ', @events) . " -> $outcome"; - is($events_and_outcome, $expected_events_and_outcome, $test_name) or diag("$stderr"); -} - -# Parse a test table. See comment at top of the file for the format. -sub parse_table -{ - my ($table) = @_; - my @lines = split /\n/, $table; - - my %expected; - - my ($user, $gssencmode, $sslmode, $sslnegotiation); - foreach my $line (@lines) { - - # Trim comments - $line =~ s/#.*$//; - - # Trim whitespace at beginning and end - $line =~ s/^\s+//; - $line =~ s/\s+$//; - - # Ignore empty lines (includes comment-only lines) - next if $line eq ''; - - $line =~ m/^(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S.*)\s*->\s*(\S+)\s*$/ or die "could not parse line \"$line\""; - $user = $1 unless $1 eq "."; - $gssencmode = $2 unless $2 eq "."; - $sslmode = $3 unless $3 eq "."; - $sslnegotiation = $4 unless $4 eq "."; - - # Normalize the whitespace in the "EVENTS -> OUTCOME" part - my @events = split /,\s*/, $5; - my $outcome = $6; - my $events_str = join(', ', @events); - $events_str =~ s/\s+$//; # trim whitespace - my $events_and_outcome = "$events_str -> $outcome"; - - my %expanded = expand_expected_line($user, $gssencmode, $sslmode, $sslnegotiation, $events_and_outcome); - %expected = (%expected, %expanded); - } - return %expected; -} - -# Expand wildcards on a test table line -sub expand_expected_line -{ - my ($user, $gssencmode, $sslmode, $sslnegotiation, $expected) = @_; - - my %result; - if ($user eq '*') { - foreach my $x (@all_test_users) { - %result = (%result, expand_expected_line($x, $gssencmode, $sslmode, $sslnegotiation, $expected)); - } - } elsif ($gssencmode eq '*') { - foreach my $x (@all_gssencmodes) { - %result = (%result, expand_expected_line($user, $x, $sslmode, $sslnegotiation, $expected)); - } - } elsif ($sslmode eq '*') { - foreach my $x (@all_sslmodes) { - %result = (%result, expand_expected_line($user, $gssencmode, $x, $sslnegotiation, $expected)); - } - } elsif ($sslnegotiation eq '*') { - foreach my $x (@all_sslnegotiations) { - %result = (%result, expand_expected_line($user, $gssencmode, $sslmode, $x, $expected)); - } - } else { - $result{"$user $gssencmode $sslmode $sslnegotiation"} = $expected; - } - return %result; -} - -# Scrape the server log for the negotiation events that match the -# EVENTS field of the test tables. -sub parse_log_events -{ - my ($log_contents) = (@_); - - my @events = (); - - my @lines = split /\n/, $log_contents; - foreach my $line (@lines) { - push @events, "reconnect" if $line =~ /connection received/ && scalar(@events) > 0; - push @events, "connect" if $line =~ /connection received/ && scalar(@events) == 0; - push @events, "sslaccept" if $line =~ /SSLRequest accepted/; - push @events, "sslreject" if $line =~ /SSLRequest rejected/; - push @events, "directsslaccept" if $line =~ /direct SSL connection accepted/; - push @events, "directsslreject" if $line =~ /direct SSL connection rejected/; - push @events, "gssaccept" if $line =~ /GSSENCRequest accepted/; - push @events, "gssreject" if $line =~ /GSSENCRequest rejected/; - push @events, "authfail" if $line =~ /no pg_hba.conf entry/; - push @events, "authok" if $line =~ /connection authenticated/; - } - - # No events at all is represented by "-" - if (scalar @events == 0) { - push @events, "-" - } - - return @events; -} diff --git a/src/test/meson.build b/src/test/meson.build index 702213bc6f6..c3d0dfedf1c 100644 --- a/src/test/meson.build +++ b/src/test/meson.build @@ -4,7 +4,6 @@ subdir('regress') subdir('isolation') subdir('authentication') -subdir('libpq_encryption') subdir('recovery') subdir('subscription') subdir('modules') |