From: Tom Lane <tgl@sss.pgh.pa.us>
To: Daniel Gustafsson <daniel@yesql.se>
Cc: Magnus Hagander <magnus@hagander.net>
Cc: Peter Eisentraut <peter.eisentraut@2ndquadrant.com>
Cc: pgsql-hackers <pgsql-hackers@postgresql.org>
Subject: Re: should libpq also require TLSv1.2 by default?
Date: Fri, 26 Jun 2020 11:36:42 -0400
Message-ID: <16724.1593185802@sss.pgh.pa.us> (raw)
In-Reply-To: <2339796.1593177583@sss.pgh.pa.us>
References: <a9408304-4381-a5af-d259-e55d349ae4ce@2ndquadrant.com>
<4FBC50DB-599A-42AA-90C8-3051E3A748BB@yesql.se>
<CABUevEzn3BH0y+ToD8jkXkXmSvRSA7tAX4v+16M4fSr4fJDH4A@mail.gmail.com>
<DF11E406-A9AB-43A6-9B0E-5291644CC16F@yesql.se>
<2305871.1593125045@sss.pgh.pa.us>
<F50C22DD-A2C0-461A-93CD-3B87847F8F82@yesql.se>
<2339796.1593177583@sss.pgh.pa.us>
Here is a quick attempt at getting libpq and the server to report
suitable hint messages about SSL version problems.
The main thing I don't like about this as formulated is that I hard-wired
knowledge of the minimum and maximum SSL versions into the hint messages.
That's clearly not very maintainable, but it seems really hard to keep the
messages readable/useful without giving concrete version numbers.
Anybdy have a better idea? Is there a reasonably direct way to ask
OpenSSL what its min and max versions are?
regards, tom lane
Attachments:ssl-protocol-version-hints-1.patch (text/x-diff, 4.8K) downloaddiff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.cindex 8adf64c78e..380268636a 100644--- a/src/backend/libpq/be-secure-openssl.c+++ b/src/backend/libpq/be-secure-openssl.c@@ -72,6 +72,7 @@ static bool dummy_ssl_passwd_cb_called = false;
static bool ssl_is_server_start;
static int ssl_protocol_version_to_openssl(int v);
+static const char *ssl_protocol_version_to_string(int v);
/* ------------------------------------------------------------ */
/* Public interface */
@@ -365,6 +366,7 @@ be_tls_open_server(Port *port)
int err;
int waitfor;
unsigned long ecode;
+ bool give_proto_hint;
Assert(!port->ssl);
Assert(!port->peer);
@@ -451,10 +453,44 @@ aloop:
errmsg("could not accept SSL connection: EOF detected")));
break;
case SSL_ERROR_SSL:
+ switch (ERR_GET_REASON(ecode))+ {+ /*+ * NO_PROTOCOLS_AVAILABLE occurs if the client and+ * server min/max protocol version limits don't+ * overlap. UNSUPPORTED_PROTOCOL and+ * WRONG_VERSION_NUMBER have been observed when trying+ * to communicate with an old OpenSSL library. It's+ * not very clear what would make OpenSSL return the+ * other codes listed here, but a hint about protocol+ * versions seems like it's appropriate for all.+ */+ case SSL_R_NO_PROTOCOLS_AVAILABLE:+ case SSL_R_UNSUPPORTED_PROTOCOL:+ case SSL_R_BAD_PROTOCOL_VERSION_NUMBER:+ case SSL_R_UNKNOWN_SSL_VERSION:+ case SSL_R_UNSUPPORTED_SSL_VERSION:+ case SSL_R_VERSION_TOO_HIGH:+ case SSL_R_VERSION_TOO_LOW:+ case SSL_R_WRONG_SSL_VERSION:+ case SSL_R_WRONG_VERSION_NUMBER:+ give_proto_hint = true;+ break;+ default:+ give_proto_hint = false;+ break;+ }
ereport(COMMERROR,
(errcode(ERRCODE_PROTOCOL_VIOLATION),
errmsg("could not accept SSL connection: %s",
- SSLerrmessage(ecode))));+ SSLerrmessage(ecode)),+ give_proto_hint ? errhint("This may indicate that the client does not support any SSL protocol version between %s and %s.",+ ssl_min_protocol_version ?+ ssl_protocol_version_to_string(ssl_min_protocol_version) :+ "TLSv1",+ ssl_max_protocol_version ?+ ssl_protocol_version_to_string(ssl_max_protocol_version) :+ "TLSv1.3") : 0));
break;
case SSL_ERROR_ZERO_RETURN:
ereport(COMMERROR,
@@ -1328,6 +1364,29 @@ ssl_protocol_version_to_openssl(int v)
return -1;
}
+/*+ * Likewise provide a mapping to strings.+ */+static const char *+ssl_protocol_version_to_string(int v)+{+ switch (v)+ {+ case PG_TLS_ANY:+ return "any";+ case PG_TLS1_VERSION:+ return "TLSv1";+ case PG_TLS1_1_VERSION:+ return "TLSv1.1";+ case PG_TLS1_2_VERSION:+ return "TLSv1.2";+ case PG_TLS1_3_VERSION:+ return "TLSv1.3";+ }++ return "(unrecognized)";+}+
static void
default_openssl_tls_init(SSL_CTX *context, bool isServerStart)
diff --git a/src/interfaces/libpq/fe-secure-openssl.c b/src/interfaces/libpq/fe-secure-openssl.cindex 2d813ef5f9..71407bffd4 100644--- a/src/interfaces/libpq/fe-secure-openssl.c+++ b/src/interfaces/libpq/fe-secure-openssl.c@@ -1304,6 +1304,40 @@ open_client_SSL(PGconn *conn)
libpq_gettext("SSL error: %s\n"),
err);
SSLerrfree(err);
+ switch (ERR_GET_REASON(ecode))+ {+ /*+ * NO_PROTOCOLS_AVAILABLE occurs if the client and+ * server min/max protocol version limits don't+ * overlap. UNSUPPORTED_PROTOCOL and+ * WRONG_VERSION_NUMBER have been observed when+ * trying to communicate with an old OpenSSL+ * library. It's not very clear what would make+ * OpenSSL return the other codes listed here, but+ * a hint about protocol versions seems like it's+ * appropriate for all.+ */+ case SSL_R_NO_PROTOCOLS_AVAILABLE:+ case SSL_R_UNSUPPORTED_PROTOCOL:+ case SSL_R_BAD_PROTOCOL_VERSION_NUMBER:+ case SSL_R_UNKNOWN_SSL_VERSION:+ case SSL_R_UNSUPPORTED_SSL_VERSION:+ case SSL_R_VERSION_TOO_HIGH:+ case SSL_R_VERSION_TOO_LOW:+ case SSL_R_WRONG_SSL_VERSION:+ case SSL_R_WRONG_VERSION_NUMBER:+ appendPQExpBuffer(&conn->errorMessage,+ libpq_gettext("This may indicate that the server does not support any SSL protocol version between %s and %s.\n"),+ conn->ssl_min_protocol_version ?+ conn->ssl_min_protocol_version :+ "TLSv1",+ conn->ssl_max_protocol_version ?+ conn->ssl_max_protocol_version :+ "TLSv1.3");+ break;+ default:+ break;+ }
pgtls_close(conn);
return PGRES_POLLING_FAILED;
}
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: pgsql-hackers@postgresql.org
Cc: tgl@sss.pgh.pa.us, daniel@yesql.se, magnus@hagander.net, peter.eisentraut@2ndquadrant.com
Subject: Re: should libpq also require TLSv1.2 by default?
In-Reply-To: <16724.1593185802@sss.pgh.pa.us>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by DDX for PostgreSQL; see mirroring instructions
for how to clone and mirror all data and code used for this inbox