Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit285613c

Browse files
committed
libpq: Add min/max_protocol_version connection options
All supported version of the PostgreSQL server send theNegotiateProtocolVersion message when an unsupported minor protocolversion is requested by a client. But many other applications thatimplement the PostgreSQL protocol (connection poolers, or otherdatabases) do not, and the same is true for PostgreSQL server versionsolder than 9.3. Connecting to such other applications thus fails if aclient requests a protocol version different than 3.0.This patch adds a max_protocol_version connection option to libpq thatspecifies the protocol version that libpq should request from theserver. Currently only 3.0 is supported, but that will change in afuture commit that bumps the protocol version. Even after that versionbump the default will likely stay 3.0 for the time being. Once more ofthe ecosystem supports the NegotiateProtocolVersion message we mightwant to change the default to the latest minor version.This also adds the similar min_protocol_version connection option, toallow the client to specify that connecting should fail if a lowerprotocol version is attempted by the server. This can be used toensure that certain protocol features are used, which can beparticularly useful if those features impact security.Author: Jelte Fennema-Nio <postgres@jeltef.nl>Reviewed-by: Robert Haas <robertmhaas@gmail.com> (earlier versions)Discussion:https://www.postgresql.org/message-id/CAGECzQTfc_O%2BHXqAo5_-xG4r3EFVsTefUeQzSvhEyyLDba-O9w@mail.gmail.comDiscussion:https://www.postgresql.org/message-id/CAGECzQRbAGqJnnJJxTdKewTsNOovUt4bsx3NFfofz3m2j-t7tA@mail.gmail.com
1 parent5070349 commit285613c

File tree

7 files changed

+315
-12
lines changed

7 files changed

+315
-12
lines changed

‎doc/src/sgml/libpq.sgml

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2144,6 +2144,54 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname
21442144
</listitem>
21452145
</varlistentry>
21462146

2147+
<varlistentry id="libpq-connect-min-protocol-version" xreflabel="min_protocol_version">
2148+
<term><literal>min_protocol_version</literal></term>
2149+
<listitem>
2150+
<para>
2151+
Specifies the minimum protocol version to allow for the connection.
2152+
The default is to allow any version of the
2153+
<productname>PostgreSQL</productname> protocol supported by libpq,
2154+
which currently means <literal>3.0</literal>. If the server
2155+
does not support at least this protocol version the connection will be
2156+
closed.
2157+
</para>
2158+
2159+
<para>
2160+
The current supported values are
2161+
<literal>3.0</literal>, <literal>3.2</literal>,
2162+
and <literal>latest</literal>. The <literal>latest</literal> value is
2163+
equivalent to the latest protocol version supported by the libpq
2164+
version being used, which is currently <literal>3.2</literal>.
2165+
</para>
2166+
</listitem>
2167+
</varlistentry>
2168+
2169+
<varlistentry id="libpq-connect-max-protocol-version" xreflabel="max_protocol_version">
2170+
<term><literal>max_protocol_version</literal></term>
2171+
<listitem>
2172+
<para>
2173+
Specifies the protocol version to request from the server.
2174+
The default is to use version <literal>3.0</literal> of the
2175+
<productname>PostgreSQL</productname> protocol, unless the connection
2176+
string specifies a feature that relies on a higher protocol version,
2177+
in which case the latest version supported by libpq is used. If the
2178+
server does not support the protocol version requested by the client,
2179+
the connection is automatically downgraded to a lower minor protocol
2180+
version that the server supports. After the connection attempt has
2181+
completed you can use <xref linkend="libpq-PQprotocolVersion"/> to
2182+
find out which exact protocol version was negotiated.
2183+
</para>
2184+
2185+
<para>
2186+
The current supported values are
2187+
<literal>3.0</literal>, <literal>3.2</literal>,
2188+
and <literal>latest</literal>. The <literal>latest</literal> value is
2189+
equivalent to the latest protocol version supported by the libpq
2190+
version being used, which is currently <literal>3.2</literal>.
2191+
</para>
2192+
</listitem>
2193+
</varlistentry>
2194+
21472195
<varlistentry id="libpq-connect-ssl-max-protocol-version" xreflabel="ssl_max_protocol_version">
21482196
<term><literal>ssl_max_protocol_version</literal></term>
21492197
<listitem>
@@ -9329,6 +9377,26 @@ myEventProc(PGEventId evtId, void *evtInfo, void *passThrough)
93299377
linkend="libpq-connect-load-balance-hosts"/> connection parameter.
93309378
</para>
93319379
</listitem>
9380+
9381+
<listitem>
9382+
<para>
9383+
<indexterm>
9384+
<primary><envar>PGMINPROTOCOLVERSION</envar></primary>
9385+
</indexterm>
9386+
<envar>PGMINPROTOCOLVERSION</envar> behaves the same as the <xref
9387+
linkend="libpq-connect-min-protocol-version"/> connection parameter.
9388+
</para>
9389+
</listitem>
9390+
9391+
<listitem>
9392+
<para>
9393+
<indexterm>
9394+
<primary><envar>PGMAXPROTOCOLVERSION</envar></primary>
9395+
</indexterm>
9396+
<envar>PGMAXPROTOCOLVERSION</envar> behaves the same as the <xref
9397+
linkend="libpq-connect-max-protocol-version"/> connection parameter.
9398+
</para>
9399+
</listitem>
93329400
</itemizedlist>
93339401
</para>
93349402

