1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-03 20:02:46 +03:00

Remove option to fall back from direct to postgres SSL negotiation

There were three problems with the sslnegotiation options:

1. The sslmode=prefer and sslnegotiation=requiredirect combination was
somewhat dangerous, as you might unintentionally fall back to
plaintext authentication when connecting to a pre-v17 server.

2. There was an asymmetry between 'postgres' and 'direct'
options. 'postgres' meant "try only traditional negotiation", while
'direct' meant "try direct first, and fall back to traditional
negotiation if it fails". That was apparent only if you knew that the
'requiredirect' mode also exists.

3. The "require" word in 'requiredirect' suggests that it's somehow
more strict or more secure, similar to sslmode. However, I don't
consider direct SSL connections to be a security feature.

To address these problems:

- Only allow sslnegotiation='direct' if sslmode='require' or
stronger. And for the record, Jacob and Robert felt that we should do
that (or have sslnegotiation='direct' imply sslmode='require') anyway,
regardless of the first issue.

- Remove the 'direct' mode that falls back to traditional negotiation,
and rename what was called 'requiredirect' to 'direct' instead. In
other words, there is no "try both methods" option anymore, 'postgres'
now means the traditional negotiation and 'direct' means a direct SSL
connection.

Reviewed-by: Jelte Fennema-Nio, Robert Haas, Jacob Champion
Discussion: https://www.postgresql.org/message-id/d3b1608a-a1b6-4eda-9ec5-ddb3e4375808%40iki.fi
This commit is contained in:
Heikki Linnakangas
2024-05-16 17:17:37 +03:00
parent 8ba3462833
commit fb5718f35f
5 changed files with 231 additions and 284 deletions

View File

@ -1773,15 +1773,18 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname
<term><literal>sslnegotiation</literal></term> <term><literal>sslnegotiation</literal></term>
<listitem> <listitem>
<para> <para>
This option controls whether <productname>PostgreSQL</productname> This option controls how SSL encryption is negotiated with the server,
will perform its protocol negotiation to request encryption from the if SSL is used. In the default <literal>postgres</literal> mode, the
server or will just directly make a standard <acronym>SSL</acronym> client first asks the server if SSL is supported. In
connection. Traditional <productname>PostgreSQL</productname> <literal>direct</literal> mode, the client starts the standard SSL
protocol negotiation is the default and the most flexible with handshake directly after establishing the TCP/IP connection. Traditional
different server configurations. If the server is known to support <productname>PostgreSQL</productname> protocol negotiation is the most
direct <acronym>SSL</acronym> connections then the latter requires one flexible with different server configurations. If the server is known
fewer round trip reducing connection latency and also allows the use to support direct <acronym>SSL</acronym> connections then the latter
of protocol agnostic SSL network tools. requires one fewer round trip reducing connection latency and also
allows the use of protocol agnostic SSL network tools. The direct SSL
option was introduced in <productname>PostgreSQL</productname> version
17.
</para> </para>
<variablelist> <variablelist>
@ -1799,32 +1802,14 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname
<term><literal>direct</literal></term> <term><literal>direct</literal></term>
<listitem> <listitem>
<para> <para>
first attempt to establish a standard SSL connection and if that start SSL handshake directly after establishing the TCP/IP
fails reconnect and perform the negotiation. This fallback connection. This is only allowed with sslmode=require or higher,
process adds significant latency if the initial SSL connection because the weaker settings could lead to unintended fallback to
fails. plaintext authentication when the server does not support direct
</para>
<para>
An exception is if <literal>gssencmode</literal> is set
to <literal>prefer</literal>, but the server rejects GSS encryption.
In that case, SSL is negotiated over the same TCP connection using
<productname>PostgreSQL</productname> protocol negotiation. In
other words, the direct SSL handshake is not used, if a TCP
connection has already been established and can be used for the
SSL handshake. SSL handshake.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><literal>requiredirect</literal></term>
<listitem>
<para>
attempt to establish a standard SSL connection and if that fails
return a connection failure immediately.
</para>
</listitem>
</varlistentry>
</variablelist> </variablelist>
</listitem> </listitem>
</varlistentry> </varlistentry>
@ -2065,7 +2050,7 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname
connections without having to decrypt the SSL stream. (Note that connections without having to decrypt the SSL stream. (Note that
unless the proxy is aware of the PostgreSQL protocol handshake this unless the proxy is aware of the PostgreSQL protocol handshake this
would require setting <literal>sslnegotiation</literal> would require setting <literal>sslnegotiation</literal>
to <literal>direct</literal> or <literal>requiredirect</literal>.) to <literal>direct</literal>.)
However, <acronym>SNI</acronym> makes the destination host name appear However, <acronym>SNI</acronym> makes the destination host name appear
in cleartext in the network traffic, so it might be undesirable in in cleartext in the network traffic, so it might be undesirable in
some cases. some cases.

View File

