Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit b68a560

Browse files
committed
Fix GSS client to non-GSS server connection
If the client is compiled with GSSAPI support and tries to start up GSS with the server, but the server is not compiled with GSSAPI support, we would mistakenly end up falling through to call ProcessStartupPacket with secure_done = true, but the client might then try to perform SSL, which the backend wouldn't understand and we'd end up failing the connection with: FATAL: unsupported frontend protocol 1234.5679: server supports 2.0 to 3.0 Fix by arranging to track ssl_done independently from gss_done, instead of trying to use the same boolean for both. Author: Andrew Gierth Discussion: https://postgr.es/m/87h82kzwqn.fsf@news-spur.riddles.org.uk Backpatch: 12-, where GSSAPI encryption was added.
1 parent d5d0969 commit b68a560

File tree

1 file changed

+24
-13
lines changed

1 file changed

+24
-13
lines changed

src/backend/postmaster/postmaster.c

+24-13
Original file line numberDiff line numberDiff line change
@@ -404,7 +404,7 @@ static void BackendRun(Port *port) pg_attribute_noreturn();
404404
static void ExitPostmaster(int status) pg_attribute_noreturn();
405405
static int ServerLoop(void);
406406
static int BackendStartup(Port *port);
407-
static int ProcessStartupPacket(Port *port, bool secure_done);
407+
static int ProcessStartupPacket(Port *port, bool ssl_done, bool gss_done);
408408
static void SendNegotiateProtocolVersion(List *unrecognized_protocol_options);
409409
static void processCancelRequest(Port *port, void *pkt);
410410
static int initMasks(fd_set *rmask);
@@ -1914,11 +1914,15 @@ initMasks(fd_set *rmask)
19141914
* send anything to the client, which would typically be appropriate
19151915
* if we detect a communications failure.)
19161916
*
1917-
* Set secure_done when negotiation of an encrypted layer (currently, TLS or
1918-
* GSSAPI) is already completed.
1917+
* Set ssl_done and/or gss_done when negotiation of an encrypted layer
1918+
* (currently, TLS or GSSAPI) is completed. A successful negotiation of either
1919+
* encryption layer sets both flags, but a rejected negotiation sets only the
1920+
* flag for that layer, since the client may wish to try the other one. We
1921+
* should make no assumption here about the order in which the client may make
1922+
* requests.
19191923
*/
19201924
static int
1921-
ProcessStartupPacket(Port *port, bool secure_done)
1925+
ProcessStartupPacket(Port *port, bool ssl_done, bool gss_done)
19221926
{
19231927
int32 len;
19241928
void *buf;
@@ -1951,7 +1955,7 @@ ProcessStartupPacket(Port *port, bool secure_done)
19511955
if (pq_getbytes(((char *) &len) + 1, 3) == EOF)
19521956
{
19531957
/* Got a partial length word, so bleat about that */
1954-
if (!secure_done)
1958+
if (!ssl_done && !gss_done)
19551959
ereport(COMMERROR,
19561960
(errcode(ERRCODE_PROTOCOL_VIOLATION),
19571961
errmsg("incomplete startup packet")));
@@ -2003,7 +2007,7 @@ ProcessStartupPacket(Port *port, bool secure_done)
20032007
return STATUS_ERROR;
20042008
}
20052009

2006-
if (proto == NEGOTIATE_SSL_CODE && !secure_done)
2010+
if (proto == NEGOTIATE_SSL_CODE && !ssl_done)
20072011
{
20082012
char SSLok;
20092013

@@ -2032,11 +2036,14 @@ ProcessStartupPacket(Port *port, bool secure_done)
20322036
if (SSLok == 'S' && secure_open_server(port) == -1)
20332037
return STATUS_ERROR;
20342038
#endif
2035-
/* regular startup packet, cancel, etc packet should follow... */
2036-
/* but not another SSL negotiation request */
2037-
return ProcessStartupPacket(port, true);
2039+
/*
2040+
* regular startup packet, cancel, etc packet should follow, but not
2041+
* another SSL negotiation request, and a GSS request should only
2042+
* follow if SSL was rejected (client may negotiate in either order)
2043+
*/
2044+
return ProcessStartupPacket(port, true, SSLok == 'S');
20382045
}
2039-
else if (proto == NEGOTIATE_GSS_CODE && !secure_done)
2046+
else if (proto == NEGOTIATE_GSS_CODE && !gss_done)
20402047
{
20412048
char GSSok = 'N';
20422049
#ifdef ENABLE_GSS
@@ -2059,8 +2066,12 @@ ProcessStartupPacket(Port *port, bool secure_done)
20592066
if (GSSok == 'G' && secure_open_gssapi(port) == -1)
20602067
return STATUS_ERROR;
20612068
#endif
2062-
/* Won't ever see more than one negotiation request */
2063-
return ProcessStartupPacket(port, true);
2069+
/*
2070+
* regular startup packet, cancel, etc packet should follow, but not
2071+
* another GSS negotiation request, and an SSL request should only
2072+
* follow if GSS was rejected (client may negotiate in either order)
2073+
*/
2074+
return ProcessStartupPacket(port, GSSok == 'G', true);
20642075
}
20652076

20662077
/* Could add additional special packet types here */
@@ -4412,7 +4423,7 @@ BackendInitialize(Port *port)
44124423
* Receive the startup packet (which might turn out to be a cancel request
44134424
* packet).
44144425
*/
4415-
status = ProcessStartupPacket(port, false);
4426+
status = ProcessStartupPacket(port, false, false);
44164427

44174428
/*
44184429
* Stop here if it was bad or a cancel packet. ProcessStartupPacket

0 commit comments

Comments
 (0)