aboutsummaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2020-06-27 12:47:58 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2020-06-27 12:47:58 -0400
commitb63dd3d88f479947ef7fb7cbf5db27de66ae0654 (patch)
treed9278731eeb77c93b702190977072e4f521c14ea /src/backend
parent6e682f61a5bdb08164a805419144318db6b7229f (diff)
downloadpostgresql-b63dd3d88f479947ef7fb7cbf5db27de66ae0654.tar.gz
postgresql-b63dd3d88f479947ef7fb7cbf5db27de66ae0654.zip
Add hints about protocol-version-related SSL connection failures.
OpenSSL's native reports about problems related to protocol version restrictions are pretty opaque and inconsistent. When we get an SSL error that is plausibly due to this, emit a hint message that includes the range of SSL protocol versions we (think we) are allowing. This should at least get the user thinking in the right direction to resolve the problem, even if the hint isn't totally accurate, which it might not be for assorted reasons. Back-patch to v13 where we increased the default minimum protocol version, thereby increasing the risk of this class of failure. Patch by me, reviewed by Daniel Gustafsson Discussion: https://postgr.es/m/a9408304-4381-a5af-d259-e55d349ae4ce@2ndquadrant.com
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/libpq/be-secure-openssl.c67
1 files changed, 66 insertions, 1 deletions
diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c
index 8adf64c78ee..d1cf455ab44 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,50 @@ aloop:
errmsg("could not accept SSL connection: EOF detected")));
break;
case SSL_ERROR_SSL:
+ switch (ERR_GET_REASON(ecode))
+ {
+ /*
+ * UNSUPPORTED_PROTOCOL, WRONG_VERSION_NUMBER, and
+ * TLSV1_ALERT_PROTOCOL_VERSION have been observed
+ * when trying to communicate with an old OpenSSL
+ * library, or when the client and server specify
+ * disjoint protocol ranges. NO_PROTOCOLS_AVAILABLE
+ * occurs if there's a local misconfiguration (which
+ * can happen despite our checks, if openssl.cnf
+ * injects a limit we didn't account for). 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_PROTOCOL:
+ 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:
+ case SSL_R_TLSV1_ALERT_PROTOCOL_VERSION:
+ 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) :
+ MIN_OPENSSL_TLS_VERSION,
+ ssl_max_protocol_version ?
+ ssl_protocol_version_to_string(ssl_max_protocol_version) :
+ MAX_OPENSSL_TLS_VERSION) : 0));
break;
case SSL_ERROR_ZERO_RETURN:
ereport(COMMERROR,
@@ -1328,6 +1370,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)