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

Commit5070349

Browse files
committed
libpq: Handle NegotiateProtocolVersion message differently
Previously libpq would always error out if the server sends aNegotiateProtocolVersion message. This was fine because libpq onlysupported a single protocol version and did not support any protocolparameters. But in the upcoming commits, we will introduce a newprotocol version and the NegotiateProtocolVersion message starts toactually be used.This patch modifies the client side checks to allow a range ofsupported protocol versions, instead of only allowing the exactversion that was requested. Currently this "range" only contains the3.0 version, but in a future commit we'll change this.Also clarify the error messages, making them suitable for the worldwhere libpq will support multiple protocol versions and protocolextensions.Note that until the later commits that introduce new protocol version,this change does not have any behavioural effect, because libpq willonly request version 3.0 and will never send protocol parameters, andtherefore will never receive a NegotiateProtocolVersion message fromthe server.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 parent748e98d commit5070349

File tree

3 files changed

+71
-35
lines changed

3 files changed

+71
-35
lines changed

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

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -667,6 +667,7 @@ pqDropServerData(PGconn *conn)
667667

668668
/* Reset assorted other per-connection state */
669669
conn->last_sqlstate[0]='\0';
670+
conn->pversion_negotiated= false;
670671
conn->auth_req_received= false;
671672
conn->client_finished_auth= false;
672673
conn->password_needed= false;
@@ -4084,16 +4085,24 @@ PQconnectPoll(PGconn *conn)
40844085

40854086
CONNECTION_FAILED();
40864087
}
4088+
/* Handle NegotiateProtocolVersion */
40874089
elseif (beresp==PqMsg_NegotiateProtocolVersion)
40884090
{
4091+
if (conn->pversion_negotiated)
4092+
{
4093+
libpq_append_conn_error(conn,"received duplicate protocol negotiation message");
4094+
gotoerror_return;
4095+
}
40894096
if (pqGetNegotiateProtocolVersion3(conn))
40904097
{
4091-
libpq_append_conn_error(conn,"received invalid protocol negotiation message");
4098+
/* pqGetNegotiateProtocolVersion3 set error already */
40924099
gotoerror_return;
40934100
}
4101+
conn->pversion_negotiated= true;
4102+
40944103
/* OK, we read the message; mark data consumed */
40954104
pqParseDone(conn,conn->inCursor);
4096-
gotoerror_return;
4105+
gotokeep_going;
40974106
}
40984107

40994108
/* It is an authentication request. */

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

