mirror of
https://github.com/postgres/postgres.git
synced 2026-10-23 13:29:09 +03:00
libpq: Stop greasing protocol connections
This reverts commit4966bd3ed9, which introduced the 19beta grease campaign, now that Beta 3 has been stamped. (The reservation and documentation for the grease version code, done ind8d7c5dc8f, remains.) Discussion: https://postgr.es/m/CAOYmi%2Bkqt_gn-wvUjJG1j3MM4LDDsRMURSPz2eMxfABu0iGtpw%40mail.gmail.com Backpatch-through: 19
This commit is contained in:
@@ -2211,23 +2211,6 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname
|
||||
<varlistentry id="libpq-connect-max-protocol-version" xreflabel="max_protocol_version">
|
||||
<term><literal>max_protocol_version</literal></term>
|
||||
<listitem>
|
||||
<note>
|
||||
<para>
|
||||
During the PostgreSQL 19 beta period, libpq connections that do not
|
||||
specify a <literal>max_protocol_version</literal> will "grease" the
|
||||
handshake by sending unsupported startup parameters, including version
|
||||
<literal>3.9999</literal>, in order to identify software that does not
|
||||
correctly negotiate the connection. This replaces the default behavior
|
||||
described below.
|
||||
</para>
|
||||
<para>
|
||||
If you know that a server doesn't properly implement protocol version
|
||||
negotiation, you can set <literal>max_protocol_version=3.0</literal> to
|
||||
revert to the standard behavior (preferably after notifying the server's
|
||||
maintainers that their software needs to be fixed).
|
||||
</para>
|
||||
</note>
|
||||
|
||||
<para>
|
||||
Specifies the protocol version to request from the server.
|
||||
The default is to use version <literal>3.0</literal> of the
|
||||
|
||||
@@ -198,17 +198,6 @@
|
||||
by default.
|
||||
</para>
|
||||
|
||||
<note>
|
||||
<para>
|
||||
During the PostgreSQL 19 beta period, libpq will instead default to
|
||||
requesting protocol version 3.9999, to test that servers and middleware
|
||||
properly implement protocol version negotiation. Servers that support
|
||||
negotiation will automatically downgrade to version 3.2 or 3.0. Users can
|
||||
bypass this beta-only behavior by explicitly setting
|
||||
<literal>max_protocol_version=3.0</literal> in their connection string.
|
||||
</para>
|
||||
</note>
|
||||
|
||||
<para>
|
||||
A single server can support multiple protocol versions. The initial
|
||||
startup-request message tells the server which protocol version the client
|
||||
|
||||
@@ -91,9 +91,8 @@ static int ldapServiceLookup(const char *purl, PQconninfoOption *options,
|
||||
|
||||
/* This is part of the protocol so just define it */
|
||||
#define ERRCODE_INVALID_PASSWORD "28P01"
|
||||
/* These too */
|
||||
/* This too */
|
||||
#define ERRCODE_CANNOT_CONNECT_NOW "57P03"
|
||||
#define ERRCODE_PROTOCOL_VIOLATION "08P01"
|
||||
|
||||
/*
|
||||
* Cope with the various platform-specific ways to spell TCP keepalive socket
|
||||
@@ -2147,13 +2146,15 @@ pqConnectOptions2(PGconn *conn)
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Default to PG_PROTOCOL_GREASE, which is larger than all real
|
||||
* versions, to test negotiation. The server should automatically
|
||||
* downgrade to a supported version.
|
||||
*
|
||||
* This behavior is for 19beta only. It will be reverted before RC1.
|
||||
* To not break connecting to older servers/poolers that do not yet
|
||||
* support NegotiateProtocolVersion, default to the 3.0 protocol at
|
||||
* least for a while longer. Except when min_protocol_version is set
|
||||
* to something larger, then we might as well default to the latest.
|
||||
*/
|
||||
conn->max_pversion = PG_PROTOCOL_GREASE;
|
||||
if (conn->min_pversion > PG_PROTOCOL(3, 0))
|
||||
conn->max_pversion = PG_PROTOCOL_LATEST;
|
||||
else
|
||||
conn->max_pversion = PG_PROTOCOL(3, 0);
|
||||
}
|
||||
|
||||
if (conn->min_pversion > conn->max_pversion)
|
||||
@@ -4159,32 +4160,6 @@ keep_going: /* We will come back to here until there is
|
||||
/* Check to see if we should mention pgpassfile */
|
||||
pgpassfileWarning(conn);
|
||||
|
||||
/*
|
||||
* ...and whether we should mention grease. If the error
|
||||
* message contains the PG_PROTOCOL_GREASE number (in
|
||||
* major.minor, decimal, or hex format) or a complaint
|
||||
* about a protocol violation before we've even started an
|
||||
* authentication exchange, it's probably caused by a
|
||||
* grease interaction.
|
||||
*/
|
||||
if (conn->max_pversion == PG_PROTOCOL_GREASE &&
|
||||
!conn->auth_req_received)
|
||||
{
|
||||
const char *sqlstate = PQresultErrorField(conn->result,
|
||||
PG_DIAG_SQLSTATE);
|
||||
|
||||
if ((sqlstate &&
|
||||
strcmp(sqlstate, ERRCODE_PROTOCOL_VIOLATION) == 0) ||
|
||||
(conn->errorMessage.len > 0 &&
|
||||
(strstr(conn->errorMessage.data, "3.9999") ||
|
||||
strstr(conn->errorMessage.data, "206607") ||
|
||||
strstr(conn->errorMessage.data, "3270F") ||
|
||||
strstr(conn->errorMessage.data, "3270f"))))
|
||||
{
|
||||
libpq_append_grease_info(conn);
|
||||
}
|
||||
}
|
||||
|
||||
CONNECTION_FAILED();
|
||||
}
|
||||
/* Handle NegotiateProtocolVersion */
|
||||
@@ -4415,14 +4390,6 @@ keep_going: /* We will come back to here until there is
|
||||
goto error_return;
|
||||
}
|
||||
|
||||
if (conn->max_pversion == PG_PROTOCOL_GREASE &&
|
||||
conn->pversion == PG_PROTOCOL_GREASE)
|
||||
{
|
||||
libpq_append_conn_error(conn, "server incorrectly accepted \"grease\" protocol version 3.9999 without negotiation");
|
||||
libpq_append_grease_info(conn);
|
||||
goto error_return;
|
||||
}
|
||||
|
||||
/* Almost there now ... */
|
||||
conn->status = CONNECTION_CHECK_TARGET;
|
||||
goto keep_going;
|
||||
|
||||
@@ -1567,21 +1567,3 @@ libpq_append_conn_error(PGconn *conn, const char *fmt, ...)
|
||||
|
||||
appendPQExpBufferChar(&conn->errorMessage, '\n');
|
||||
}
|
||||
|
||||
/*
|
||||
* For 19beta only, some protocol errors will have additional information
|
||||
* appended to help with the "grease" campaign.
|
||||
*/
|
||||
void
|
||||
libpq_append_grease_info(PGconn *conn)
|
||||
{
|
||||
/* translator: %s is a URL */
|
||||
libpq_append_conn_error(conn,
|
||||
"\tThis indicates a bug in either the server being contacted\n"
|
||||
"\tor a proxy handling the connection. Please consider\n"
|
||||
"\treporting this to the maintainers of that software.\n"
|
||||
"\tFor more information, including instructions on how to\n"
|
||||
"\twork around this issue for now, visit\n"
|
||||
"\t\t%s",
|
||||
"https://wiki.postgresql.org/wiki/Grease");
|
||||
}
|
||||
|
||||
@@ -1445,15 +1445,6 @@ pqGetNegotiateProtocolVersion3(PGconn *conn)
|
||||
{
|
||||
int their_version;
|
||||
int num;
|
||||
bool found_test_protocol_negotiation;
|
||||
bool expect_test_protocol_negotiation;
|
||||
|
||||
/*
|
||||
* During 19beta only, if protocol grease is in use, assume that it's the
|
||||
* cause of any invalid messages encountered below. We'll print extra
|
||||
* information for the end user in that case.
|
||||
*/
|
||||
bool need_grease_info = (conn->max_pversion == PG_PROTOCOL_GREASE);
|
||||
|
||||
if (pqGetInt(&their_version, 4, conn) != 0)
|
||||
goto eof;
|
||||
@@ -1514,7 +1505,6 @@ pqGetNegotiateProtocolVersion3(PGconn *conn)
|
||||
PG_PROTOCOL_MAJOR(conn->min_pversion),
|
||||
PG_PROTOCOL_MINOR(conn->min_pversion));
|
||||
|
||||
need_grease_info = false; /* this is valid server behavior */
|
||||
goto failure;
|
||||
}
|
||||
|
||||
@@ -1522,12 +1512,9 @@ pqGetNegotiateProtocolVersion3(PGconn *conn)
|
||||
conn->pversion = their_version;
|
||||
|
||||
/*
|
||||
* Check that all expected unsupported parameters are reported by the
|
||||
* server.
|
||||
* We don't currently request any protocol extensions, so we don't expect
|
||||
* the server to reply with any either.
|
||||
*/
|
||||
found_test_protocol_negotiation = false;
|
||||
expect_test_protocol_negotiation = (conn->max_pversion == PG_PROTOCOL_GREASE);
|
||||
|
||||
for (int i = 0; i < num; i++)
|
||||
{
|
||||
if (pqGets(&conn->workBuffer, conn))
|
||||
@@ -1539,30 +1526,8 @@ pqGetNegotiateProtocolVersion3(PGconn *conn)
|
||||
libpq_append_conn_error(conn, "received invalid protocol negotiation message: server reported unsupported parameter name without a \"%s\" prefix (\"%s\")", "_pq_.", conn->workBuffer.data);
|
||||
goto failure;
|
||||
}
|
||||
|
||||
/* Check if this is the expected test parameter */
|
||||
if (expect_test_protocol_negotiation &&
|
||||
strcmp(conn->workBuffer.data, "_pq_.test_protocol_negotiation") == 0)
|
||||
{
|
||||
found_test_protocol_negotiation = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
libpq_append_conn_error(conn, "received invalid protocol negotiation message: server reported an unsupported parameter that was not requested (\"%s\")",
|
||||
conn->workBuffer.data);
|
||||
goto failure;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If we requested protocol grease, the server must report
|
||||
* _pq_.test_protocol_negotiation as unsupported. This ensures
|
||||
* comprehensive NegotiateProtocolVersion implementation.
|
||||
*/
|
||||
if (expect_test_protocol_negotiation && !found_test_protocol_negotiation)
|
||||
{
|
||||
libpq_append_conn_error(conn, "server did not report the unsupported \"%s\" parameter in its protocol negotiation message",
|
||||
"_pq_.test_protocol_negotiation");
|
||||
libpq_append_conn_error(conn, "received invalid protocol negotiation message: server reported an unsupported parameter that was not requested (\"%s\")",
|
||||
conn->workBuffer.data);
|
||||
goto failure;
|
||||
}
|
||||
|
||||
@@ -1571,8 +1536,6 @@ pqGetNegotiateProtocolVersion3(PGconn *conn)
|
||||
eof:
|
||||
libpq_append_conn_error(conn, "received invalid protocol negotiation message: message too short");
|
||||
failure:
|
||||
if (need_grease_info)
|
||||
libpq_append_grease_info(conn);
|
||||
conn->asyncStatus = PGASYNC_READY;
|
||||
pqSaveErrorResult(conn);
|
||||
return 1;
|
||||
@@ -2540,14 +2503,6 @@ build_startup_packet(const PGconn *conn, char *packet,
|
||||
if (conn->client_encoding_initial && conn->client_encoding_initial[0])
|
||||
ADD_STARTUP_OPTION("client_encoding", conn->client_encoding_initial);
|
||||
|
||||
/*
|
||||
* Add the test_protocol_negotiation option when greasing, to test that
|
||||
* servers properly report unsupported protocol options in addition to
|
||||
* unsupported minor versions.
|
||||
*/
|
||||
if (conn->pversion == PG_PROTOCOL_GREASE)
|
||||
ADD_STARTUP_OPTION("_pq_.test_protocol_negotiation", "");
|
||||
|
||||
/* Add any environment-driven GUC settings needed */
|
||||
for (next_eo = options; next_eo->envName; next_eo++)
|
||||
{
|
||||
|
||||
@@ -968,7 +968,6 @@ extern char *libpq_ngettext(const char *msgid, const char *msgid_plural, unsigne
|
||||
|
||||
extern void libpq_append_error(PQExpBuffer errorMessage, const char *fmt, ...) pg_attribute_printf(2, 3);
|
||||
extern void libpq_append_conn_error(PGconn *conn, const char *fmt, ...) pg_attribute_printf(2, 3);
|
||||
extern void libpq_append_grease_info(PGconn *conn);
|
||||
|
||||
/*
|
||||
* These macros are needed to let error-handling code be portable between
|
||||
|
||||
@@ -1363,7 +1363,7 @@ test_protocol_version(PGconn *conn)
|
||||
Assert(max_protocol_version_index >= 0);
|
||||
|
||||
/*
|
||||
* Test default protocol_version (GREASE - should negotiate down to 3.2)
|
||||
* Test default protocol_version
|
||||
*/
|
||||
vals[max_protocol_version_index] = "";
|
||||
conn = PQconnectdbParams(keywords, vals, false);
|
||||
@@ -1373,8 +1373,8 @@ test_protocol_version(PGconn *conn)
|
||||
PQerrorMessage(conn));
|
||||
|
||||
protocol_version = PQfullProtocolVersion(conn);
|
||||
if (protocol_version != 30002)
|
||||
pg_fatal("expected 30002, got %d", protocol_version);
|
||||
if (protocol_version != 30000)
|
||||
pg_fatal("expected 30000, got %d", protocol_version);
|
||||
|
||||
PQfinish(conn);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user