‎doc/src/sgml/protocol.sgml

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,24 +18,37 @@
1818
</para>
1919

2020
<para>
21-
This document describes version 3.0 of the protocol, implemented in
22-
<productname>PostgreSQL</productname> 7.4 and later. For descriptions
23-
of the earlier protocol versions, see previous releases of the
24-
<productname>PostgreSQL</productname> documentation. A single server
21+
This document describes version 3.2 of the protocol, introduced in
22+
<productname>PostgreSQL</productname> version 18. The server and the libpq
23+
client library are backwards compatible with protocol version 3.0,
24+
implemented in <productname>PostgreSQL</productname> 7.4 and later.
25+
For descriptions of earlier protocol versions, see previous releases of the
26+
<productname>PostgreSQL</productname> documentation.
27+
</para>
28+
29+
<para>
30+
A single server
2531
can support multiple protocol versions. The initial startup-request
2632
message tells the server which protocol version the client is attempting to
2733
use. If the major version requested by the client is not supported by
2834
the server, the connection will be rejected (for example, this would occur
2935
if the client requested protocol version 4.0, which does not exist as of
3036
this writing). If the minor version requested by the client is not
31-
supported by the server (e.g., the client requests version 3.1, but the
37+
supported by the server (e.g., the client requests version 3.2, but the
3238
server supports only 3.0), the server may either reject the connection or
3339
may respond with a NegotiateProtocolVersion message containing the highest
3440
minor protocol version which it supports. The client may then choose either
3541
to continue with the connection using the specified protocol version or
3642
to abort the connection.
3743
</para>
3844

45+
<para>
46+
The protocol negotiation was introduced in
47+
<productname>PostgreSQL</productname> version 9.3.21. Earlier versions would
48+
reject the connection if the client requested a minor version that was not
49+
supported by the server.
50+
</para>
51+
3952
<para>
4053
In order to serve multiple clients efficiently, the server launches
4154
a new <quote>backend</quote> process for each client.
@@ -413,8 +426,14 @@
413426
this message indicates the highest supported minor version. This
414427
message will also be sent if the client requested unsupported protocol
415428
options (i.e., beginning with <literal>_pq_.</literal>) in the
416-
startup packet. This message will be followed by an ErrorResponse or
417-
a message indicating the success or failure of authentication.
429+
startup packet.
430+
</para>
431+
<para>
432+
After this message, the authentication will continue using the version
433+
indicated by the server. If the client does not support the older
434+
version, it should immediately close the connection. If the server
435+
does not send this message, it supports the client's requested
436+
protocol version and all the protocol options.
418437
</para>
419438
</listitem>
420439
</varlistentry>

‎src/include/libpq/pqcomm.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,11 +91,10 @@ is_unixsock_path(const char *path)
9191

9292
/*
9393
* The earliest and latest frontend/backend protocol version supported.
94-
* (Only protocol version 3 is currently supported)
9594
*/
9695

9796
#definePG_PROTOCOL_EARLIESTPG_PROTOCOL(3,0)
98-
#definePG_PROTOCOL_LATESTPG_PROTOCOL(3,0)
97+
#definePG_PROTOCOL_LATESTPG_PROTOCOL(3,2)
9998

10099
typedefuint32ProtocolVersion;/* FE/BE protocol version number */
101100

‎src/interfaces/libpq/fe-connect.c

Lines changed: 87 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,16 @@ static const internalPQconninfoOption PQconninfoOptions[] = {
325325
"Require-Auth","",14,/* sizeof("scram-sha-256") == 14 */
326326
offsetof(structpg_conn,require_auth)},
327327

328+
{"min_protocol_version","PGMINPROTOCOLVERSION",
329+
NULL,NULL,
330+
"Min-Protocol-Version","",6,/* sizeof("latest") = 6 */
331+
offsetof(structpg_conn,min_protocol_version)},
332+
333+
{"max_protocol_version","PGMAXPROTOCOLVERSION",
334+
NULL,NULL,
335+
"Max-Protocol-Version","",6,/* sizeof("latest") = 6 */
336+
offsetof(structpg_conn,max_protocol_version)},
337+
328338
{"ssl_min_protocol_version","PGSSLMINPROTOCOLVERSION","TLSv1.2",NULL,
329339
"SSL-Minimum-Protocol-Version","",8,/* sizeof("TLSv1.x") == 8 */
330340
offsetof(structpg_conn,ssl_min_protocol_version)},
@@ -483,6 +493,7 @@ static void pgpassfileWarning(PGconn *conn);
483493
staticvoiddefault_threadlock(intacquire);
484494
staticboolsslVerifyProtocolVersion(constchar*version);
485495
staticboolsslVerifyProtocolRange(constchar*min,constchar*max);
496+
staticboolpqParseProtocolVersion(constchar*value,ProtocolVersion*result,PGconn*conn,constchar*context);
486497

487498

488499
/* global variable because fe-auth.c needs to access it */
@@ -2081,6 +2092,48 @@ pqConnectOptions2(PGconn *conn)
20812092
}
20822093
}
20832094

