From 8b618dd8f03ea9d6dc18bd1dc9c858d795428c95 Mon Sep 17 00:00:00 2001
From: Heikki Linnakangas <heikki.linnakangas@iki.fi>
Date: Wed, 10 Jan 2024 10:25:08 +0200
Subject: [PATCH v7 12/12] Add tests for sslnegotiation

---
 .../t/001_negotiate_encryption.pl             | 110 +++++++++++++-----
 1 file changed, 78 insertions(+), 32 deletions(-)

diff --git a/src/test/libpq_encryption/t/001_negotiate_encryption.pl b/src/test/libpq_encryption/t/001_negotiate_encryption.pl
index 7a80fe90f56..85f55e9c07f 100644
--- a/src/test/libpq_encryption/t/001_negotiate_encryption.pl
+++ b/src/test/libpq_encryption/t/001_negotiate_encryption.pl
@@ -173,6 +173,63 @@ connect_test($node, 'user=testuser sslmode=allow', 'plain');
 connect_test($node, 'user=testuser sslmode=prefer', 'plain');
 connect_test($node, 'user=testuser sslmode=require', 'fail');
 
+connect_test($node, 'user=testuser sslmode=disable sslnegotiation=direct', 'plain');
+connect_test($node, 'user=testuser sslmode=allow sslnegotiation=direct', 'plain');
+connect_test($node, 'user=testuser sslmode=prefer sslnegotiation=direct', 'plain');
+connect_test($node, 'user=testuser sslmode=require sslnegotiation=direct', 'fail');
+
+connect_test($node, 'user=testuser sslmode=disable sslnegotiation=requiredirect', 'plain');
+connect_test($node, 'user=testuser sslmode=allow sslnegotiation=requiredirect', 'plain');
+connect_test($node, 'user=testuser sslmode=prefer sslnegotiation=requiredirect', 'plain');
+connect_test($node, 'user=testuser sslmode=require sslnegotiation=requiredirect', 'fail');
+
+# Enable SSL in the server
+SKIP:
+{
+	skip "SSL not supported by this build" unless $ssl_supported;
+
+	$node->adjust_conf('postgresql.conf', 'ssl', 'on');
+	$node->restart;
+
+	connect_test($node, 'user=testuser sslmode=disable', 'plain');
+	connect_test($node, 'user=testuser sslmode=allow', 'plain');
+	connect_test($node, 'user=testuser sslmode=prefer', 'ssl');
+	connect_test($node, 'user=testuser sslmode=require', 'ssl');
+
+	connect_test($node, 'user=testuser sslmode=disable sslnegotiation=direct', 'plain');
+	connect_test($node, 'user=testuser sslmode=allow sslnegotiation=direct', 'plain');
+	connect_test($node, 'user=testuser sslmode=prefer sslnegotiation=direct', 'ssl');
+	connect_test($node, 'user=testuser sslmode=require sslnegotiation=direct', 'ssl');
+
+	connect_test($node, 'user=testuser sslmode=disable sslnegotiation=requiredirect', 'plain');
+	connect_test($node, 'user=testuser sslmode=allow sslnegotiation=requiredirect', 'plain');
+	connect_test($node, 'user=testuser sslmode=prefer sslnegotiation=requiredirect', 'ssl');
+	connect_test($node, 'user=testuser sslmode=require sslnegotiation=requiredirect', 'ssl');
+
+	connect_test($node, 'user=ssluser sslmode=disable', 'fail');
+	connect_test($node, 'user=ssluser sslmode=allow', 'ssl');
+	connect_test($node, 'user=ssluser sslmode=prefer', 'ssl');
+	connect_test($node, 'user=ssluser sslmode=require', 'ssl');
+
+	connect_test($node, 'user=ssluser sslmode=disable sslnegotiation=direct', 'fail');
+	connect_test($node, 'user=ssluser sslmode=allow sslnegotiation=direct', 'ssl');
+	connect_test($node, 'user=ssluser sslmode=prefer sslnegotiation=direct', 'ssl');
+	connect_test($node, 'user=ssluser sslmode=require sslnegotiation=direct', 'ssl');
+
+	connect_test($node, 'user=ssluser sslmode=disable sslnegotiation=requiredirect', 'fail');
+	connect_test($node, 'user=ssluser sslmode=allow sslnegotiation=requiredirect', 'ssl');
+	connect_test($node, 'user=ssluser sslmode=prefer sslnegotiation=requiredirect', 'ssl');
+	connect_test($node, 'user=ssluser sslmode=require sslnegotiation=requiredirect', 'ssl');
+
+	connect_test($node, 'user=nossluser sslmode=disable', 'plain');
+	connect_test($node, 'user=nossluser sslmode=allow', 'plain');
+	connect_test($node, 'user=nossluser sslmode=prefer', 'plain');
+	connect_test($node, 'user=nossluser sslmode=require', 'fail');
+
+	$node->adjust_conf('postgresql.conf', 'ssl', 'off');
+	$node->reload;
+}
+
 # Test GSSAPI
 SKIP:
 {
@@ -192,8 +249,13 @@ SKIP:
 	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');
+	connect_test($node, 'user=testuser sslmode=prefer sslnegotiation=direct gssencmode=disable', 'plain');
+	connect_test($node, 'user=testuser sslmode=prefer sslnegotiation=direct gssencmode=prefer', 'gss');
+	connect_test($node, 'user=testuser sslmode=prefer sslnegotiation=direct gssencmode=require', 'gss');
+
+	connect_test($node, 'user=testuser sslmode=require sslnegotiation=direct gssencmode=disable', 'fail');
+	connect_test($node, 'user=testuser sslmode=require sslnegotiation=direct gssencmode=prefer', 'gss');
+	connect_test($node, 'user=testuser sslmode=require sslnegotiation=requiredirect gssencmode=prefer', 'gss');
 
 	# If you set both sslmode and gssencmode to 'require', 'gssencmode=require' takes
 	# precedence.
@@ -211,45 +273,26 @@ SKIP:
 	# 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');
+	connect_test($node, 'user=nogssuser sslmode=prefer gssencmode=prefer sslnegotiation=direct', 'plain',
+				 'no pg_hba.conf entry for host "127.0.0.1", user "nogssuser", database "postgres", GSS encryption');
+	connect_test($node, 'user=nogssuser sslmode=prefer gssencmode=prefer sslnegotiation=requiredirect', 'plain',
+				 'no pg_hba.conf entry for host "127.0.0.1", user "nogssuser", database "postgres", GSS encryption');
 }
 
