v7-0002-Add-enc-tests.patch
text/x-patch
Filename: v7-0002-Add-enc-tests.patch
Type: text/x-patch
Part: 1
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch v7-0002
Subject: Add enc tests
| File | + | − |
|---|---|---|
| src/test/libpq_encryption/Makefile | 25 | 0 |
| src/test/libpq_encryption/meson.build | 19 | 0 |
| src/test/libpq_encryption/README | 23 | 0 |
| src/test/libpq_encryption/t/001_negotiate_encryption.pl | 294 | 0 |
| src/test/perl/PostgreSQL/Test/Kerberos.pm | 3 | 3 |
From 9df81d1607ad9a94ddfa48132bfd3f7b7c49f120 Mon Sep 17 00:00:00 2001
From: Heikki Linnakangas <heikki.linnakangas@iki.fi>
Date: Wed, 10 Jan 2024 09:47:46 +0200
Subject: [PATCH v7 02/12] Add enc tests
---
src/test/libpq_encryption/Makefile | 25 ++
src/test/libpq_encryption/README | 23 ++
src/test/libpq_encryption/meson.build | 19 ++
.../t/001_negotiate_encryption.pl | 294 ++++++++++++++++++
src/test/perl/PostgreSQL/Test/Kerberos.pm | 6 +-
5 files changed, 364 insertions(+), 3 deletions(-)
create mode 100644 src/test/libpq_encryption/Makefile
create mode 100644 src/test/libpq_encryption/README
create mode 100644 src/test/libpq_encryption/meson.build
create mode 100644 src/test/libpq_encryption/t/001_negotiate_encryption.pl
diff --git a/src/test/libpq_encryption/Makefile b/src/test/libpq_encryption/Makefile
new file mode 100644
index 00000000000..710929c4cce
--- /dev/null
+++ b/src/test/libpq_encryption/Makefile
@@ -0,0 +1,25 @@
+#-------------------------------------------------------------------------
+#
+# 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/ldap/libpq_encryption
+#
+#-------------------------------------------------------------------------
+
+subdir = src/test/libpq_encryption
+top_builddir = ../../..
+include $(top_builddir)/src/Makefile.global
+
+export OPENSSL 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
new file mode 100644
index 00000000000..66430b54316
--- /dev/null
+++ b/src/test/libpq_encryption/README
@@ -0,0 +1,23 @@
+src/test/libpq_encryption/README
+
+Tests for negotiating network encryption method
+===============================================
+
+
+Running the tests
+=================
+
+NOTE: You must have given the --enable-tap-tests argument to configure.
+
+Run
+ make check PG_TEST_EXTRA=libpq_encryption
+
+XXX 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.
+
+XXX Either way, this test initializes, starts, and stops a test Postgres
+cluster, as well as a test LDAP server.
+
+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
new file mode 100644
index 00000000000..04f479e9fe7
--- /dev/null
+++ b/src/test/libpq_encryption/meson.build
@@ -0,0 +1,19 @@
+# Copyright (c) 2022-2024, PostgreSQL Global Development Group
+
+tests += {
+ 'name': 'ldap',
+ 'sd': meson.current_source_dir(),
+ 'bd': meson.current_build_dir(),
+ 'tap': {
+ 'tests': [
+ 't/001_auth.pl',
+ 't/002_bindpasswd.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
new file mode 100644
index 00000000000..7a80fe90f56
--- /dev/null
+++ b/src/test/libpq_encryption/t/001_negotiate_encryption.pl
@@ -0,0 +1,294 @@
+
+# Copyright (c) 2021-2024, PostgreSQL Global Development Group
+
+# Test negotiation of SSL and GSSAPI encryption
+
+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 $host = 'enc-test-localhost.postgresql.example.com';
+my $hostaddr = '127.0.0.1';
+my $servercidr = '127.0.0.1/32';
+
+note "setting up PostgreSQL instance";
+
+my $node = PostgreSQL::Test::Cluster->new('node');
+$node->init;
+$node->append_conf(
+ 'postgresql.conf', qq{
+listen_addresses = '$hostaddr'
+log_connections = 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;
+
+my $ssl_supported = $ENV{with_ssl} eq 'openssl';
+my $gss_supported = $ENV{with_gssapi} eq 'yes';
+
+if ($ENV{with_gssapi} eq 'yes')
+{
+ 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 ($ENV{with_ssl} eq 'openssl')
+{
+ 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");
+
+ # 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);
+
+$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.
+#
+# When connecting to certdb, also check the client certificate.
+open my $hba, '>', "$pgdata/pg_hba.conf";
+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 ($ENV{with_ssl} eq 'openssl');
+
+print $hba qq{
+hostgssenc postgres gssuser $servercidr trust
+} if ($ENV{with_gssapi} eq 'yes');
+close $hba;
+$node->reload;
+
+note "running tests";
+
+sub connect_test
+{
+ local $Test::Builder::Level = $Test::Builder::Level + 1;
+
+ my ($node, $connstr, $expected_enc, @expect_log_msgs)
+ = @_;
+
+ my %params = ();
+
+ if (@expect_log_msgs)
+ {
+ # Match every message literally.
+ my @regexes = map { qr/\Q$_\E/ } @expect_log_msgs;
+
+ $params{log_like} = \@regexes;
+ }
+
+ my $test_name = "'$connstr' -> $expected_enc";
+
+ my $connstr_full = "";
+ $connstr_full .= "dbname=postgres " unless $connstr =~ m/dbname=/;
+ $connstr_full .= "host=$host hostaddr=$hostaddr " unless $connstr =~ m/host=/;
+ $connstr_full .= $connstr;
+
+ if ($expected_enc eq "fail")
+ {
+ $node->connect_fails($connstr_full, $test_name, %params);
+ }
+ else
+ {
+ $params{sql} = "SELECT current_enc()";
+ $params{expected_stdout} = qr/^$expected_enc$/;;
+
+ $node->connect_ok($connstr_full, $test_name, %params);
+ }
+}
+
+
+# First test with SSL disabled in the server
+connect_test($node, 'user=testuser sslmode=disable', 'plain');
+connect_test($node, 'user=testuser sslmode=allow', 'plain');
+connect_test($node, 'user=testuser sslmode=prefer', 'plain');
+connect_test($node, 'user=testuser sslmode=require', 'fail');
+
+# Test GSSAPI
+SKIP:
+{
+ skip "GSSAPI/Kerberos not supported by this build" unless $ENV{with_gssapi} eq 'yes';
+
+ # No ticket
+ connect_test($node, 'user=testuser sslmode=disable gssencmode=require', 'fail');
+
+ $krb->create_principle('gssuser', $gssuser_password);
+ $krb->create_ticket('gssuser', $gssuser_password);
+
+ connect_test($node, 'user=testuser sslmode=disable gssencmode=disable', 'plain');
+ connect_test($node, 'user=testuser sslmode=disable gssencmode=prefer', 'gss');
+ connect_test($node, 'user=testuser sslmode=disable gssencmode=require', 'gss');
+
+ connect_test($node, 'user=testuser sslmode=prefer gssencmode=disable', 'plain');
+ connect_test($node, 'user=testuser sslmode=prefer gssencmode=prefer', 'gss');
+ connect_test($node, 'user=testuser sslmode=prefer gssencmode=require', 'gss');
+
+ connect_test($node, 'user=testuser sslmode=require gssencmode=disable', 'fail');
+ connect_test($node, 'user=testuser sslmode=require gssencmode=prefer', 'gss');
+
+ # If you set both sslmode and gssencmode to 'require', 'gssencmode=require' takes
+ # precedence.
+ connect_test($node, 'user=testuser sslmode=require gssencmode=require', 'gss');
+
+ # Test case that server supports GSSAPI, but it's not allowed for
+ # this user.
+ connect_test($node, 'user=nogssuser sslmode=prefer gssencmode=require', 'fail',
+ 'no pg_hba.conf entry for host "127.0.0.1", user "nogssuser", database "postgres", GSS encryption');
+
+ # With 'gssencmode=prefer', libpq will first negotiate GSSAPI
+ # encryption, but the connection will fail because pg_hba.conf
+ # forbids GSSAPI encryption for this user. It will then reconnect
+ # with SSL, but the server doesn't support it, so it will continue
+ # with no encryption.
+ connect_test($node, 'user=nogssuser sslmode=prefer gssencmode=prefer', 'plain',
+ 'no pg_hba.conf entry for host "127.0.0.1", user "nogssuser", database "postgres", GSS encryption');
+}
+
+# Enable SSL in the server
+SKIP:
+{
+ skip "SSL not supported by this build" unless $ssl_supported;
+
+ 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");
+
+ $node->adjust_conf('postgresql.conf', 'ssl', 'on');
+ $node->reload;
+
+ connect_test($node, 'user=testuser sslmode=disable gssencmode=disable', 'plain');
+ connect_test($node, 'user=testuser sslmode=allow gssencmode=disable', 'plain');
+ connect_test($node, 'user=testuser sslmode=prefer gssencmode=disable', 'ssl');
+ connect_test($node, 'user=testuser sslmode=require gssencmode=disable', 'ssl');
+
+ connect_test($node, 'user=ssluser sslmode=disable gssencmode=disable', 'fail');
+ connect_test($node, 'user=ssluser sslmode=allow gssencmode=disable', 'ssl');
+ connect_test($node, 'user=ssluser sslmode=prefer gssencmode=disable', 'ssl');
+ connect_test($node, 'user=ssluser sslmode=require gssencmode=disable', 'ssl');
+
+ connect_test($node, 'user=nossluser sslmode=disable gssencmode=disable', 'plain');
+ connect_test($node, 'user=nossluser sslmode=allow gssencmode=disable', 'plain');
+ connect_test($node, 'user=nossluser sslmode=prefer gssencmode=disable', 'plain');
+ connect_test($node, 'user=nossluser sslmode=require gssencmode=disable', 'fail');
+}
+
+# Server supports SSL and GSSAPI
+SKIP:
+{
+ skip "GSSAPI/Kerberos or SSL not supported by this build" unless ($ssl_supported && $gss_supported);
+
+ connect_test($node, 'user=testuser sslmode=disable gssencmode=disable', 'plain');
+ connect_test($node, 'user=testuser sslmode=disable gssencmode=prefer', 'gss');
+ connect_test($node, 'user=testuser sslmode=disable gssencmode=require', 'gss');
+
+ connect_test($node, 'user=testuser sslmode=prefer gssencmode=disable', 'ssl');
+ connect_test($node, 'user=testuser sslmode=prefer gssencmode=prefer', 'gss');
+ connect_test($node, 'user=testuser sslmode=prefer gssencmode=require', 'gss');
+
+ connect_test($node, 'user=testuser sslmode=require gssencmode=disable', 'ssl');
+ connect_test($node, 'user=testuser sslmode=require gssencmode=prefer', 'gss');
+
+ # If you set both sslmode and gssencmode to 'require', 'gssencmode=require' takes
+ # precedence.
+ connect_test($node, 'user=testuser sslmode=require gssencmode=require', 'gss');
+
+ # Test case that server supports GSSAPI, but it's not allowed for
+ # this user.
+ connect_test($node, 'user=nogssuser sslmode=prefer gssencmode=require', 'fail',
+ 'no pg_hba.conf entry for host "127.0.0.1", user "nogssuser", database "postgres", GSS encryption');
+
+ # with 'gssencmode=prefer', libpq will first negotiate GSSAPI
+ # encryption, but the connection will fail because pg_hba.conf
+ # forbids GSSAPI encryption for this user. It will then reconnect
+ # with SSL.
+ connect_test($node, 'user=nogssuser sslmode=prefer gssencmode=prefer', 'ssl',
+ 'no pg_hba.conf entry for host "127.0.0.1", user "nogssuser", database "postgres", GSS encryption');
+
+ # Setting both sslmode=require and gssencmode=require fails if GSSAPI is not
+ # available.
+ connect_test($node, 'user=nogssuser sslmode=require gssencmode=require', 'fail');
+}
+
+# Test negotiation over unix domain sockets.
+SKIP:
+{
+ skip "Unix domain sockets not supported" unless ($unixdir ne "");
+
+ connect_test($node, "user=localuser sslmode=require gssencmode=prefer host=$unixdir", 'plain');
+ connect_test($node, "user=localuser sslmode=prefer gssencmode=require host=$unixdir", 'fail');
+}
+
+done_testing();
diff --git a/src/test/perl/PostgreSQL/Test/Kerberos.pm b/src/test/perl/PostgreSQL/Test/Kerberos.pm
index 382a38ec9d2..b9c5c388085 100644
--- a/src/test/perl/PostgreSQL/Test/Kerberos.pm
+++ b/src/test/perl/PostgreSQL/Test/Kerberos.pm
@@ -81,10 +81,10 @@ sub new
my ($stdout, $krb5_version);
run_log [ $krb5_config, '--version' ], '>', \$stdout
- or BAIL_OUT("could not execute krb5-config");
- BAIL_OUT("Heimdal is not supported") if $stdout =~ m/heimdal/;
+ or die("could not execute krb5-config");
+ die("Heimdal is not supported") if $stdout =~ m/heimdal/;
$stdout =~ m/Kerberos 5 release ([0-9]+\.[0-9]+)/
- or BAIL_OUT("could not get Kerberos version");
+ or die("could not get Kerberos version");
$krb5_version = $1;
# Build the krb5.conf to use.
--
2.39.2