diff options
author | Peter Eisentraut <peter@eisentraut.org> | 2022-11-17 15:14:44 +0100 |
---|---|---|
committer | Peter Eisentraut <peter@eisentraut.org> | 2022-11-17 15:42:09 +0100 |
commit | bbf9c282ce92272ed7bf6771daf0f9efa209e61b (patch) | |
tree | f05ce44758da3450325dae752d595f623b2f9883 /src/interfaces/libpq/fe-protocol3.c | |
parent | dce92e59b1a9ff8401a660a1ac448ea37d498284 (diff) | |
download | postgresql-bbf9c282ce92272ed7bf6771daf0f9efa209e61b.tar.gz postgresql-bbf9c282ce92272ed7bf6771daf0f9efa209e61b.zip |
libpq: Handle NegotiateProtocolVersion message
Before, receiving a NegotiateProtocolVersion message would result in a
confusing error message like
expected authentication request from server, but received v
This adds proper handling of this protocol message and produces an
on-topic error message from it.
Reviewed-by: Jacob Champion <jchampion@timescale.com>
Reviewed-by: Nathan Bossart <nathandbossart@gmail.com>
Discussion: https://www.postgresql.org/message-id/flat/f9c7862f-b864-8ef7-a861-c4638c83e209%40enterprisedb.com
Diffstat (limited to 'src/interfaces/libpq/fe-protocol3.c')
-rw-r--r-- | src/interfaces/libpq/fe-protocol3.c | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/src/interfaces/libpq/fe-protocol3.c b/src/interfaces/libpq/fe-protocol3.c index 88dd360c905..364bad2b882 100644 --- a/src/interfaces/libpq/fe-protocol3.c +++ b/src/interfaces/libpq/fe-protocol3.c @@ -1386,6 +1386,61 @@ reportErrorPosition(PQExpBuffer msg, const char *query, int loc, int encoding) /* + * Attempt to read a NegotiateProtocolVersion message. + * Entry: 'v' message type and length have already been consumed. + * Exit: returns 0 if successfully consumed message. + * returns EOF if not enough data. + */ +int +pqGetNegotiateProtocolVersion3(PGconn *conn) +{ + int tmp; + ProtocolVersion their_version; + int num; + PQExpBufferData buf; + + if (pqGetInt(&tmp, 4, conn) != 0) + return EOF; + their_version = tmp; + + if (pqGetInt(&num, 4, conn) != 0) + return EOF; + + initPQExpBuffer(&buf); + for (int i = 0; i < num; i++) + { + if (pqGets(&conn->workBuffer, conn)) + { + termPQExpBuffer(&buf); + return EOF; + } + if (buf.len > 0) + appendPQExpBufferChar(&buf, ' '); + appendPQExpBufferStr(&buf, conn->workBuffer.data); + } + + if (their_version < conn->pversion) + appendPQExpBuffer(&conn->errorMessage, + libpq_gettext("protocol version not supported by server: client uses %u.%u, server supports up to %u.%u\n"), + PG_PROTOCOL_MAJOR(conn->pversion), PG_PROTOCOL_MINOR(conn->pversion), + PG_PROTOCOL_MAJOR(their_version), PG_PROTOCOL_MINOR(their_version)); + if (num > 0) + appendPQExpBuffer(&conn->errorMessage, + libpq_ngettext("protocol extension not supported by server: %s\n", + "protocol extensions not supported by server: %s\n", num), + buf.data); + + /* neither -- server shouldn't have sent it */ + if (!(their_version < conn->pversion) && !(num > 0)) + appendPQExpBuffer(&conn->errorMessage, + libpq_gettext("invalid %s message"), "NegotiateProtocolVersion"); + + termPQExpBuffer(&buf); + return 0; +} + + +/* * Attempt to read a ParameterStatus message. * This is possible in several places, so we break it out as a subroutine. * Entry: 'S' message type and length have already been consumed. |