-# Enable SSL in the server
+# Server supports both SSL and GSSAPI
 SKIP:
 {
-	skip "SSL not supported by this build" unless $ssl_supported;
-
-	my $certdir = dirname(__FILE__) . "/../../ssl/ssl";
+	skip "GSSAPI/Kerberos or SSL not supported by this build" unless ($ssl_supported && $gss_supported);
 
-	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");
+	# SSL is still disabled
+	connect_test($node, 'user=testuser sslmode=prefer gssencmode=prefer', 'gss');
+	connect_test($node, 'user=testuser sslmode=prefer gssencmode=prefer sslnegotiation=direct', 'gss');
+	connect_test($node, 'user=testuser sslmode=prefer gssencmode=prefer sslnegotiation=requiredirect', 'gss');
 
+	# Enable SSL
 	$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');
@@ -261,6 +304,9 @@ SKIP:
 	connect_test($node, 'user=testuser sslmode=require gssencmode=disable', 'ssl');
 	connect_test($node, 'user=testuser sslmode=require gssencmode=prefer', 'gss');
 
+	connect_test($node, 'user=testuser sslmode=prefer gssencmode=prefer sslnegotiation=direct', 'gss');
+	connect_test($node, 'user=testuser sslmode=prefer gssencmode=prefer sslnegotiation=requiredirect', 'gss');
+
 	# If you set both sslmode and gssencmode to 'require', 'gssencmode=require' takes
 	# precedence.
 	connect_test($node, 'user=testuser sslmode=require gssencmode=require', 'gss');
-- 
2.39.2

