@@ -404,7 +404,7 @@ static void BackendRun(Port *port) pg_attribute_noreturn();
404404static void ExitPostmaster (int status )pg_attribute_noreturn ();
405405static int ServerLoop (void );
406406static 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 );
408408static void SendNegotiateProtocolVersion (List * unrecognized_protocol_options );
409409static void processCancelRequest (Port * port ,void * pkt );
410410static int initMasks (fd_set * rmask );
@@ -1891,11 +1891,15 @@ initMasks(fd_set *rmask)
18911891 * send anything to the client, which would typically be appropriate
18921892 * if we detect a communications failure.)
18931893 *
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.
18961900 */
18971901static int
1898- ProcessStartupPacket (Port * port ,bool secure_done )
1902+ ProcessStartupPacket (Port * port ,bool ssl_done , bool gss_done )
18991903{
19001904int32 len ;
19011905void * buf ;
@@ -1928,7 +1932,7 @@ ProcessStartupPacket(Port *port, bool secure_done)
19281932if (pq_getbytes (((char * )& len )+ 1 ,3 )== EOF )
19291933{
19301934/* Got a partial length word, so bleat about that */
1931- if (!secure_done )
1935+ if (!ssl_done && ! gss_done )
19321936ereport (COMMERROR ,
19331937(errcode (ERRCODE_PROTOCOL_VIOLATION ),
19341938errmsg ("incomplete startup packet" )));
@@ -1980,7 +1984,7 @@ ProcessStartupPacket(Port *port, bool secure_done)
19801984return STATUS_ERROR ;
19811985}
19821986
1983- if (proto == NEGOTIATE_SSL_CODE && !secure_done )
1987+ if (proto == NEGOTIATE_SSL_CODE && !ssl_done )
19841988{
19851989char SSLok ;
19861990
@@ -2009,11 +2013,14 @@ ProcessStartupPacket(Port *port, bool secure_done)
20092013if (SSLok == 'S' && secure_open_server (port )== -1 )
20102014return STATUS_ERROR ;
20112015#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' );
20152022}
2016- else if (proto == NEGOTIATE_GSS_CODE && !secure_done )
2023+ else if (proto == NEGOTIATE_GSS_CODE && !gss_done )
20172024{
20182025char GSSok = 'N' ;
20192026#ifdef ENABLE_GSS
@@ -2036,8 +2043,12 @@ ProcessStartupPacket(Port *port, bool secure_done)
20362043if (GSSok == 'G' && secure_open_gssapi (port )== -1 )
20372044return STATUS_ERROR ;
20382045#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);
20412052}
20422053
20432054/* Could add additional special packet types here */
@@ -4339,7 +4350,7 @@ BackendInitialize(Port *port)
43394350 * Receive the startup packet (which might turn out to be a cancel request
43404351 * packet).
43414352 */
4342- status = ProcessStartupPacket (port , false);
4353+ status = ProcessStartupPacket (port , false, false );
43434354
43444355/*
43454356 * Stop here if it was bad or a cancel packet. ProcessStartupPacket