1
0
mirror of https://github.com/postgres/postgres.git synced 2026-10-23 13:29:09 +03:00

libpq: Stop greasing protocol connections

This reverts commit 4966bd3ed9, which
introduced the 19beta grease campaign, now that Beta 3 has been stamped.
(The reservation and documentation for the grease version code, done in
d8d7c5dc8f, remains.)

Discussion: https://postgr.es/m/CAOYmi%2Bkqt_gn-wvUjJG1j3MM4LDDsRMURSPz2eMxfABu0iGtpw%40mail.gmail.com
Backpatch-through: 19
This commit is contained in:
Jacob Champion
2026-09-01 10:25:39 -07:00
parent e502f9aa81
commit 408a28c49a
7 changed files with 16 additions and 141 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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
@@ -2150,13 +2149,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)
@@ -4162,32 +4163,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 */
@@ -4418,14 +4393,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;

View File

@@ -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");
}

View File

@@ -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++)
{

View File

@@ -965,7 +965,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

View File

@@ -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);