2095+
if (conn->min_protocol_version)
2096+
{
2097+
if (!pqParseProtocolVersion(conn->min_protocol_version,&conn->min_pversion,conn,"min_protocol_version"))
2098+
{
2099+
conn->status=CONNECTION_BAD;
2100+
return false;
2101+
}
2102+
}
2103+
else
2104+
{
2105+
conn->min_pversion=PG_PROTOCOL_EARLIEST;
2106+
}
2107+
2108+
if (conn->max_protocol_version)
2109+
{
2110+
if (!pqParseProtocolVersion(conn->max_protocol_version,&conn->max_pversion,conn,"max_protocol_version"))
2111+
{
2112+
conn->status=CONNECTION_BAD;
2113+
return false;
2114+
}
2115+
}
2116+
else
2117+
{
2118+
/*
2119+
* To not break connecting to older servers/poolers that do not yet
2120+
* support NegotiateProtocolVersion, default to the 3.0 protocol at
2121+
* least for a while longer. Except when min_protocol_version is set
2122+
* to something larger, then we might as well default to the latest.
2123+
*/
2124+
if (conn->min_pversion>PG_PROTOCOL(3,0))
2125+
conn->max_pversion=PG_PROTOCOL_LATEST;
2126+
else
2127+
conn->max_pversion=PG_PROTOCOL(3,0);
2128+
}
2129+
2130+
if (conn->min_pversion>conn->max_pversion)
2131+
{
2132+
conn->status=CONNECTION_BAD;
2133+
libpq_append_conn_error(conn,"min_protocol_version is greater than max_protocol_version");
2134+
return false;
2135+
}
2136+
20842137
/*
20852138
* Resolve special "auto" client_encoding from the locale
20862139
*/
@@ -3084,7 +3137,7 @@ PQconnectPoll(PGconn *conn)
30843137
* must persist across individual connection attempts, but we must
30853138
* reset them when we start to consider a new server.
30863139
*/
3087-
conn->pversion=PG_PROTOCOL(3,0);
3140+
conn->pversion=conn->max_pversion;
30883141
conn->send_appname= true;
30893142
conn->failed_enc_methods=0;
30903143
conn->current_enc_method=0;
@@ -4102,6 +4155,7 @@ PQconnectPoll(PGconn *conn)
41024155

