aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/interfaces/libpq/fe-secure-openssl.c24
-rw-r--r--src/test/ssl/t/001_ssltests.pl4
2 files changed, 24 insertions, 4 deletions
diff --git a/src/interfaces/libpq/fe-secure-openssl.c b/src/interfaces/libpq/fe-secure-openssl.c
index 00b203cbfa3..470e9265400 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);
diff --git a/src/test/ssl/t/001_ssltests.pl b/src/test/ssl/t/001_ssltests.pl
index 6fdc040cfc2..e7956cb1a0f 100644
--- a/src/test/ssl/t/001_ssltests.pl
+++ b/src/test/ssl/t/001_ssltests.pl
@@ -476,10 +476,12 @@ $common_connstr =
"$default_ssl_connstr user=ssltestuser dbname=trustdb sslrootcert=system hostaddr=$SERVERHOSTADDR";
# By default our custom-CA-signed certificate should not be trusted.
+# OpenSSL 3.0 reports a missing/invalid system CA as "unregistered schema"
+# instead of a failed certificate verification.
$node->connect_fails(
"$common_connstr sslmode=verify-full host=common-name.pg-ssltest.test",
"sslrootcert=system does not connect with private CA",
- expected_stderr => qr/SSL error: certificate verify failed/);
+ expected_stderr => qr/SSL error: (certificate verify failed|unregistered scheme)/);
# Modes other than verify-full cannot be mixed with sslrootcert=system.
$node->connect_fails(