Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 6a2c80e

Browse files
committed
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
1 parent dd73d10 commit 6a2c80e

File tree

2 files changed

+36
-6
lines changed

2 files changed

+36
-6
lines changed

src/backend/libpq/be-secure-openssl.c

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1350,9 +1350,9 @@ initialize_ecdh(SSL_CTX *context, bool isServerStart)
13501350
*
13511351
* ERR_get_error() is used by caller to get errcode to pass here.
13521352
*
1353-
* Some caution is needed here since ERR_reason_error_string will
1354-
* return NULL if it doesn't recognize the error code. We don't
1355-
* want to return NULL ever.
1353+
* Some caution is needed here since ERR_reason_error_string will return NULL
1354+
* if it doesn't recognize the error code, or (in OpenSSL >= 3) if the code
1355+
* represents a system errno value. We don't want to return NULL ever.
13561356
*/
13571357
static const char *
13581358
SSLerrmessage(unsigned long ecode)
@@ -1365,6 +1365,19 @@ SSLerrmessage(unsigned long ecode)
13651365
errreason = ERR_reason_error_string(ecode);
13661366
if (errreason != NULL)
13671367
return errreason;
1368+
1369+
/*
1370+
* In OpenSSL 3.0.0 and later, ERR_reason_error_string randomly refuses to
1371+
* map system errno values. We can cover that shortcoming with this bit
1372+
* of code. Older OpenSSL versions don't have the ERR_SYSTEM_ERROR macro,
1373+
* but that's okay because they don't have the shortcoming either.
1374+
*/
1375+
#ifdef ERR_SYSTEM_ERROR
1376+
if (ERR_SYSTEM_ERROR(ecode))
1377+
return strerror(ERR_GET_REASON(ecode));
1378+
#endif
1379+
1380+
/* No choice but to report the numeric ecode */
13681381
snprintf(errbuf, sizeof(errbuf), _("SSL error code %lu"), ecode);
13691382
return errbuf;
13701383
}

src/interfaces/libpq/fe-secure-openssl.c

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1675,10 +1675,11 @@ pgtls_close(PGconn *conn)
16751675
* Obtain reason string for passed SSL errcode
16761676
*
16771677
* ERR_get_error() is used by caller to get errcode to pass here.
1678+
* The result must be freed after use, using SSLerrfree.
16781679
*
1679-
* Some caution is needed here since ERR_reason_error_string will
1680-
* return NULL if it doesn't recognize the error code. We don't
1681-
* want to return NULL ever.
1680+
* Some caution is needed here since ERR_reason_error_string will return NULL
1681+
* if it doesn't recognize the error code, or (in OpenSSL >= 3) if the code
1682+
* represents a system errno value. We don't want to return NULL ever.
16821683
*/
16831684
static char ssl_nomem[] = "out of memory allocating error description";
16841685

@@ -1704,6 +1705,22 @@ SSLerrmessage(unsigned long ecode)
17041705
strlcpy(errbuf, errreason, SSL_ERR_LEN);
17051706
return errbuf;
17061707
}
1708+
1709+
/*
1710+
* In OpenSSL 3.0.0 and later, ERR_reason_error_string randomly refuses to
1711+
* map system errno values. We can cover that shortcoming with this bit
1712+
* of code. Older OpenSSL versions don't have the ERR_SYSTEM_ERROR macro,
1713+
* but that's okay because they don't have the shortcoming either.
1714+
*/
1715+
#ifdef ERR_SYSTEM_ERROR
1716+
if (ERR_SYSTEM_ERROR(ecode))
1717+
{
1718+
strlcpy(errbuf, strerror(ERR_GET_REASON(ecode)), SSL_ERR_LEN);
1719+
return errbuf;
1720+
}
1721+
#endif
1722+
1723+
/* No choice but to report the numeric ecode */
17071724
snprintf(errbuf, SSL_ERR_LEN, libpq_gettext("SSL error code %lu"), ecode);
17081725
return errbuf;
17091726
}

0 commit comments

Comments
 (0)