From c95d2159c1dd3f269383a9bd830e1c804dba34c8 Mon Sep 17 00:00:00 2001 From: Heikki Linnakangas <heikki.linnakangas@iki.fi> Date: Fri, 26 Jul 2024 14:52:08 +0300 Subject: [PATCH] Fix fallback behavior when server sends an ERROR early at startup With sslmode=prefer, the desired behavior is to completely fail the connection attempt, *not* fall back to a plaintext connection, if the server responds to the SSLRequest with an error ('E') response instead of rejecting SSL with an 'N' response. This was broken in commit 05fd30c0e7. Reported-by: Jacob Champion Reviewed-by: Michael Paquier Discussion: https://www.postgresql.org/message-id/CAOYmi%2Bnwvu21mJ4DYKUa98HdfM_KZJi7B1MhyXtnsyOO-PB6Ww%40mail.gmail.com Backpatch-through: 17 --- src/interfaces/libpq/fe-connect.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c index e003279fb6..360d9a4547 100644 --- a/src/interfaces/libpq/fe-connect.c +++ b/src/interfaces/libpq/fe-connect.c @@ -3521,6 +3521,12 @@ keep_going: /* We will come back to here until there is * byte here. */ conn->status = CONNECTION_AWAITING_RESPONSE; + + /* + * Don't fall back to a plaintext connection after + * reading the error. + */ + conn->failed_enc_methods |= conn->allowed_enc_methods & (~conn->current_enc_method); goto keep_going; } else @@ -3612,6 +3618,13 @@ keep_going: /* We will come back to here until there is * into AWAITING_RESPONSE state and let the code there * deal with it. Note we have *not* consumed the "E" * byte here. + * + * Note that unlike on an error response to + * SSLRequest, we allow falling back to SSL or + * plaintext connection here. GSS support was + * introduced in PostgreSQL version 12, so an error + * response might mean that we are connecting to a + * pre-v12 server. */ conn->status = CONNECTION_AWAITING_RESPONSE; goto keep_going; @@ -3659,6 +3672,10 @@ keep_going: /* We will come back to here until there is } else if (pollres == PGRES_POLLING_FAILED) { + /* + * GSS handshake failed. We will retry with an SSL or + * plaintext connection, if permitted by the options. + */ CONNECTION_FAILED(); } /* Else, return POLLING_READING or POLLING_WRITING status */