From 664555decb695123a4bf25ea56f789202b926ea0 Mon Sep 17 00:00:00 2001
From: Heikki Linnakangas <heikki.linnakangas@iki.fi>
Date: Wed, 24 Apr 2024 00:10:24 +0300
Subject: [PATCH 1/1] Fix documentation and comments on what happens after GSS
 rejection

The paragraph in the docs and the comment applied to
sslnegotiaton=direct, but not sslnegotiation=requiredirect. In
'requiredirect' mode, negotiated SSL is never used. Move the paragraph
in the docs under the description of 'direct' mode, and rephrase it.

Also the comment's reference to reusing a plaintext connection was
bogus. Authentication failure in plaintext mode only happens after
sending the startup packet, so the connection cannot be reused.
---
 doc/src/sgml/libpq.sgml           | 19 +++++++++----------
 src/interfaces/libpq/fe-connect.c | 11 ++++++-----
 2 files changed, 15 insertions(+), 15 deletions(-)

diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index 9199d0d2e5..7f854edfa2 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -1803,6 +1803,15 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname
              process adds significant latency if the initial SSL connection
              fails.
            </para>
+           <para>
+             An exception is if <literal>gssencmode</literal> is set
+             to <literal>prefer</literal>, but the server rejects GSS encryption.
+             In that case, SSL is negotiated over the same TCP connection using
+             <productname>PostgreSQL</productname> protocol negotiation. In
+             other words, the direct SSL handshake is not used, if a TCP
+             connection has already been established and can be used for the
+             SSL handshake.
+           </para>
           </listitem>
          </varlistentry>
 
@@ -1816,16 +1825,6 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname
           </listitem>
          </varlistentry>
         </variablelist>
-
-       <para>
-        Note that if <literal>gssencmode</literal> is set
-        to <literal>prefer</literal>, a <acronym>GSS</acronym> connection is
-        attempted first. If the server rejects GSS encryption, SSL is
-        negotiated over the same TCP connection using the traditional postgres
-        protocol, regardless of <literal>sslnegotiation</literal>. In other
-        words, the direct SSL handshake is not used, if a TCP connection has
-        already been established and can be used for the SSL handshake.
-       </para>
       </listitem>
      </varlistentry>
 
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index ec20e3f3a9..b1d3bfa59d 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -4430,11 +4430,12 @@ select_next_encryption_method(PGconn *conn, bool have_valid_connection)
 
 	/*
 	 * If enabled, try direct SSL. Unless we have a valid TCP connection that
-	 * failed negotiating GSSAPI encryption or a plaintext connection in case
-	 * of sslmode='allow'; in that case we prefer to reuse the connection with
-	 * negotiated SSL, instead of reconnecting to do direct SSL. The point of
-	 * direct SSL is to avoid the roundtrip from the negotiation, but
-	 * reconnecting would also incur a roundtrip.
+	 * failed negotiating GSSAPI encryption; in that case we prefer to reuse
+	 * the connection with negotiated SSL, instead of reconnecting to do
+	 * direct SSL. The point of sslnegotiation=direct is to avoid the
+	 * roundtrip from the negotiation, but reconnecting would also incur a
+	 * roundtrip. (In sslnegotiation=requiredirect mode, negotiatied SSL is
+	 * not in the list of allowed methods and we will reconnect.)
 	 */
 	if (have_valid_connection)
 		SELECT_NEXT_METHOD(ENC_NEGOTIATED_SSL);
-- 
2.39.2

