@@ -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 );
@@ -1891,11 +1891,15 @@ initMasks(fd_set *rmask)
1891
1891
* send anything to the client, which would typically be appropriate
1892
1892
* if we detect a communications failure.)
1893
1893
*
1894
- * Set secure_done when negotiation of an encrypted layer (currently, TLS or
1895
- * GSSAPI) is already completed.
1894
+ * Set ssl_done and/or gss_done when negotiation of an encrypted layer
1895
+ * (currently, TLS or GSSAPI) is completed. A successful negotiation of either
1896
+ * encryption layer sets both flags, but a rejected negotiation sets only the
1897
+ * flag for that layer, since the client may wish to try the other one. We
1898
+ * should make no assumption here about the order in which the client may make
1899
+ * requests.
1896
1900
*/
1897
1901
static int
1898
- ProcessStartupPacket (Port * port , bool secure_done )
1902
+ ProcessStartupPacket (Port * port , bool ssl_done , bool gss_done )
1899
1903
{
1900
1904
int32 len ;
1901
1905
void * buf ;
@@ -1928,7 +1932,7 @@ ProcessStartupPacket(Port *port, bool secure_done)
1928
1932
if (pq_getbytes (((char * ) & len ) + 1 , 3 ) == EOF )
1929
1933
{
1930
1934
/* Got a partial length word, so bleat about that */
1931
- if (!secure_done )
1935
+ if (!ssl_done && ! gss_done )
1932
1936
ereport (COMMERROR ,
1933
1937
(errcode (ERRCODE_PROTOCOL_VIOLATION ),
1934
1938
errmsg ("incomplete startup packet" )));
@@ -1980,7 +1984,7 @@ ProcessStartupPacket(Port *port, bool secure_done)
1980
1984
return STATUS_ERROR ;
1981
1985
}
1982
1986
1983
- if (proto == NEGOTIATE_SSL_CODE && !secure_done )
1987
+ if (proto == NEGOTIATE_SSL_CODE && !ssl_done )
1984
1988
{
1985
1989
char SSLok ;
1986
1990
@@ -2009,11 +2013,14 @@ ProcessStartupPacket(Port *port, bool secure_done)
2009
2013
if (SSLok == 'S' && secure_open_server (port ) == -1 )
2010
2014
return STATUS_ERROR ;
2011
2015
#endif
2012
- /* regular startup packet, cancel, etc packet should follow... */
2013
- /* but not another SSL negotiation request */
2014
- return ProcessStartupPacket (port , true);
2016
+ /*
2017
+ * regular startup packet, cancel, etc packet should follow, but not
2018
+ * another SSL negotiation request, and a GSS request should only
2019
+ * follow if SSL was rejected (client may negotiate in either order)
2020
+ */
2021
+ return ProcessStartupPacket (port , true, SSLok == 'S' );
2015
2022
}
2016
- else if (proto == NEGOTIATE_GSS_CODE && !secure_done )
2023
+ else if (proto == NEGOTIATE_GSS_CODE && !gss_done )
2017
2024
{
2018
2025
char GSSok = 'N' ;
2019
2026
#ifdef ENABLE_GSS
@@ -2036,8 +2043,12 @@ ProcessStartupPacket(Port *port, bool secure_done)
2036
2043
if (GSSok == 'G' && secure_open_gssapi (port ) == -1 )
2037
2044
return STATUS_ERROR ;
2038
2045
#endif
2039
- /* Won't ever see more than one negotiation request */
2040
- return ProcessStartupPacket (port , true);
2046
+ /*
2047
+ * regular startup packet, cancel, etc packet should follow, but not
2048
+ * another GSS negotiation request, and an SSL request should only
2049
+ * follow if GSS was rejected (client may negotiate in either order)
2050
+ */
2051
+ return ProcessStartupPacket (port , GSSok == 'G' , true);
2041
2052
}
2042
2053
2043
2054
/* Could add additional special packet types here */
@@ -4339,7 +4350,7 @@ BackendInitialize(Port *port)
4339
4350
* Receive the startup packet (which might turn out to be a cancel request
4340
4351
* packet).
4341
4352
*/
4342
- status = ProcessStartupPacket (port , false);
4353
+ status = ProcessStartupPacket (port , false, false );
4343
4354
4344
4355
/*
4345
4356
* Stop here if it was bad or a cancel packet. ProcessStartupPacket
0 commit comments