libpq: Fix error messages when server rejects SSL or GSS

These messages were lost in commit 05fd30c0e7. Put them back.

This makes one change in the error message behavior compared to v16,
in the case that the server responds to GSSRequest with an error
instead of rejecting it with 'N'. Previously, libpq would hide the
error that the server sent, assuming that you got the error because
the server is an old pre-v12 version that doesn't understand the
GSSRequest message. A v11 server sends a "FATAL: unsupported frontend
protocol 1234.5680: server supports 2.0 to 3.0" error if you try to
connect to it with GSS. That was a reasonable assumption when the
feature was introduced, but v12 was released a long time ago and I
don't think it's the most probable cause anymore. The attached patch
changes things so that libpq prints the error message that the server
sent in that case, making the "server responds with error to
GSSRequest" case behave the same as the "server responds with error to
SSLRequest" case.

Reported-by: Peter Eisentraut
Discussion: https://www.postgresql.org/message-id/bb3b94da-afc7-438d-8940-cb946e553d9d@eisentraut.org
This commit is contained in:
Heikki Linnakangas 2024-04-29 18:12:21 +03:00
parent 7e61e4cc7c
commit 87d2801d4b
1 changed files with 35 additions and 14 deletions

View File

@ -2861,12 +2861,17 @@ keep_going: /* We will come back to here until there is
need_new_connection = false;
}
/* Decide what to do next, if SSL or GSS negotiation fails */
#define ENCRYPTION_NEGOTIATION_FAILED() \
/*
* Decide what to do next, if server rejects SSL or GSS negotiation, but
* the connection is still valid. If there are no options left, error out
* with 'msg'.
*/
#define ENCRYPTION_NEGOTIATION_FAILED(msg) \
do { \
switch (encryption_negotiation_failed(conn)) \
{ \
case 0: \
libpq_append_conn_error(conn, (msg)); \
goto error_return; \
case 1: \
conn->status = CONNECTION_MADE; \
@ -2877,7 +2882,11 @@ keep_going: /* We will come back to here until there is
} \
} while(0);
/* Decide what to do next, if connection fails */
/*
* Decide what to do next, if connection fails. If there are no options
* left, return with an error. The error message has already been written
* to the connection's error buffer.
*/
#define CONNECTION_FAILED() \
do { \
if (connection_failed(conn)) \
@ -3483,9 +3492,13 @@ keep_going: /* We will come back to here until there is
{
/* mark byte consumed */
conn->inStart = conn->inCursor;
/* OK to do without SSL? */
/* We can proceed using this connection */
ENCRYPTION_NEGOTIATION_FAILED();
/*
* The connection is still valid, so if it's OK to
* continue without SSL, we can proceed using this
* connection. Otherwise return with an error.
*/
ENCRYPTION_NEGOTIATION_FAILED("server does not support SSL, but SSL was required");
}
else if (SSLok == 'E')
{
@ -3583,13 +3596,17 @@ keep_going: /* We will come back to here until there is
if (gss_ok == 'E')
{
/*
* Server failure of some sort. Assume it's a
* protocol version support failure, and let's see if
* we can't recover (if it's not, we'll get a better
* error message on retry). Server gets fussy if we
* don't hang up the socket, though.
* Server failure of some sort, possibly protocol
* version support failure. We need to process and
* report the error message, which might be formatted
* according to either protocol 2 or protocol 3.
* Rather than duplicate the code for that, we flip
* into AWAITING_RESPONSE state and let the code there
* deal with it. Note we have *not* consumed the "E"
* byte here.
*/
CONNECTION_FAILED();
conn->status = CONNECTION_AWAITING_RESPONSE;
goto keep_going;
}
/* mark byte consumed */
@ -3597,8 +3614,12 @@ keep_going: /* We will come back to here until there is
if (gss_ok == 'N')
{
/* We can proceed using this connection */
ENCRYPTION_NEGOTIATION_FAILED();
/*
* The connection is still valid, so if it's OK to
* continue without GSS, we can proceed using this
* connection. Otherwise return with an error.
*/
ENCRYPTION_NEGOTIATION_FAILED("server doesn't support GSSAPI encryption, but it was required");
}
else if (gss_ok != 'G')
{