@ -274,7 +274,7 @@ static const internalPQconninfoOption PQconninfoOptions[] = {
offsetof(struct pg_conn, sslmode)}, offsetof(struct pg_conn, sslmode)},
{"sslnegotiation", "PGSSLNEGOTIATION", DefaultSSLNegotiation, NULL, {"sslnegotiation", "PGSSLNEGOTIATION", DefaultSSLNegotiation, NULL,
"SSL-Negotiation", "", 14, /* sizeof("requiredirect") == 14 */ "SSL-Negotiation", "", 9, /* sizeof("postgres") == 9 */
offsetof(struct pg_conn, sslnegotiation)}, offsetof(struct pg_conn, sslnegotiation)},
{"sslcompression", "PGSSLCOMPRESSION", "0", NULL, {"sslcompression", "PGSSLCOMPRESSION", "0", NULL,
@ -1590,8 +1590,7 @@ pqConnectOptions2(PGconn *conn)
if (conn->sslnegotiation) if (conn->sslnegotiation)
{ {
if (strcmp(conn->sslnegotiation, "postgres") != 0 if (strcmp(conn->sslnegotiation, "postgres") != 0
&& strcmp(conn->sslnegotiation, "direct") != 0 && strcmp(conn->sslnegotiation, "direct") != 0)
&& strcmp(conn->sslnegotiation, "requiredirect") != 0)
{ {
conn->status = CONNECTION_BAD; conn->status = CONNECTION_BAD;
libpq_append_conn_error(conn, "invalid %s value: \"%s\"", libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
@ -1608,6 +1607,25 @@ pqConnectOptions2(PGconn *conn)
return false; return false;
} }
#endif #endif
/*
* Don't allow direct SSL negotiation with sslmode='prefer', because
* that poses a risk of unintentional fallback to plaintext connection
* when connecting to a pre-v17 server that does not support direct
* SSL connections. To keep things simple, don't allow it with
* sslmode='allow' or sslmode='disable' either. If a user goes through
* the trouble of setting sslnegotiation='direct', they probably
* intend to use SSL, and sslmode=disable or allow is probably a user
* user mistake anyway.
*/
if (conn->sslnegotiation[0] == 'd' &&
conn->sslmode[0] != 'r' && conn->sslmode[0] != 'v')
{
conn->status = CONNECTION_BAD;
libpq_append_conn_error(conn, "weak sslmode \"%s\" may not be used with sslnegotiation=direct (use \"require\", \"verify-ca\", or \"verify-full\")",
conn->sslmode);
return false;
}
} }
else else
{ {
@ -3347,42 +3365,45 @@ keep_going: /* We will come back to here until there is
goto error_return; goto error_return;
/* /*
* If direct SSL is enabled, jump right into SSL handshake. We * If SSL is enabled, start the SSL negotiation. We will come
* will come back here after SSL encryption has been * back here after SSL encryption has been established, with
* established, with ssl_in_use set. * ssl_in_use set.
*/ */
if (conn->current_enc_method == ENC_DIRECT_SSL && !conn->ssl_in_use) if (conn->current_enc_method == ENC_SSL && !conn->ssl_in_use)
{ {
conn->status = CONNECTION_SSL_STARTUP;
return PGRES_POLLING_WRITING;
}
/*
* If negotiated SSL is enabled, request SSL and proceed with
* SSL handshake. We will come back here after SSL encryption
* has been established, with ssl_in_use set.
*/
if (conn->current_enc_method == ENC_NEGOTIATED_SSL && !conn->ssl_in_use)
{
ProtocolVersion pv;
/* /*
* Send the SSL request packet. * If traditional postgres SSL negotiation is used, send
* * the SSL request. In direct negotiation, jump straight
* Theoretically, this could block, but it really * into the SSL handshake.
* shouldn't since we only got here if the socket is
* write-ready.
*/ */
pv = pg_hton32(NEGOTIATE_SSL_CODE); if (conn->sslnegotiation[0] == 'p')
if (pqPacketSend(conn, 0, &pv, sizeof(pv)) != STATUS_OK)
{ {
libpq_append_conn_error(conn, "could not send SSL negotiation packet: %s", ProtocolVersion pv;
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
goto error_return; /*
* Send the SSL request packet.
*
* Theoretically, this could block, but it really
* shouldn't since we only got here if the socket is
* write-ready.
*/
pv = pg_hton32(NEGOTIATE_SSL_CODE);
if (pqPacketSend(conn, 0, &pv, sizeof(pv)) != STATUS_OK)
{
libpq_append_conn_error(conn, "could not send SSL negotiation packet: %s",
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
goto error_return;
}
/* Ok, wait for response */
conn->status = CONNECTION_SSL_STARTUP;
return PGRES_POLLING_READING;
}
else
{
Assert(conn->sslnegotiation[0] == 'd');
conn->status = CONNECTION_SSL_STARTUP;
return PGRES_POLLING_WRITING;
} }
/* Ok, wait for response */
conn->status = CONNECTION_SSL_STARTUP;
return PGRES_POLLING_READING;
} }
#endif /* USE_SSL */ #endif /* USE_SSL */
@ -3453,11 +3474,11 @@ keep_going: /* We will come back to here until there is
PostgresPollingStatusType pollres; PostgresPollingStatusType pollres;
/* /*
* On first time through, get the postmaster's response to our * On first time through with traditional SSL negotiation, get
* SSL negotiation packet. If we are trying a direct ssl * the postmaster's response to our SSLRequest packet. With
* connection, go straight to initiating ssl. * sslnegotiation='direct', go straight to initiating SSL.
*/ */
if (!conn->ssl_in_use && conn->current_enc_method == ENC_NEGOTIATED_SSL) if (!conn->ssl_in_use && conn->sslnegotiation[0] == 'p')
{ {
/* /*
* We use pqReadData here since it has the logic to * We use pqReadData here since it has the logic to
@ -4282,7 +4303,7 @@ init_allowed_encryption_methods(PGconn *conn)
if (conn->raddr.addr.ss_family == AF_UNIX) if (conn->raddr.addr.ss_family == AF_UNIX)
{ {
/* Don't request SSL or GSSAPI over Unix sockets */ /* Don't request SSL or GSSAPI over Unix sockets */
conn->allowed_enc_methods &= ~(ENC_DIRECT_SSL | ENC_NEGOTIATED_SSL | ENC_GSSAPI); conn->allowed_enc_methods &= ~(ENC_SSL | ENC_GSSAPI);
/* /*
* XXX: we probably should not do this. sslmode=require works * XXX: we probably should not do this. sslmode=require works
@ -4309,12 +4330,7 @@ init_allowed_encryption_methods(PGconn *conn)
/* sslmode anything but 'disable', and GSSAPI not required */ /* sslmode anything but 'disable', and GSSAPI not required */
if (conn->sslmode[0] != 'd' && conn->gssencmode[0] != 'r') if (conn->sslmode[0] != 'd' && conn->gssencmode[0] != 'r')
{ {
if (conn->sslnegotiation[0] == 'p') conn->allowed_enc_methods |= ENC_SSL;
conn->allowed_enc_methods |= ENC_NEGOTIATED_SSL;
else if (conn->sslnegotiation[0] == 'd')
conn->allowed_enc_methods |= ENC_DIRECT_SSL | ENC_NEGOTIATED_SSL;
else if (conn->sslnegotiation[0] == 'r')
conn->allowed_enc_methods |= ENC_DIRECT_SSL;
} }
#endif #endif
@ -4354,7 +4370,8 @@ encryption_negotiation_failed(PGconn *conn)
if (select_next_encryption_method(conn, true)) if (select_next_encryption_method(conn, true))
{ {
if (conn->current_enc_method == ENC_DIRECT_SSL) /* An existing connection cannot be reused for direct SSL */
if (conn->current_enc_method == ENC_SSL && conn->sslnegotiation[0] == 'd')
return 2; return 2;
else else
return 1; return 1;
@ -4376,18 +4393,6 @@ connection_failed(PGconn *conn)
Assert((conn->failed_enc_methods & conn->current_enc_method) == 0); Assert((conn->failed_enc_methods & conn->current_enc_method) == 0);
conn->failed_enc_methods |= conn->current_enc_method; conn->failed_enc_methods |= conn->current_enc_method;
/*
* If the server reported an error after the SSL handshake, no point in
* retrying with negotiated vs direct SSL.
*/
if ((conn->current_enc_method & (ENC_DIRECT_SSL | ENC_NEGOTIATED_SSL)) != 0 &&
conn->ssl_handshake_started)
{
conn->failed_enc_methods |= (ENC_DIRECT_SSL | ENC_NEGOTIATED_SSL) & conn->allowed_enc_methods;
}
else
conn->failed_enc_methods |= conn->current_enc_method;
return select_next_encryption_method(conn, false); return select_next_encryption_method(conn, false);
} }
@ -4445,24 +4450,17 @@ select_next_encryption_method(PGconn *conn, bool have_valid_connection)
SELECT_NEXT_METHOD(ENC_GSSAPI); SELECT_NEXT_METHOD(ENC_GSSAPI);
#endif #endif
/* With sslmode=allow, try plaintext connection before SSL. */ /*
* The order between SSL encryption and plaintext depends on sslmode. With
* sslmode=allow, try plaintext connection before SSL. With
* sslmode=prefer, it's the other way round. With other modes, we only try
* plaintext or SSL connections so the order they're listed here doesn't
* matter.
*/
if (conn->sslmode[0] == 'a') if (conn->sslmode[0] == 'a')
SELECT_NEXT_METHOD(ENC_PLAINTEXT); SELECT_NEXT_METHOD(ENC_PLAINTEXT);
/* SELECT_NEXT_METHOD(ENC_SSL);
* If enabled, try direct SSL. Unless we have a valid TCP connection that
* failed negotiating GSSAPI encryption; in that case we prefer to reuse
* the connection with negotiated SSL, instead of reconnecting to do
* direct SSL. The point of sslnegotiation=direct is to avoid the
* roundtrip from the negotiation, but reconnecting would also incur a
* roundtrip. (In sslnegotiation=requiredirect mode, negotiated SSL is not
* in the list of allowed methods and we will reconnect.)
*/
if (have_valid_connection)
SELECT_NEXT_METHOD(ENC_NEGOTIATED_SSL);
SELECT_NEXT_METHOD(ENC_DIRECT_SSL);
SELECT_NEXT_METHOD(ENC_NEGOTIATED_SSL);
if (conn->sslmode[0] != 'a') if (conn->sslmode[0] != 'a')
SELECT_NEXT_METHOD(ENC_PLAINTEXT); SELECT_NEXT_METHOD(ENC_PLAINTEXT);

View File

@ -1586,7 +1586,7 @@ open_client_SSL(PGconn *conn)
} }
/* ALPN is mandatory with direct SSL connections */ /* ALPN is mandatory with direct SSL connections */
if (conn->current_enc_method == ENC_DIRECT_SSL) if (conn->current_enc_method == ENC_SSL && conn->sslnegotiation[0] == 'd')
{ {
const unsigned char *selected; const unsigned char *selected;
unsigned int len; unsigned int len;

View File

@ -235,8 +235,7 @@ typedef enum
#define ENC_ERROR 0 #define ENC_ERROR 0
#define ENC_PLAINTEXT 0x01 #define ENC_PLAINTEXT 0x01
#define ENC_GSSAPI 0x02 #define ENC_GSSAPI 0x02
#define ENC_DIRECT_SSL 0x04 #define ENC_SSL 0x04
#define ENC_NEGOTIATED_SSL 0x08
/* Target server type (decoded value of target_session_attrs) */ /* Target server type (decoded value of target_session_attrs) */
typedef enum typedef enum
@ -395,8 +394,7 @@ struct pg_conn
char *keepalives_count; /* maximum number of TCP keepalive char *keepalives_count; /* maximum number of TCP keepalive
* retransmits */ * retransmits */
char *sslmode; /* SSL mode (require,prefer,allow,disable) */ char *sslmode; /* SSL mode (require,prefer,allow,disable) */
char *sslnegotiation; /* SSL initiation style char *sslnegotiation; /* SSL initiation style (postgres,direct) */
* (postgres,direct,requiredirect) */
char *sslcompression; /* SSL compression (0 or 1) */ char *sslcompression; /* SSL compression (0 or 1) */
char *sslkey; /* client key filename */ char *sslkey; /* client key filename */
char *sslcert; /* client certificate filename */ char *sslcert; /* client certificate filename */

View File

@ -213,7 +213,7 @@ my @all_test_users =
('testuser', 'ssluser', 'nossluser', 'gssuser', 'nogssuser'); ('testuser', 'ssluser', 'nossluser', 'gssuser', 'nogssuser');
my @all_gssencmodes = ('disable', 'prefer', 'require'); my @all_gssencmodes = ('disable', 'prefer', 'require');
my @all_sslmodes = ('disable', 'allow', 'prefer', 'require'); my @all_sslmodes = ('disable', 'allow', 'prefer', 'require');
my @all_sslnegotiations = ('postgres', 'direct', 'requiredirect'); my @all_sslnegotiations = ('postgres', 'direct');
my $server_config = { my $server_config = {
server_ssl => 0, server_ssl => 0,
@ -228,23 +228,22 @@ if ($ssl_supported)
{ {
$test_table = q{ $test_table = q{
# USER GSSENCMODE SSLMODE SSLNEGOTIATION EVENTS -> OUTCOME # USER GSSENCMODE SSLMODE SSLNEGOTIATION EVENTS -> OUTCOME
testuser disable disable * connect, authok -> plain testuser disable disable postgres connect, authok -> plain
. . allow * connect, authok -> plain . . allow postgres connect, authok -> plain
. . prefer postgres connect, sslreject, authok -> plain . . prefer postgres connect, sslreject, authok -> plain
. . . direct connect, directsslreject, reconnect, sslreject, authok -> plain
. . . requiredirect connect, directsslreject, reconnect, authok -> plain
. . require postgres connect, sslreject -> fail . . require postgres connect, sslreject -> fail
. . . direct connect, directsslreject, reconnect, sslreject -> fail . . . direct connect, directsslreject -> fail
. . . requiredirect connect, directsslreject -> fail . prefer disable postgres connect, authok -> plain
. prefer disable * connect, authok -> plain . . allow postgres connect, authok -> plain
. . allow * connect, authok -> plain
. . prefer postgres connect, sslreject, authok -> plain . . prefer postgres connect, sslreject, authok -> plain
. . . direct connect, directsslreject, reconnect, sslreject, authok -> plain
. . . requiredirect connect, directsslreject, reconnect, authok -> plain
. . require postgres connect, sslreject -> fail . . require postgres connect, sslreject -> fail
. . . direct connect, directsslreject, reconnect, sslreject -> fail . . . direct connect, directsslreject -> fail
. . . requiredirect connect, directsslreject -> fail
}; # sslnegotiation=direct is not acccepted unless sslmode=require or stronger
* * disable direct - -> fail
* * allow direct - -> fail
* * prefer direct - -> fail
};
} }
else else
{ {
@ -258,11 +257,10 @@ testuser disable disable postgres connect, authok
. . allow postgres connect, authok -> plain . . allow postgres connect, authok -> plain
. . prefer postgres connect, authok -> plain . . prefer postgres connect, authok -> plain
# Without SSL support, sslmode=require and sslnegotiation=direct/requiredirect # Without SSL support, sslmode=require and sslnegotiation=direct are
# are not accepted at all. # not accepted at all
. * require * - -> fail * * require * - -> fail
. * * direct - -> fail * * * direct - -> fail
. * * requiredirect - -> fail
}; };
} }
@ -288,34 +286,26 @@ SKIP:
$test_table = q{ $test_table = q{
# USER GSSENCMODE SSLMODE SSLNEGOTIATION EVENTS -> OUTCOME # USER GSSENCMODE SSLMODE SSLNEGOTIATION EVENTS -> OUTCOME
testuser disable disable * connect, authok -> plain testuser disable disable postgres connect, authok -> plain
. . allow * connect, authok -> plain . . allow postgres connect, authok -> plain
. . prefer postgres connect, sslaccept, authok -> ssl . . prefer postgres connect, sslaccept, authok -> ssl
. . . direct connect, directsslaccept, authok -> ssl . . require postgres connect, sslaccept, authok -> ssl
. . . requiredirect connect, directsslaccept, authok -> ssl . . . direct connect, directsslaccept, authok -> ssl
. . require postgres connect, sslaccept, authok -> ssl ssluser . disable postgres connect, authfail -> fail
. . . direct connect, directsslaccept, authok -> ssl . . allow postgres connect, authfail, reconnect, sslaccept, authok -> ssl
. . . requiredirect connect, directsslaccept, authok -> ssl . . prefer postgres connect, sslaccept, authok -> ssl
ssluser . disable * connect, authfail -> fail . . require postgres connect, sslaccept, authok -> ssl
. . allow postgres connect, authfail, reconnect, sslaccept, authok -> ssl . . . direct connect, directsslaccept, authok -> ssl
. . . direct connect, authfail, reconnect, directsslaccept, authok -> ssl nossluser . disable postgres connect, authok -> plain
. . . requiredirect connect, authfail, reconnect, directsslaccept, authok -> ssl
. . prefer postgres connect, sslaccept, authok -> ssl
. . . direct connect, directsslaccept, authok -> ssl
. . . requiredirect connect, directsslaccept, authok -> ssl
. . require postgres connect, sslaccept, authok -> ssl
. . . direct connect, directsslaccept, authok -> ssl
. . . requiredirect connect, directsslaccept, authok -> ssl
nossluser . disable * connect, authok -> plain
. . allow postgres connect, authok -> plain . . allow postgres connect, authok -> plain
. . . direct connect, authok -> plain
. . . requiredirect connect, authok -> plain
. . prefer postgres connect, sslaccept, authfail, reconnect, authok -> plain . . prefer postgres connect, sslaccept, authfail, reconnect, authok -> plain
. . . direct connect, directsslaccept, authfail, reconnect, authok -> plain
. . . requiredirect connect, directsslaccept, authfail, reconnect, authok -> plain
. . require postgres connect, sslaccept, authfail -> fail . . require postgres connect, sslaccept, authfail -> fail
. . require direct connect, directsslaccept, authfail -> fail . . require direct connect, directsslaccept, authfail -> fail
. . require requiredirect connect, directsslaccept, authfail -> fail
# sslnegotiation=direct is not acccepted unless sslmode=require or stronger
* * disable direct - -> fail
* * allow direct - -> fail
* * prefer direct - -> fail
}; };
# Enable SSL in the server # Enable SSL in the server
@ -350,62 +340,54 @@ SKIP:
$test_table = q{ $test_table = q{
# USER GSSENCMODE SSLMODE SSLNEGOTIATION EVENTS -> OUTCOME # USER GSSENCMODE SSLMODE SSLNEGOTIATION EVENTS -> OUTCOME
testuser disable disable * connect, authok -> plain testuser disable disable postgres connect, authok -> plain
. . allow * connect, authok -> plain
. . prefer postgres connect, sslreject, authok -> plain
. . . direct connect, directsslreject, reconnect, sslreject, authok -> plain
. . . requiredirect connect, directsslreject, reconnect, authok -> plain
. . require postgres connect, sslreject -> fail
. . . direct connect, directsslreject, reconnect, sslreject -> fail
. . . requiredirect connect, directsslreject -> fail
. prefer * * connect, gssaccept, authok -> gss
. require * * connect, gssaccept, authok -> gss
gssuser disable disable * connect, authfail -> fail
. . allow postgres connect, authfail, reconnect, sslreject -> fail
. . . direct connect, authfail, reconnect, directsslreject, reconnect, sslreject -> fail
. . . requiredirect connect, authfail, reconnect, directsslreject -> fail
. . prefer postgres connect, sslreject, authfail -> fail
. . . direct connect, directsslreject, reconnect, sslreject, authfail -> fail
. . . requiredirect connect, directsslreject, reconnect, authfail -> fail
. . require postgres connect, sslreject -> fail
. . . direct connect, directsslreject, reconnect, sslreject -> fail
. . . requiredirect connect, directsslreject -> fail
. prefer * * connect, gssaccept, authok -> gss
. require * * connect, gssaccept, authok -> gss
nogssuser disable disable * connect, authok -> plain
. . allow postgres connect, authok -> plain . . allow postgres connect, authok -> plain
. . . direct connect, authok -> plain
. . . requiredirect connect, authok -> plain
. . prefer postgres connect, sslreject, authok -> plain . . prefer postgres connect, sslreject, authok -> plain
. . . direct connect, directsslreject, reconnect, sslreject, authok -> plain . . require postgres connect, sslreject -> fail
. . . requiredirect connect, directsslreject, reconnect, authok -> plain . . . direct connect, directsslreject -> fail
. prefer * postgres connect, gssaccept, authok -> gss
. prefer require direct connect, gssaccept, authok -> gss
. require * postgres connect, gssaccept, authok -> gss
. . require direct connect, gssaccept, authok -> gss
gssuser disable disable postgres connect, authfail -> fail
. . allow postgres connect, authfail, reconnect, sslreject -> fail
. . prefer postgres connect, sslreject, authfail -> fail
. . require postgres connect, sslreject -> fail . . require postgres connect, sslreject -> fail
. . . direct connect, directsslreject, reconnect, sslreject -> fail . . . direct connect, directsslreject -> fail
. . . requiredirect connect, directsslreject -> fail . prefer * postgres connect, gssaccept, authok -> gss
. prefer disable * connect, gssaccept, authfail, reconnect, authok -> plain . prefer require direct connect, gssaccept, authok -> gss
. require * postgres connect, gssaccept, authok -> gss
. . require direct connect, gssaccept, authok -> gss
nogssuser disable disable postgres connect, authok -> plain
. . allow postgres connect, authok -> plain
. . prefer postgres connect, sslreject, authok -> plain
. . require postgres connect, sslreject -> fail
. . . direct connect, directsslreject -> fail
. prefer disable postgres connect, gssaccept, authfail, reconnect, authok -> plain
. . allow postgres connect, gssaccept, authfail, reconnect, authok -> plain . . allow postgres connect, gssaccept, authfail, reconnect, authok -> plain
. . . direct connect, gssaccept, authfail, reconnect, authok -> plain
. . . requiredirect connect, gssaccept, authfail, reconnect, authok -> plain
. . prefer postgres connect, gssaccept, authfail, reconnect, sslreject, authok -> plain . . prefer postgres connect, gssaccept, authfail, reconnect, sslreject, authok -> plain
. . . direct connect, gssaccept, authfail, reconnect, directsslreject, reconnect, sslreject, authok -> plain
. . . requiredirect connect, gssaccept, authfail, reconnect, directsslreject, reconnect, authok -> plain
. . require postgres connect, gssaccept, authfail, reconnect, sslreject -> fail . . require postgres connect, gssaccept, authfail, reconnect, sslreject -> fail
. . . direct connect, gssaccept, authfail, reconnect, directsslreject, reconnect, sslreject -> fail . . . direct connect, gssaccept, authfail, reconnect, directsslreject -> fail
. . . requiredirect connect, gssaccept, authfail, reconnect, directsslreject -> fail . require disable postgres connect, gssaccept, authfail -> fail
. require disable * connect, gssaccept, authfail -> fail . . allow postgres connect, gssaccept, authfail -> fail
. . allow * connect, gssaccept, authfail -> fail . . prefer postgres connect, gssaccept, authfail -> fail
. . prefer * connect, gssaccept, authfail -> fail . . require postgres connect, gssaccept, authfail -> fail # If both GSSAPI and sslmode are required, and GSS is not available -> fail
. . require * connect, gssaccept, authfail -> fail # If both GSSAPI and sslmode are required, and GSS is not available -> fail . . . direct connect, gssaccept, authfail -> fail # If both GSSAPI and sslmode are required, and GSS is not available -> fail
# sslnegotiation=direct is not acccepted unless sslmode=require or stronger
* * disable direct - -> fail
* * allow direct - -> fail
* * prefer direct - -> fail
}; };
# The expected events and outcomes above assume that SSL support # The expected events and outcomes above assume that SSL support
# is enabled. When libpq is compiled without SSL support, all # is enabled. When libpq is compiled without SSL support, all
# attempts to connect with sslmode=require or # attempts to connect with sslmode=require or
# sslnegotiation=direct/requiredirect would fail immediately without # sslnegotiation=direct would fail immediately without even
# even connecting to the server. Skip those, because we tested # connecting to the server. Skip those, because we tested them
# them earlier already. # earlier already.
my ($sslmodes, $sslnegotiations); my ($sslmodes, $sslnegotiations);
if ($ssl_supported != 0) if ($ssl_supported != 0)
{ {
@ -445,100 +427,84 @@ SKIP:
$test_table = q{ $test_table = q{
# USER GSSENCMODE SSLMODE SSLNEGOTIATION EVENTS -> OUTCOME # USER GSSENCMODE SSLMODE SSLNEGOTIATION EVENTS -> OUTCOME
testuser disable disable * connect, authok -> plain testuser disable disable postgres connect, authok -> plain
. . allow * connect, authok -> plain
. . prefer postgres connect, sslaccept, authok -> ssl
. . . direct connect, directsslaccept, authok -> ssl
. . . requiredirect connect, directsslaccept, authok -> ssl
. . require postgres connect, sslaccept, authok -> ssl
. . . direct connect, directsslaccept, authok -> ssl
. . . requiredirect connect, directsslaccept, authok -> ssl
. prefer disable * connect, gssaccept, authok -> gss
. . allow * connect, gssaccept, authok -> gss
. . prefer * connect, gssaccept, authok -> gss
. . require * connect, gssaccept, authok -> gss # If both GSS and SSL is possible, GSS is chosen over SSL, even if sslmode=require
. require disable * connect, gssaccept, authok -> gss
. . allow * connect, gssaccept, authok -> gss
. . prefer * connect, gssaccept, authok -> gss
. . require * connect, gssaccept, authok -> gss # If both GSS and SSL is possible, GSS is chosen over SSL, even if sslmode=require
gssuser disable disable * connect, authfail -> fail
. . allow postgres connect, authfail, reconnect, sslaccept, authfail -> fail
. . . direct connect, authfail, reconnect, directsslaccept, authfail -> fail
. . . requiredirect connect, authfail, reconnect, directsslaccept, authfail -> fail
. . prefer postgres connect, sslaccept, authfail, reconnect, authfail -> fail
. . . direct connect, directsslaccept, authfail, reconnect, authfail -> fail
. . . requiredirect connect, directsslaccept, authfail, reconnect, authfail -> fail
. . require postgres connect, sslaccept, authfail -> fail
. . . direct connect, directsslaccept, authfail -> fail
. . . requiredirect connect, directsslaccept, authfail -> fail
. prefer disable * connect, gssaccept, authok -> gss
. . allow * connect, gssaccept, authok -> gss
. . prefer * connect, gssaccept, authok -> gss
. . require * connect, gssaccept, authok -> gss # GSS is chosen over SSL, even though sslmode=require
. require disable * connect, gssaccept, authok -> gss
. . allow * connect, gssaccept, authok -> gss
. . prefer * connect, gssaccept, authok -> gss
. . require * connect, gssaccept, authok -> gss # If both GSS and SSL is possible, GSS is chosen over SSL, even if sslmode=require
ssluser disable disable * connect, authfail -> fail
. . allow postgres connect, authfail, reconnect, sslaccept, authok -> ssl
. . . direct connect, authfail, reconnect, directsslaccept, authok -> ssl
. . . requiredirect connect, authfail, reconnect, directsslaccept, authok -> ssl
. . prefer postgres connect, sslaccept, authok -> ssl
. . . direct connect, directsslaccept, authok -> ssl
. . . requiredirect connect, directsslaccept, authok -> ssl
. . require postgres connect, sslaccept, authok -> ssl
. . . direct connect, directsslaccept, authok -> ssl
. . . requiredirect connect, directsslaccept, authok -> ssl
. prefer disable * connect, gssaccept, authfail, reconnect, authfail -> fail
. . allow postgres connect, gssaccept, authfail, reconnect, authfail, reconnect, sslaccept, authok -> ssl
. . . direct connect, gssaccept, authfail, reconnect, authfail, reconnect, directsslaccept, authok -> ssl
. . . requiredirect connect, gssaccept, authfail, reconnect, authfail, reconnect, directsslaccept, authok -> ssl
. . prefer postgres connect, gssaccept, authfail, reconnect, sslaccept, authok -> ssl
. . . direct connect, gssaccept, authfail, reconnect, directsslaccept, authok -> ssl
. . . requiredirect connect, gssaccept, authfail, reconnect, directsslaccept, authok -> ssl
. . require postgres connect, gssaccept, authfail, reconnect, sslaccept, authok -> ssl
. . . direct connect, gssaccept, authfail, reconnect, directsslaccept, authok -> ssl
. . . requiredirect connect, gssaccept, authfail, reconnect, directsslaccept, authok -> ssl
. require disable * connect, gssaccept, authfail -> fail
. . allow * connect, gssaccept, authfail -> fail
. . prefer * connect, gssaccept, authfail -> fail
. . require * connect, gssaccept, authfail -> fail # If both GSS and SSL are required, the sslmode=require is effectively ignored and GSS is required
nogssuser disable disable * connect, authok -> plain
. . allow postgres connect, authok -> plain . . allow postgres connect, authok -> plain
. . . direct connect, authok -> plain
. . . requiredirect connect, authok -> plain
. . prefer postgres connect, sslaccept, authok -> ssl . . prefer postgres connect, sslaccept, authok -> ssl
. . . direct connect, directsslaccept, authok -> ssl
. . . requiredirect connect, directsslaccept, authok -> ssl
. . require postgres connect, sslaccept, authok -> ssl . . require postgres connect, sslaccept, authok -> ssl
. . . direct connect, directsslaccept, authok -> ssl . . . direct connect, directsslaccept, authok -> ssl
. . . requiredirect connect, directsslaccept, authok -> ssl . prefer disable postgres connect, gssaccept, authok -> gss
. prefer disable * connect, gssaccept, authfail, reconnect, authok -> plain . . allow postgres connect, gssaccept, authok -> gss
. . allow * connect, gssaccept, authfail, reconnect, authok -> plain . . prefer postgres connect, gssaccept, authok -> gss
. . prefer postgres connect, gssaccept, authfail, reconnect, sslaccept, authok -> ssl . . require postgres connect, gssaccept, authok -> gss # If both GSS and SSL is possible, GSS is chosen over SSL, even if sslmode=require
. . . direct connect, gssaccept, authfail, reconnect, directsslaccept, authok -> ssl . . . direct connect, gssaccept, authok -> gss
. . . requiredirect connect, gssaccept, authfail, reconnect, directsslaccept, authok -> ssl . require disable postgres connect, gssaccept, authok -> gss
. . require postgres connect, gssaccept, authfail, reconnect, sslaccept, authok -> ssl . . allow postgres connect, gssaccept, authok -> gss
. . . direct connect, gssaccept, authfail, reconnect, directsslaccept, authok -> ssl . . prefer postgres connect, gssaccept, authok -> gss
. . . requiredirect connect, gssaccept, authfail, reconnect, directsslaccept, authok -> ssl . . require postgres connect, gssaccept, authok -> gss # If both GSS and SSL is possible, GSS is chosen over SSL, even if sslmode=require
. require disable * connect, gssaccept, authfail -> fail . . . direct connect, gssaccept, authok -> gss
. . allow * connect, gssaccept, authfail -> fail
. . prefer * connect, gssaccept, authfail -> fail
. . require * connect, gssaccept, authfail -> fail # If both GSS and SSL are required, the sslmode=require is effectively ignored and GSS is required
nossluser disable disable * connect, authok -> plain gssuser disable disable postgres connect, authfail -> fail
. . allow * connect, authok -> plain . . allow postgres connect, authfail, reconnect, sslaccept, authfail -> fail
. . prefer postgres connect, sslaccept, authfail, reconnect, authok -> plain . . prefer postgres connect, sslaccept, authfail, reconnect, authfail -> fail
. . . direct connect, directsslaccept, authfail, reconnect, authok -> plain
. . . requiredirect connect, directsslaccept, authfail, reconnect, authok -> plain
. . require postgres connect, sslaccept, authfail -> fail . . require postgres connect, sslaccept, authfail -> fail
. . . direct connect, directsslaccept, authfail -> fail . . . direct connect, directsslaccept, authfail -> fail
. . . requiredirect connect, directsslaccept, authfail -> fail . prefer disable postgres connect, gssaccept, authok -> gss
. prefer * * connect, gssaccept, authok -> gss . . allow postgres connect, gssaccept, authok -> gss
. require * * connect, gssaccept, authok -> gss . . prefer postgres connect, gssaccept, authok -> gss
. . require postgres connect, gssaccept, authok -> gss # GSS is chosen over SSL, even though sslmode=require
. . . direct connect, gssaccept, authok -> gss
. require disable postgres connect, gssaccept, authok -> gss
. . allow postgres connect, gssaccept, authok -> gss
. . prefer postgres connect, gssaccept, authok -> gss
. . require postgres connect, gssaccept, authok -> gss # If both GSS and SSL is possible, GSS is chosen over SSL, even if sslmode=require
. . . direct connect, gssaccept, authok -> gss
ssluser disable disable postgres connect, authfail -> fail
. . allow postgres connect, authfail, reconnect, sslaccept, authok -> ssl
. . prefer postgres connect, sslaccept, authok -> ssl
. . require postgres connect, sslaccept, authok -> ssl
. . . direct connect, directsslaccept, authok -> ssl
. prefer disable postgres connect, gssaccept, authfail, reconnect, authfail -> fail
. . allow postgres connect, gssaccept, authfail, reconnect, authfail, reconnect, sslaccept, authok -> ssl
. . prefer postgres connect, gssaccept, authfail, reconnect, sslaccept, authok -> ssl
. . require postgres connect, gssaccept, authfail, reconnect, sslaccept, authok -> ssl
. . . direct connect, gssaccept, authfail, reconnect, directsslaccept, authok -> ssl
. require disable postgres connect, gssaccept, authfail -> fail
. . allow postgres connect, gssaccept, authfail -> fail
. . prefer postgres connect, gssaccept, authfail -> fail
. . require postgres connect, gssaccept, authfail -> fail # If both GSS and SSL are required, the sslmode=require is effectively ignored and GSS is required
. . . direct connect, gssaccept, authfail -> fail
nogssuser disable disable postgres connect, authok -> plain
. . allow postgres connect, authok -> plain
. . prefer postgres connect, sslaccept, authok -> ssl
. . require postgres connect, sslaccept, authok -> ssl
. . . direct connect, directsslaccept, authok -> ssl
. prefer disable postgres connect, gssaccept, authfail, reconnect, authok -> plain
. . allow postgres connect, gssaccept, authfail, reconnect, authok -> plain
. . prefer postgres connect, gssaccept, authfail, reconnect, sslaccept, authok -> ssl
. . require postgres connect, gssaccept, authfail, reconnect, sslaccept, authok -> ssl
. . . direct connect, gssaccept, authfail, reconnect, directsslaccept, authok -> ssl
. require disable postgres connect, gssaccept, authfail -> fail
. . allow postgres connect, gssaccept, authfail -> fail
. . prefer postgres connect, gssaccept, authfail -> fail
. . require postgres connect, gssaccept, authfail -> fail # If both GSS and SSL are required, the sslmode=require is effectively ignored and GSS is required
. . . direct connect, gssaccept, authfail -> fail
nossluser disable disable postgres connect, authok -> plain
. . allow postgres connect, authok -> plain
. . prefer postgres connect, sslaccept, authfail, reconnect, authok -> plain
. . require postgres connect, sslaccept, authfail -> fail
. . . direct connect, directsslaccept, authfail -> fail
. prefer * postgres connect, gssaccept, authok -> gss
. . require direct connect, gssaccept, authok -> gss
. require * postgres connect, gssaccept, authok -> gss
. . require direct connect, gssaccept, authok -> gss
# sslnegotiation=direct is not acccepted unless sslmode=require or stronger
* * disable direct - -> fail
* * allow direct - -> fail
* * prefer direct - -> fail
}; };
note("Running tests with both GSS and SSL enabled in server"); note("Running tests with both GSS and SSL enabled in server");