aboutsummaryrefslogtreecommitdiff
path: root/src/backend/libpq/be-secure-openssl.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2024-03-07 19:37:51 -0500
committerTom Lane <tgl@sss.pgh.pa.us>2024-03-07 19:37:51 -0500
commit0fe82e45cbedbe840f00d834cc6cae55593ef8cf (patch)
tree72a09a4acf8d6b124d3149420ff48f503eca0b14 /src/backend/libpq/be-secure-openssl.c
parentb5c645d2a2652070ac128a42cf0d7b34403a6cfe (diff)
downloadpostgresql-0fe82e45cbedbe840f00d834cc6cae55593ef8cf.tar.gz
postgresql-0fe82e45cbedbe840f00d834cc6cae55593ef8cf.zip
Cope with a deficiency in OpenSSL 3.x's error reporting.
In OpenSSL 3.0.0 and later, ERR_reason_error_string randomly refuses to provide a string for error codes representing system errno values (e.g., "No such file or directory"). There is a poorly-documented way to extract the errno from the SSL error code in this case, so do that and apply strerror, rather than falling back to reporting the error code's numeric value as we were previously doing. Problem reported by David Zhang, although this is not his proposed patch; it's instead based on a suggestion from Heikki Linnakangas. Back-patch to all supported branches, since any of them are likely to be used with recent OpenSSL. Discussion: https://postgr.es/m/b6fb018b-f05c-4afd-abd3-318c649faf18@highgo.ca
Diffstat (limited to 'src/backend/libpq/be-secure-openssl.c')
-rw-r--r--src/backend/libpq/be-secure-openssl.c19
1 files changed, 16 insertions, 3 deletions
diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c
index ed13e8b06df..4c7e16ca2ca 100644
--- a/src/backend/libpq/be-secure-openssl.c
+++ b/src/backend/libpq/be-secure-openssl.c
@@ -1241,9 +1241,9 @@ initialize_ecdh(SSL_CTX *context, bool isServerStart)
*
* ERR_get_error() is used by caller to get errcode to pass here.
*
- * Some caution is needed here since ERR_reason_error_string will
- * return NULL if it doesn't recognize the error code. We don't
- * want to return NULL ever.
+ * Some caution is needed here since ERR_reason_error_string will return NULL
+ * if it doesn't recognize the error code, or (in OpenSSL >= 3) if the code
+ * represents a system errno value. We don't want to return NULL ever.
*/
static const char *
SSLerrmessage(unsigned long ecode)
@@ -1256,6 +1256,19 @@ SSLerrmessage(unsigned long ecode)
errreason = ERR_reason_error_string(ecode);
if (errreason != NULL)
return errreason;
+
+ /*
+ * In OpenSSL 3.0.0 and later, ERR_reason_error_string randomly refuses to
+ * map system errno values. We can cover that shortcoming with this bit
+ * of code. Older OpenSSL versions don't have the ERR_SYSTEM_ERROR macro,
+ * but that's okay because they don't have the shortcoming either.
+ */
+#ifdef ERR_SYSTEM_ERROR
+ if (ERR_SYSTEM_ERROR(ecode))
+ return strerror(ERR_GET_REASON(ecode));
+#endif
+
+ /* No choice but to report the numeric ecode */
snprintf(errbuf, sizeof(errbuf), _("SSL error code %lu"), ecode);
return errbuf;
}