41034156
/* OK, we read the message; mark data consumed */
41044157
pqParseDone(conn,conn->inCursor);
4158+
41054159
gotokeep_going;
41064160
}
41074161

@@ -8157,6 +8211,38 @@ pqParseIntParam(const char *value, int *result, PGconn *conn,
81578211
return false;
81588212
}
81598213

8214+
/*
8215+
* Parse and try to interpret "value" as a ProtocolVersion value, and if
8216+
* successful, store it in *result.
8217+
*/
8218+
staticbool
8219+
pqParseProtocolVersion(constchar*value,ProtocolVersion*result,PGconn*conn,
8220+
constchar*context)
8221+
{
8222+
if (strcmp(value,"latest")==0)
8223+
{
8224+
*result=PG_PROTOCOL_LATEST;
8225+
return true;
8226+
}
8227+
if (strcmp(value,"3.0")==0)
8228+
{
8229+
*result=PG_PROTOCOL(3,0);
8230+
return true;
8231+
}
8232+
8233+
/* 3.1 never existed, we went straight from 3.0 to 3.2 */
8234+
8235+
if (strcmp(value,"3.2")==0)
8236+
{
8237+
*result=PG_PROTOCOL(3,2);
8238+
return true;
8239+
}
8240+
8241+
libpq_append_conn_error(conn,"invalid %s value: \"%s\"",
8242+
context,value);
8243+
return false;
8244+
}
8245+
81608246
/*
81618247
* To keep the API consistent, the locking stubs are always provided, even
81628248
* if they are not required.

‎src/interfaces/libpq/fe-protocol3.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1432,6 +1432,13 @@ pqGetNegotiateProtocolVersion3(PGconn *conn)
14321432
gotofailure;
14331433
}
14341434

1435+
/* 3.1 never existed, we went straight from 3.0 to 3.2 */
1436+
if (their_version==PG_PROTOCOL(3,1))
1437+
{
1438+
libpq_append_conn_error(conn,"received invalid protocol negotiation message: server requests downgrade to non-existent 3.1 protocol version");
1439+
gotofailure;
1440+
}
1441+
14351442
if (num<0)
14361443
{
14371444
libpq_append_conn_error(conn,"received invalid protocol negotiation message: server reported negative number of unsupported parameters");
@@ -1444,6 +1451,17 @@ pqGetNegotiateProtocolVersion3(PGconn *conn)
14441451
gotofailure;
14451452
}
14461453

1454+
if (their_version<conn->min_pversion)
1455+
{
1456+
libpq_append_conn_error(conn,"server only supports protocol version %d.%d, but min_protocol_version was set to %d.%d",
1457+
PG_PROTOCOL_MAJOR(their_version),
1458+
PG_PROTOCOL_MINOR(their_version),
1459+
PG_PROTOCOL_MAJOR(conn->min_pversion),
1460+
PG_PROTOCOL_MINOR(conn->min_pversion));
1461+
1462+
gotofailure;
1463+
}
1464+
14471465
/* the version is acceptable */
14481466
conn->pversion=their_version;
14491467

‎src/interfaces/libpq/libpq-int.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,8 @@ struct pg_conn
417417
char*gsslib;/* What GSS library to use ("gssapi" or
418418
* "sspi") */
419419
char*gssdelegation;/* Try to delegate GSS credentials? (0 or 1) */
420+
char*min_protocol_version;/* minimum used protocol version */
421+
char*max_protocol_version;/* maximum used protocol version */
420422
char*ssl_min_protocol_version;/* minimum TLS protocol version */
421423
char*ssl_max_protocol_version;/* maximum TLS protocol version */
422424
char*target_session_attrs;/* desired session properties */
@@ -539,6 +541,8 @@ struct pg_conn
539541
void*scram_client_key_binary;/* binary SCRAM client key */
540542
size_tscram_server_key_len;
541543
void*scram_server_key_binary;/* binary SCRAM server key */
544+
ProtocolVersionmin_pversion;/* protocol version to request */
545+
ProtocolVersionmax_pversion;/* protocol version to request */
542546

543547
/* Miscellaneous stuff */
544548
intbe_pid;/* PID of backend --- needed for cancels */

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp