@@ -404,7 +404,7 @@ static void BackendRun(Port *port) pg_attribute_noreturn();
404
404
static void ExitPostmaster (int status ) pg_attribute_noreturn ();
405
405
static int ServerLoop (void );
406
406
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 );
408
408
static void SendNegotiateProtocolVersion (List * unrecognized_protocol_options );
409
409
static void processCancelRequest (Port * port , void * pkt );
410
410
static int initMasks (fd_set * rmask );
@@ -1914,11 +1914,15 @@ initMasks(fd_set *rmask)
1914
1914
* send anything to the client, which would typically be appropriate
1915
1915
* if we detect a communications failure.)
1916
1916
*
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.
1919
1923
*/
1920
1924
static int
1921
- ProcessStartupPacket (Port * port , bool secure_done )
1925
+ ProcessStartupPacket (Port * port , bool ssl_done , bool gss_done )
1922
1926
{
1923
1927
int32 len ;
1924
1928
void * buf ;
@@ -1951,7 +1955,7 @@ ProcessStartupPacket(Port *port, bool secure_done)
1951
1955
if (pq_getbytes (((char * ) & len ) + 1 , 3 ) == EOF )
1952
1956
{
1953
1957
/* Got a partial length word, so bleat about that */
1954
- if (!secure_done )
1958
+ if (!ssl_done && ! gss_done )
1955
1959
ereport (COMMERROR ,
1956
1960
(errcode (ERRCODE_PROTOCOL_VIOLATION ),
1957
1961
errmsg ("incomplete startup packet" )));
@@ -2003,7 +2007,7 @@ ProcessStartupPacket(Port *port, bool secure_done)
2003
2007
return STATUS_ERROR ;
2004
2008
}
2005
2009
2006
- if (proto == NEGOTIATE_SSL_CODE && !secure_done )
2010
+ if (proto == NEGOTIATE_SSL_CODE && !ssl_done )
2007
2011
{
2008
2012
char SSLok ;
2009
2013
@@ -2032,11 +2036,14 @@ ProcessStartupPacket(Port *port, bool secure_done)
2032
2036
if (SSLok == 'S' && secure_open_server (port ) == -1 )
2033
2037
return STATUS_ERROR ;
2034
2038
#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' );
2038
2045
}
2039
- else if (proto == NEGOTIATE_GSS_CODE && !secure_done )
2046
+ else if (proto == NEGOTIATE_GSS_CODE && !gss_done )
2040
2047
{
2041
2048
char GSSok = 'N' ;
2042
2049
#ifdef ENABLE_GSS
@@ -2059,8 +2066,12 @@ ProcessStartupPacket(Port *port, bool secure_done)
2059
2066
if (GSSok == 'G' && secure_open_gssapi (port ) == -1 )
2060
2067
return STATUS_ERROR ;
2061
2068
#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);
2064
2075
}
2065
2076
2066
2077
/* Could add additional special packet types here */
@@ -4412,7 +4423,7 @@ BackendInitialize(Port *port)
4412
4423
* Receive the startup packet (which might turn out to be a cancel request
4413
4424
* packet).
4414
4425
*/
4415
- status = ProcessStartupPacket (port , false);
4426
+ status = ProcessStartupPacket (port , false, false );
4416
4427
4417
4428
/*
4418
4429
* Stop here if it was bad or a cancel packet. ProcessStartupPacket
0 commit comments