Lines changed: 58 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -870,6 +870,7 @@ getAnotherTuple(PGconn *conn, int msgLength)
870870
/*
871871
* Attempt to read an Error or Notice response message.
872872
* This is possible in several places, so we break it out as a subroutine.
873+
*
873874
* Entry: 'E' or 'N' message type and length have already been consumed.
874875
* Exit: returns 0 if successfully consumed message.
875876
* returns EOF if not enough data.
@@ -1399,64 +1400,87 @@ reportErrorPosition(PQExpBuffer msg, const char *query, int loc, int encoding)
13991400

14001401

14011402
/*
1402-
* Attempt to read a NegotiateProtocolVersion message.
1403+
* Attempt to read a NegotiateProtocolVersion message. Sets conn->pversion
1404+
* to the version that's negotiated by the server.
1405+
*
14031406
* Entry: 'v' message type and length have already been consumed.
14041407
* Exit: returns 0 if successfully consumed message.
1405-
* returnsEOF if not enough data.
1408+
* returns1 on failure. The error message is filled in.
14061409
*/
14071410
int
14081411
pqGetNegotiateProtocolVersion3(PGconn*conn)
14091412
{
1410-
inttmp;
1411-
ProtocolVersiontheir_version;
1413+
inttheir_version;
14121414
intnum;
1413-
PQExpBufferDatabuf;
14141415

1415-
if (pqGetInt(&tmp,4,conn)!=0)
1416-
returnEOF;
1417-
their_version=tmp;
1416+
if (pqGetInt(&their_version,4,conn)!=0)
1417+
gotoeof;
14181418

14191419
if (pqGetInt(&num,4,conn)!=0)
1420-
returnEOF;
1420+
gotoeof;
14211421

1422-
initPQExpBuffer(&buf);
1423-
for (inti=0;i<num;i++)
1422+
/* Check the protocol version */
1423+
if (their_version>conn->pversion)
14241424
{
1425-
if (pqGets(&conn->workBuffer,conn))
1426-
{
1427-
termPQExpBuffer(&buf);
1428-
returnEOF;
1429-
}
1430-
if (buf.len>0)
1431-
appendPQExpBufferChar(&buf,' ');
1432-
appendPQExpBufferStr(&buf,conn->workBuffer.data);
1425+
libpq_append_conn_error(conn,"received invalid protocol negotiation message: server requested downgrade to a higher-numbered version");
1426+
gotofailure;
1427+
}
1428+
1429+
if (their_version<PG_PROTOCOL(3,0))
1430+
{
1431+
libpq_append_conn_error(conn,"received invalid protocol negotiation message: server requested downgrade to pre-3.0 protocol version");
1432+
gotofailure;
14331433
}
14341434

1435-
if (their_version<conn->pversion)
1436-
libpq_append_conn_error(conn,"protocol version not supported by server: client uses %u.%u, server supports up to %u.%u",
1437-
PG_PROTOCOL_MAJOR(conn->pversion),PG_PROTOCOL_MINOR(conn->pversion),
1438-
PG_PROTOCOL_MAJOR(their_version),PG_PROTOCOL_MINOR(their_version));
1439-
if (num>0)
1435+
if (num<0)
14401436
{
1441-
appendPQExpBuffer(&conn->errorMessage,
1442-
libpq_ngettext("protocol extension not supported by server: %s",
1443-
"protocol extensions not supported by server: %s",num),
1444-
buf.data);
1445-
appendPQExpBufferChar(&conn->errorMessage,'\n');
1437+
libpq_append_conn_error(conn,"received invalid protocol negotiation message: server reported negative number of unsupported parameters");
1438+
gotofailure;
1439+
}
1440+
1441+
if (their_version==conn->pversion&&num==0)
1442+
{
1443+
libpq_append_conn_error(conn,"received invalid protocol negotiation message: server negotiated but asks for no changes");
1444+
gotofailure;
14461445
}
14471446

1448-
/* neither -- server shouldn't have sent it */
1449-
if (!(their_version<conn->pversion)&& !(num>0))
1450-
libpq_append_conn_error(conn,"invalid %s message","NegotiateProtocolVersion");
1447+
/* the version is acceptable */
1448+
conn->pversion=their_version;
1449+
1450+
/*
1451+
* We don't currently request any protocol extensions, so we don't expect
1452+
* the server to reply with any either.
1453+
*/
1454+
for (inti=0;i<num;i++)
1455+
{
1456+
if (pqGets(&conn->workBuffer,conn))
1457+
{
1458+
gotoeof;
1459+
}
1460+
if (strncmp(conn->workBuffer.data,"_pq_.",5)!=0)
1461+
{
1462+
libpq_append_conn_error(conn,"received invalid protocol negotiation message: server reported unsupported parameter name without a _pq_. prefix (\"%s\")",conn->workBuffer.data);
1463+
gotofailure;
1464+
}
1465+
libpq_append_conn_error(conn,"received invalid protocol negotiation message: server reported an unsupported parameter that was not requested (\"%s\")",conn->workBuffer.data);
1466+
gotofailure;
1467+
}
14511468

1452-
termPQExpBuffer(&buf);
14531469
return0;
1470+
1471+
eof:
1472+
libpq_append_conn_error(conn,"received invalid protocol negotation message: message too short");
1473+
failure:
1474+
conn->asyncStatus=PGASYNC_READY;
1475+
pqSaveErrorResult(conn);
1476+
return1;
14541477
}
14551478

14561479

14571480
/*
14581481
* Attempt to read a ParameterStatus message.
14591482
* This is possible in several places, so we break it out as a subroutine.
1483+
*
14601484
* Entry: 'S' message type and length have already been consumed.
14611485
* Exit: returns 0 if successfully consumed message.
14621486
* returns EOF if not enough data.
@@ -1486,6 +1510,7 @@ getParameterStatus(PGconn *conn)
14861510
/*
14871511
* Attempt to read a Notify response message.
14881512
* This is possible in several places, so we break it out as a subroutine.
1513+
*
14891514
* Entry: 'A' message type and length have already been consumed.
14901515
* Exit: returns 0 if successfully consumed Notify message.
14911516
* returns EOF if not enough data.

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,8 @@ struct pg_conn
496496
SockAddrraddr;/* Remote address */
497497
ProtocolVersionpversion;/* FE/BE protocol version in use */
498498
intsversion;/* server version, e.g. 70401 for 7.4.1 */
499+
boolpversion_negotiated;/* true if NegotiateProtocolVersion
500+
* was received */
499501
boolauth_req_received;/* true if any type of auth req received */
500502
boolpassword_needed;/* true if server demanded a password */
501503
boolgssapi_used;/* true if authenticated via gssapi */

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp