summaryrefslogtreecommitdiff
path: root/src/interfaces/libpq
diff options
context:
space:
mode:
authorDaniel Gustafsson <dgustafsson@postgresql.org>2023-04-19 12:54:58 +0200
committerDaniel Gustafsson <dgustafsson@postgresql.org>2023-04-19 12:54:58 +0200
commit0b5d1fb36adda612bd3d5d032463a6eeb0729237 (patch)
tree0526f777b9b6ba94fe17d3e01b3ec97fcd85fd44 /src/interfaces/libpq
parent77dedeb2c45745f592b504e181fa9d391d9afff0 (diff)
downloadpostgresql-0b5d1fb36adda612bd3d5d032463a6eeb0729237.tar.gz
Fix errormessage for missing system CA in OpenSSL 3.1
The error message for a missing or invalid system CA when using sslrootcert=system differs based on the OpenSSL version used. In OpenSSL 1.0.1-3.0 it is reported as SSL Error, with varying degrees of helpfulness in the error message. With OpenSSL 3.1 it is reported as an SSL SYSCALL error with "Undefined error" as the error message. This fix pulls out the particular error in OpenSSL 3.1 as a certificate verify error in order to help the user better figure out what happened, and to keep the ssl test working. While there is no evidence that extracing the errors will clobber errno, this adds a guard against that regardless to also make the consistent with how we handle OpenSSL errors elsewhere. It also memorizes the output from OpenSSL 3.0 in the test in cases where the system CA isn't responding. Reported-by: Peter Eisentraut <peter.eisentraut@enterprisedb.com> Discussion: https://postgr.es/m/c39be3c5-c1a5-1e33-1024-16f527e251a4@enterprisedb.com
Diffstat (limited to 'src/interfaces/libpq')
-rw-r--r--src/interfaces/libpq/fe-secure-openssl.c24
1 files changed, 21 insertions, 3 deletions
diff --git a/src/interfaces/libpq/fe-secure-openssl.c b/src/interfaces/libpq/fe-secure-openssl.c
index 00b203cbfa..470e926540 100644
--- a/src/interfaces/libpq/fe-secure-openssl.c
+++ b/src/interfaces/libpq/fe-secure-openssl.c
@@ -1489,10 +1489,12 @@ open_client_SSL(PGconn *conn)
{
int r;
+ SOCK_ERRNO_SET(0);
ERR_clear_error();
r = SSL_connect(conn->ssl);
if (r <= 0)
{
+ int save_errno = SOCK_ERRNO;
int err = SSL_get_error(conn->ssl, r);
unsigned long ecode;
@@ -1508,10 +1510,26 @@ open_client_SSL(PGconn *conn)
case SSL_ERROR_SYSCALL:
{
char sebuf[PG_STRERROR_R_BUFLEN];
-
- if (r == -1)
+ unsigned long vcode;
+
+ vcode = SSL_get_verify_result(conn->ssl);
+
+ /*
+ * If we get an X509 error here for failing to load the
+ * local issuer cert, without an error in the socket layer
+ * it means that verification failed due to a missing
+ * system CA pool without it being a protocol error. We
+ * inspect the sslrootcert setting to ensure that the user
+ * was using the system CA pool. For other errors, log them
+ * using the normal SYSCALL logging.
+ */
+ if (!save_errno && vcode == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY &&
+ strcmp(conn->sslrootcert, "system") == 0)
+ libpq_append_conn_error(conn, "SSL error: certificate verify failed: %s",
+ X509_verify_cert_error_string(vcode));
+ else if (r == -1)
libpq_append_conn_error(conn, "SSL SYSCALL error: %s",
- SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
+ SOCK_STRERROR(save_errno, sebuf, sizeof(sebuf)));
else
libpq_append_conn_error(conn, "SSL SYSCALL error: EOF detected");
pgtls_close(conn);