From: Jacob Champion <pchampion@vmware.com>
To: peter.eisentraut@enterprisedb.com <peter.eisentraut@enterprisedb.com>
To: pgsql-hackers@postgresql.org <pgsql-hackers@postgresql.org>
Subject: Re: [PATCH] Log details for client certificate failures
Date: Thu, 12 May 2022 22:36:01 +0000
Message-ID: <9b8338210b865d79239ec35ca523792ce331c0a3.camel@vmware.com> (raw)
In-Reply-To: <7c0468dcadbc0d0c987daf9ca08c8d111948eae6.camel@vmware.com>
References: <d13c4a5787c2a3f83705124f0391e0738c796751.camel@vmware.com>
<cd03fa63-d4d9-8d3b-f9f5-13206a28d888@enterprisedb.com>
<a922e857c4e4a073f219bc5005b862eb22255c20.camel@vmware.com>
<290871e5-f1d9-54a8-5df4-dbd9e604c08d@enterprisedb.com>
<7c0468dcadbc0d0c987daf9ca08c8d111948eae6.camel@vmware.com>
On Thu, 2022-05-05 at 15:12 +0000, Jacob Champion wrote:
> On Wed, 2022-05-04 at 15:53 +0200, Peter Eisentraut wrote:
> > In terms of aligning what is printed, I meant that pg_stat_ssl uses the
> > issuer plus serial number to identify the certificate unambiguously.
>
> Oh, that's a great idea. I'll do that too.
v2 limits the maximum subject length and adds the serial number to the
logs.
Thanks!
--Jacob
Attachments:since-v1.diff.txt (text/plain, 12.8K) download
commit eb5ddc1d8909fe322ddeb1ec4bf9118bb9544667
Author: Jacob Champion <pchampion@vmware.com>
Date: Wed May 11 10:33:33 2022 -0700
squash! Log details for client certificate failures
- Add a maximum Subject length to prevent malicious client certs from
spamming the logs.
- Add the certificate serial number to the output, for disambiguation if
the Subject gets truncated unhelpfully.
diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.cindex 1683f9cc9e..3ccc23ba62 100644--- a/src/backend/libpq/be-secure-openssl.c+++ b/src/backend/libpq/be-secure-openssl.c@@ -1094,6 +1094,8 @@ verify_cb(int ok, X509_STORE_CTX *ctx)
const char *errstring;
X509 *cert;
char *certname = NULL;
+ char *truncated = NULL;+ char *serialno = NULL;
if (ok)
{
@@ -1108,14 +1110,56 @@ verify_cb(int ok, X509_STORE_CTX *ctx)
cert = X509_STORE_CTX_get_current_cert(ctx);
if (cert)
+ {+ size_t namelen;+ ASN1_INTEGER *sn;+ BIGNUM *b;++ /*+ * Get the Subject for logging, but don't let maliciously huge certs+ * flood the logs.+ *+ * Common Names are 64 chars max, so for a common case where the CN is+ * the last field, we can still print the longest possible CN with a+ * 7-character prefix (".../CN=[64 chars]"), for a reasonable limit of+ * 71 characters.+ */+#define MAXLEN 71
certname = X509_NAME_to_cstring(X509_get_subject_name(cert));
+ namelen = strlen(certname);++ if (namelen > MAXLEN)+ {+ /*+ * Keep the end of the Subject, not the beginning, since the most+ * specific field is likely to give users the most information.+ */+ truncated = certname + namelen - MAXLEN;+ truncated[0] = truncated[1] = truncated[2] = '.';+ }+#undef MAXLEN++ /*+ * Pull the serial number, too, in case a Subject is still ambiguous.+ * This mirrors be_tls_get_peer_serial().+ */+ sn = X509_get_serialNumber(cert);+ b = ASN1_INTEGER_to_BN(sn, NULL);+ serialno = BN_bn2dec(b);++ BN_free(b);+ }
ereport(COMMERROR,
(errmsg("client certificate verification failed at depth %d: %s",
depth, errstring),
/* only print detail if we have a certificate to print */
- certname && errdetail("failed certificate's subject: %s", certname)));+ certname && errdetail("failed certificate had subject '%s', serial number %s",+ truncated ? truncated : certname,+ serialno ? serialno : _("unknown"))));+ if (serialno)+ OPENSSL_free(serialno);
if (certname)
pfree(certname);
diff --git a/src/test/ssl/conf/client-long.config b/src/test/ssl/conf/client-long.confignew file mode 100644index 0000000000..0e92a8fbfe--- /dev/null+++ b/src/test/ssl/conf/client-long.config@@ -0,0 +1,14 @@+# An OpenSSL format CSR config file for creating a client certificate with a+# long Subject.++[ req ]+distinguished_name = req_distinguished_name+prompt = no++[ req_distinguished_name ]+# Common Names are 64 characters max+CN = ssl-123456789012345678901234567890123456789012345678901234567890+OU = Some Organizational Unit+O = PostgreSQL Global Development Group++# no extensions in client certsdiff --git a/src/test/ssl/ssl/client-long.crt b/src/test/ssl/ssl/client-long.crtnew file mode 100644index 0000000000..a1db55b5c3--- /dev/null+++ b/src/test/ssl/ssl/client-long.crt@@ -0,0 +1,69 @@+Certificate:+ Data:+ Version: 1 (0x0)+ Serial Number: 2315418733629425152 (0x2022051214444600)+ Signature Algorithm: sha256WithRSAEncryption+ Issuer: CN = Test CA for PostgreSQL SSL regression test client certs+ Validity+ Not Before: May 12 21:44:47 2022 GMT+ Not After : Sep 27 21:44:47 2049 GMT+ Subject: O = PostgreSQL Global Development Group, OU = Some Organizational Unit, CN = ssl-123456789012345678901234567890123456789012345678901234567890+ Subject Public Key Info:+ Public Key Algorithm: rsaEncryption+ RSA Public-Key: (2048 bit)+ Modulus:+ 00:d8:31:99:e1:e2:55:1b:81:4f:09:46:43:5a:0c:+ d8:cd:5c:91:00:88:fe:8e:21:61:c3:bd:05:87:71:+ 0d:81:e2:03:b8:f2:d5:65:5e:9f:28:fc:06:d5:22:+ e4:08:fd:54:38:69:7e:2b:9e:c0:36:ab:19:0e:5a:+ 4e:08:03:d6:93:23:93:0d:0c:a2:b0:4a:06:bf:7e:+ d6:ed:71:18:7f:fc:43:79:64:81:4f:8e:41:7a:cf:+ 82:5a:38:22:b5:5c:a9:aa:19:15:0d:27:b8:c6:95:+ 6e:27:97:d1:d0:f2:4d:fb:13:69:54:18:62:da:80:+ b7:38:48:fd:41:92:20:e8:64:db:e9:41:f5:f3:fa:+ f2:3c:3d:70:b1:f4:41:8b:d1:fa:a4:34:20:f1:b5:+ dc:8e:73:99:26:0f:32:3d:15:63:03:27:f5:31:7d:+ ff:6b:01:39:24:55:81:35:40:72:b6:20:39:02:e4:+ de:cf:df:19:ee:ba:b6:65:41:21:66:1c:ab:ae:72:+ 82:a0:f5:fb:07:ae:f8:f6:b1:8c:f9:f0:b1:e7:e4:+ 76:77:fa:25:d6:11:1b:51:75:0a:8e:e0:e7:6a:68:+ 3c:46:22:78:01:df:40:e2:7a:f6:c1:b4:2d:8c:74:+ 94:13:83:0b:af:6a:bd:22:78:59:d0:90:d3:32:b0:+ db:cf+ Exponent: 65537 (0x10001)+ Signature Algorithm: sha256WithRSAEncryption+ ae:be:6b:d5:4c:60:53:33:f2:92:6b:b9:65:d2:fa:cb:c4:c0:+ 65:b4:90:d7:20:58:d2:78:6c:47:04:64:0d:de:ba:88:f2:bd:+ 53:a4:fa:2b:6f:a9:2f:c5:5c:ea:2a:28:bf:d5:8e:b4:74:3a:+ a2:13:f7:81:26:af:77:8d:1c:1d:19:85:6a:ec:08:b1:9e:16:+ 93:49:a3:7e:da:4e:b8:f1:69:d6:1c:a8:f1:df:d0:62:b6:c4:+ 9b:7a:8d:7b:9a:a5:9f:94:bd:87:c8:a9:a1:8b:c5:b5:fe:73:+ 94:ad:8a:1c:91:73:f5:e8:59:31:9d:73:18:01:11:34:25:4c:+ f1:45:10:2b:25:2e:64:1e:46:ca:b6:65:6e:c9:5f:e8:ff:fd:+ 06:c7:39:e1:85:16:c4:fd:a9:af:9a:ff:44:9e:83:79:77:c8:+ cc:01:5f:5d:3f:00:15:59:42:94:04:40:f7:8f:60:a5:7d:0b:+ 56:b5:eb:c8:33:7a:d0:25:09:f3:c4:09:99:80:90:dc:0b:48:+ 83:36:18:7a:a7:1d:60:74:dd:f1:e4:b6:f4:fe:70:84:37:54:+ e4:db:d1:38:ff:8b:8c:44:de:45:e2:45:e0:17:f2:73:68:0c:+ ef:3c:59:0f:60:43:49:fe:5e:c6:f9:cd:aa:2c:b8:db:f9:51:+ d5:be:2c:cf+-----BEGIN CERTIFICATE-----+MIIDWjCCAkICCCAiBRIUREYAMA0GCSqGSIb3DQEBCwUAMEIxQDA+BgNVBAMMN1Rl+c3QgQ0EgZm9yIFBvc3RncmVTUUwgU1NMIHJlZ3Jlc3Npb24gdGVzdCBjbGllbnQg+Y2VydHMwHhcNMjIwNTEyMjE0NDQ3WhcNNDkwOTI3MjE0NDQ3WjCBnDEsMCoGA1UE+CgwjUG9zdGdyZVNRTCBHbG9iYWwgRGV2ZWxvcG1lbnQgR3JvdXAxITAfBgNVBAsM+GFNvbWUgT3JnYW5pemF0aW9uYWwgVW5pdDFJMEcGA1UEAwxAc3NsLTEyMzQ1Njc4+OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2+Nzg5MDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANgxmeHiVRuBTwlG+Q1oM2M1ckQCI/o4hYcO9BYdxDYHiA7jy1WVenyj8BtUi5Aj9VDhpfiuewDarGQ5a+TggD1pMjkw0MorBKBr9+1u1xGH/8Q3lkgU+OQXrPglo4IrVcqaoZFQ0nuMaVbieX+0dDyTfsTaVQYYtqAtzhI/UGSIOhk2+lB9fP68jw9cLH0QYvR+qQ0IPG13I5zmSYP+Mj0VYwMn9TF9/2sBOSRVgTVAcrYgOQLk3s/fGe66tmVBIWYcq65ygqD1+weu+Pax+jPnwsefkdnf6JdYRG1F1Co7g52poPEYieAHfQOJ69sG0LYx0lBODC69qvSJ4WdCQ+0zKw288CAwEAATANBgkqhkiG9w0BAQsFAAOCAQEArr5r1UxgUzPykmu5ZdL6y8TA+ZbSQ1yBY0nhsRwRkDd66iPK9U6T6K2+pL8Vc6ioov9WOtHQ6ohP3gSavd40cHRmF+auwIsZ4Wk0mjftpOuPFp1hyo8d/QYrbEm3qNe5qln5S9h8ipoYvFtf5zlK2KHJFz+9ehZMZ1zGAERNCVM8UUQKyUuZB5GyrZlbslf6P/9Bsc54YUWxP2pr5r/RJ6DeXfI+zAFfXT8AFVlClARA949gpX0LVrXryDN60CUJ88QJmYCQ3AtIgzYYeqcdYHTd8eS2+9P5whDdU5NvROP+LjETeReJF4Bfyc2gM7zxZD2BDSf5exvnNqiy42/lR1b4szw==+-----END CERTIFICATE-----diff --git a/src/test/ssl/ssl/client-long.key b/src/test/ssl/ssl/client-long.keynew file mode 100644index 0000000000..5b455a021f--- /dev/null+++ b/src/test/ssl/ssl/client-long.key@@ -0,0 +1,27 @@+-----BEGIN RSA PRIVATE KEY-----+MIIEpAIBAAKCAQEA2DGZ4eJVG4FPCUZDWgzYzVyRAIj+jiFhw70Fh3ENgeIDuPLV+ZV6fKPwG1SLkCP1UOGl+K57ANqsZDlpOCAPWkyOTDQyisEoGv37W7XEYf/xDeWSB+T45Bes+CWjgitVypqhkVDSe4xpVuJ5fR0PJN+xNpVBhi2oC3OEj9QZIg6GTb6UH1+8/ryPD1wsfRBi9H6pDQg8bXcjnOZJg8yPRVjAyf1MX3/awE5JFWBNUBytiA5AuTe+z98Z7rq2ZUEhZhyrrnKCoPX7B6749rGM+fCx5+R2d/ol1hEbUXUKjuDnamg8RiJ4+Ad9A4nr2wbQtjHSUE4MLr2q9InhZ0JDTMrDbzwIDAQABAoIBADwJykpIqIny5xgU+QzAG0U52nm4fnVGrQ5MwMxDh/HZNZes+xLRaCqk/FEasYdd9Qp5H7Zn/hDGqYlLy+ESl4p2ZFQtkk4SlD5YvYladq+PrR+4sCtkZ5owWQCwsy+7CSAywRux7kIRRE+0pT+hxkXsUBAq8eG3i0AAeHHo01KX4kptlJ5d1pFKKAPThTUHCT4VPHg8r59IdsNy6wC++0E5ZRWsVUePy+ERuarX/um896hgbaiDJLFk02Orlc87+OBmRwO8J+KoUOEcAiTO+OZqGGaDEn5Y2mEdp2cCmq7+Izcklaha6CPsoV8+O2HK8PKvBIQmlgbDmal4/RNqr+JFqYz0ECgYEA+5z74Tmj+tzH57lcdMqVpndG39N8spBe8JbiFL16qOb6gRDytXjc+hY6IQo4JStpJulnPBZ5JQSbSBgCOzYWJJVBnnwMJKjNCd1th4znjxxMOe4LiDTtw+D3hQtzBU9FlI2sjWEUKf1xCyi9N41ApQC5eDWWd/0GN9+xAsxRjLL00CgYEA2/aH+4kNVsBHQ7vmv+sNsWeIgKg7PC7hRjcCYQG9ylBbBnFtv5XJYicXwqorqngzJPoGw+gB7iaSWL1UNAOSWRSFYe+woPpkY7n6Pbq211nzqV1avAdVrLylJwyE+EOQgTS30D+8BHv0I714PMd/QLK5NSUEr1IRtCfLeMpcSg6YYsCgYEAv3O86KxeTMTvyy9s3WVE+p4y8vhUDHi/iPbjhQBzJF3nhhJGrzE+xpGJG5jWDdpRQY15wuvqtDMkIKA8GmfWQ+3Hao0gKSV6z3VzCOdEKZQeILNAnsDVt7shm/eRRqoB7L48XLtQh37UJESUbY+qb6+L0fTZxTs2VjLBF1TY4mxGUUCgYEA1PLENKnJkA5/fowd8aA2CoKfbvgtPARyd9Bn+1aHPhEzPnabsGm7sBl2qFAEvCFoKjkgR7sd3nCHsUUetKmYTU7uEfLcN1YSS/oct+CLaMs92M53JCfZqsRrAvXc2VjX0i6Ocb49QJnph4tBHKC4MjmAuxWr8C9QPNxyfv+nAw9EOcCgYBYzejUzp6xiv5YzpwIncIF0A5E6VITcsW+LOR/FZOUPso0X2hQoIEs+wx8HjKCGfvX6628vnaWJC099hTmOzVwpEgik5zOmeAmZ//gt2I53Yg/loQUzH0CD+iXxrg/4Up7Yxx897w11ukOZv2xwmAFO1o52Q8k7d5FiMfEIzAkS3Pg==+-----END RSA PRIVATE KEY-----diff --git a/src/test/ssl/sslfiles.mk b/src/test/ssl/sslfiles.mkindex cc023667af..5f67aba795 100644--- a/src/test/ssl/sslfiles.mk+++ b/src/test/ssl/sslfiles.mk@@ -33,7 +33,7 @@ SERVERS := server-cn-and-alt-names \
server-multiple-alt-names \
server-no-names \
server-revoked
-CLIENTS := client client-dn client-revoked client_ext+CLIENTS := client client-dn client-revoked client_ext client-long
#
# To add a new non-standard key, add it to SPECIAL_KEYS and then add a recipe
diff --git a/src/test/ssl/t/001_ssltests.pl b/src/test/ssl/t/001_ssltests.plindex ecc7bd2bce..4c7a8bd7a2 100644--- a/src/test/ssl/t/001_ssltests.pl+++ b/src/test/ssl/t/001_ssltests.pl@@ -668,7 +668,7 @@ $node->connect_fails(
expected_stderr => qr/SSL error: sslv3 alert certificate revoked/,
log_like => [
qr/client certificate verification failed at depth 0: certificate revoked/,
- qr/failed certificate's subject: \/CN=ssltestuser/,+ qr/failed certificate had subject '\/CN=ssltestuser', serial number 2315134995201656577/,
],
# revoked certificates should not authenticate the user
log_unlike => [qr/connection authenticated:/],);
@@ -715,7 +715,16 @@ $node->connect_fails(
expected_stderr => qr/SSL error: tlsv1 alert unknown ca/,
log_like => [
qr/client certificate verification failed at depth 0: unable to get local issuer certificate/,
- qr/failed certificate's subject: \/CN=ssltestuser/,+ qr/failed certificate had subject '\/CN=ssltestuser', serial number 2315134995201656576/,+ ]);++$node->connect_fails(+ "$common_connstr sslmode=require sslcert=ssl/client-long.crt " . sslkey('client-long.key'),+ "logged client certificate Subjects are truncated if they're too long",+ expected_stderr => qr/SSL error: tlsv1 alert unknown ca/,+ log_like => [+ qr/client certificate verification failed at depth 0: unable to get local issuer certificate/,+ qr/failed certificate had subject '\.\.\.\/CN=ssl-123456789012345678901234567890123456789012345678901234567890', serial number 2315418733629425152/,
]);
# Use an invalid cafile here so that the next test won't be able to verify the
@@ -730,7 +739,7 @@ $node->connect_fails(
expected_stderr => qr/SSL error: tlsv1 alert unknown ca/,
log_like => [
qr/client certificate verification failed at depth 1: unable to get local issuer certificate/,
- qr/failed certificate's subject: \/CN=Test CA for PostgreSQL SSL regression test client certs/,+ qr/failed certificate had subject '\/CN=Test CA for PostgreSQL SSL regression test client certs', serial number 2315134995201656577/,
]);
# test server-side CRL directory
@@ -743,7 +752,7 @@ $node->connect_fails(
expected_stderr => qr/SSL error: sslv3 alert certificate revoked/,
log_like => [
qr/client certificate verification failed at depth 0: certificate revoked/,
- qr/failed certificate's subject: \/CN=ssltestuser/,+ qr/failed certificate had subject '\/CN=ssltestuser', serial number 2315134995201656577/,
]);
done_testing();
diff --git a/src/test/ssl/t/SSL/Backend/OpenSSL.pm b/src/test/ssl/t/SSL/Backend/OpenSSL.pmindex 1546b5081b..cdfd14fcdf 100644--- a/src/test/ssl/t/SSL/Backend/OpenSSL.pm+++ b/src/test/ssl/t/SSL/Backend/OpenSSL.pm@@ -88,7 +88,7 @@ sub init
"client.key", "client-revoked.key",
"client-der.key", "client-encrypted-pem.key",
"client-encrypted-der.key", "client-dn.key",
- "client_ext.key");+ "client_ext.key", "client-long.key");
foreach my $keyfile (@keys)
{
copy("ssl/$keyfile", "$cert_tempdir/$keyfile")
v2-0001-Log-details-for-client-certificate-failures.patch (text/x-patch, 13.2K) download
From 71148b4a38d459ca86d8637577c60b8cae568242 Mon Sep 17 00:00:00 2001
From: Jacob Champion <pchampion@vmware.com>
Date: Mon, 29 Mar 2021 10:07:31 -0700
Subject: [PATCH v2] Log details for client certificate failures
Currently, debugging client cert verification failures is mostly limited
to looking at the TLS alert code on the client side. For simple
deployments, sometimes it's enough to see "sslv3 alert certificate
revoked" and know exactly what needs to be fixed, but if you add any
more complexity (multiple CA layers, misconfigured CA certificates,
etc.), trying to debug what happened based on the TLS alert alone can be
an exercise in frustration.
Luckily, the server has more information about exactly what failed in
the chain, and we already have the requisite callback implemented as a
stub. Fill it out with error handling and add a COMMERROR log so that a
DBA can debug client failures more easily. It ends up looking like
LOG: connection received: host=localhost port=44120
LOG: client certificate verification failed at depth 1: unable to get local issuer certificate
DETAIL: failed certificate had subject '/CN=Test CA for PostgreSQL SSL regression test client certs', serial number 2315134995201656577
LOG: could not accept SSL connection: certificate verify failed
The printed Subject's length is limited to prevent malicious client
certs from spamming the logs. In case the truncation makes things
ambiguous, the certificate's serial number is also logged.
---
src/backend/libpq/be-secure-openssl.c | 77 ++++++++++++++++++++++++++-
src/test/ssl/conf/client-long.config | 14 +++++
src/test/ssl/ssl/client-long.crt | 20 +++++++
src/test/ssl/ssl/client-long.key | 27 ++++++++++
src/test/ssl/sslfiles.mk | 2 +-
src/test/ssl/t/001_ssltests.pl | 40 +++++++++++++-
src/test/ssl/t/SSL/Backend/OpenSSL.pm | 2 +-
7 files changed, 176 insertions(+), 6 deletions(-)
create mode 100644 src/test/ssl/conf/client-long.config
create mode 100644 src/test/ssl/ssl/client-long.crt
create mode 100644 src/test/ssl/ssl/client-long.key
diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.cindex 3d0168a369..3ccc23ba62 100644--- a/src/backend/libpq/be-secure-openssl.c+++ b/src/backend/libpq/be-secure-openssl.c@@ -1080,8 +1080,7 @@ dummy_ssl_passwd_cb(char *buf, int size, int rwflag, void *userdata)
* Certificate verification callback
*
* This callback allows us to log intermediate problems during
- * verification, but for now we'll see if the final error message- * contains enough information.+ * verification.
*
* This callback also allows us to override the default acceptance
* criteria (e.g., accepting self-signed or expired certs), but
@@ -1090,6 +1089,80 @@ dummy_ssl_passwd_cb(char *buf, int size, int rwflag, void *userdata)
static int
verify_cb(int ok, X509_STORE_CTX *ctx)
{
+ int depth;+ int errcode;+ const char *errstring;+ X509 *cert;+ char *certname = NULL;+ char *truncated = NULL;+ char *serialno = NULL;++ if (ok)+ {+ /* Nothing to do for the successful case. */+ return ok;+ }++ /* Pull all the information we have on the verification failure. */+ depth = X509_STORE_CTX_get_error_depth(ctx);+ errcode = X509_STORE_CTX_get_error(ctx);+ errstring = X509_verify_cert_error_string(errcode);++ cert = X509_STORE_CTX_get_current_cert(ctx);+ if (cert)+ {+ size_t namelen;+ ASN1_INTEGER *sn;+ BIGNUM *b;++ /*+ * Get the Subject for logging, but don't let maliciously huge certs+ * flood the logs.+ *+ * Common Names are 64 chars max, so for a common case where the CN is+ * the last field, we can still print the longest possible CN with a+ * 7-character prefix (".../CN=[64 chars]"), for a reasonable limit of+ * 71 characters.+ */+#define MAXLEN 71+ certname = X509_NAME_to_cstring(X509_get_subject_name(cert));+ namelen = strlen(certname);++ if (namelen > MAXLEN)+ {+ /*+ * Keep the end of the Subject, not the beginning, since the most+ * specific field is likely to give users the most information.+ */+ truncated = certname + namelen - MAXLEN;+ truncated[0] = truncated[1] = truncated[2] = '.';+ }+#undef MAXLEN++ /*+ * Pull the serial number, too, in case a Subject is still ambiguous.+ * This mirrors be_tls_get_peer_serial().+ */+ sn = X509_get_serialNumber(cert);+ b = ASN1_INTEGER_to_BN(sn, NULL);+ serialno = BN_bn2dec(b);++ BN_free(b);+ }++ ereport(COMMERROR,+ (errmsg("client certificate verification failed at depth %d: %s",+ depth, errstring),+ /* only print detail if we have a certificate to print */+ certname && errdetail("failed certificate had subject '%s', serial number %s",+ truncated ? truncated : certname,+ serialno ? serialno : _("unknown"))));++ if (serialno)+ OPENSSL_free(serialno);+ if (certname)+ pfree(certname);+
return ok;
}
diff --git a/src/test/ssl/conf/client-long.config b/src/test/ssl/conf/client-long.confignew file mode 100644index 0000000000..0e92a8fbfe--- /dev/null+++ b/src/test/ssl/conf/client-long.config@@ -0,0 +1,14 @@+# An OpenSSL format CSR config file for creating a client certificate with a+# long Subject.++[ req ]+distinguished_name = req_distinguished_name+prompt = no++[ req_distinguished_name ]+# Common Names are 64 characters max+CN = ssl-123456789012345678901234567890123456789012345678901234567890+OU = Some Organizational Unit+O = PostgreSQL Global Development Group++# no extensions in client certsdiff --git a/src/test/ssl/ssl/client-long.crt b/src/test/ssl/ssl/client-long.crtnew file mode 100644index 0000000000..a1db55b5c3--- /dev/null+++ b/src/test/ssl/ssl/client-long.crt@@ -0,0 +1,20 @@+-----BEGIN CERTIFICATE-----+MIIDWjCCAkICCCAiBRIUREYAMA0GCSqGSIb3DQEBCwUAMEIxQDA+BgNVBAMMN1Rl+c3QgQ0EgZm9yIFBvc3RncmVTUUwgU1NMIHJlZ3Jlc3Npb24gdGVzdCBjbGllbnQg+Y2VydHMwHhcNMjIwNTEyMjE0NDQ3WhcNNDkwOTI3MjE0NDQ3WjCBnDEsMCoGA1UE+CgwjUG9zdGdyZVNRTCBHbG9iYWwgRGV2ZWxvcG1lbnQgR3JvdXAxITAfBgNVBAsM+GFNvbWUgT3JnYW5pemF0aW9uYWwgVW5pdDFJMEcGA1UEAwxAc3NsLTEyMzQ1Njc4+OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2+Nzg5MDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANgxmeHiVRuBTwlG+Q1oM2M1ckQCI/o4hYcO9BYdxDYHiA7jy1WVenyj8BtUi5Aj9VDhpfiuewDarGQ5a+TggD1pMjkw0MorBKBr9+1u1xGH/8Q3lkgU+OQXrPglo4IrVcqaoZFQ0nuMaVbieX+0dDyTfsTaVQYYtqAtzhI/UGSIOhk2+lB9fP68jw9cLH0QYvR+qQ0IPG13I5zmSYP+Mj0VYwMn9TF9/2sBOSRVgTVAcrYgOQLk3s/fGe66tmVBIWYcq65ygqD1+weu+Pax+jPnwsefkdnf6JdYRG1F1Co7g52poPEYieAHfQOJ69sG0LYx0lBODC69qvSJ4WdCQ+0zKw288CAwEAATANBgkqhkiG9w0BAQsFAAOCAQEArr5r1UxgUzPykmu5ZdL6y8TA+ZbSQ1yBY0nhsRwRkDd66iPK9U6T6K2+pL8Vc6ioov9WOtHQ6ohP3gSavd40cHRmF+auwIsZ4Wk0mjftpOuPFp1hyo8d/QYrbEm3qNe5qln5S9h8ipoYvFtf5zlK2KHJFz+9ehZMZ1zGAERNCVM8UUQKyUuZB5GyrZlbslf6P/9Bsc54YUWxP2pr5r/RJ6DeXfI+zAFfXT8AFVlClARA949gpX0LVrXryDN60CUJ88QJmYCQ3AtIgzYYeqcdYHTd8eS2+9P5whDdU5NvROP+LjETeReJF4Bfyc2gM7zxZD2BDSf5exvnNqiy42/lR1b4szw==+-----END CERTIFICATE-----diff --git a/src/test/ssl/ssl/client-long.key b/src/test/ssl/ssl/client-long.keynew file mode 100644index 0000000000..5b455a021f--- /dev/null+++ b/src/test/ssl/ssl/client-long.key@@ -0,0 +1,27 @@+-----BEGIN RSA PRIVATE KEY-----+MIIEpAIBAAKCAQEA2DGZ4eJVG4FPCUZDWgzYzVyRAIj+jiFhw70Fh3ENgeIDuPLV+ZV6fKPwG1SLkCP1UOGl+K57ANqsZDlpOCAPWkyOTDQyisEoGv37W7XEYf/xDeWSB+T45Bes+CWjgitVypqhkVDSe4xpVuJ5fR0PJN+xNpVBhi2oC3OEj9QZIg6GTb6UH1+8/ryPD1wsfRBi9H6pDQg8bXcjnOZJg8yPRVjAyf1MX3/awE5JFWBNUBytiA5AuTe+z98Z7rq2ZUEhZhyrrnKCoPX7B6749rGM+fCx5+R2d/ol1hEbUXUKjuDnamg8RiJ4+Ad9A4nr2wbQtjHSUE4MLr2q9InhZ0JDTMrDbzwIDAQABAoIBADwJykpIqIny5xgU+QzAG0U52nm4fnVGrQ5MwMxDh/HZNZes+xLRaCqk/FEasYdd9Qp5H7Zn/hDGqYlLy+ESl4p2ZFQtkk4SlD5YvYladq+PrR+4sCtkZ5owWQCwsy+7CSAywRux7kIRRE+0pT+hxkXsUBAq8eG3i0AAeHHo01KX4kptlJ5d1pFKKAPThTUHCT4VPHg8r59IdsNy6wC++0E5ZRWsVUePy+ERuarX/um896hgbaiDJLFk02Orlc87+OBmRwO8J+KoUOEcAiTO+OZqGGaDEn5Y2mEdp2cCmq7+Izcklaha6CPsoV8+O2HK8PKvBIQmlgbDmal4/RNqr+JFqYz0ECgYEA+5z74Tmj+tzH57lcdMqVpndG39N8spBe8JbiFL16qOb6gRDytXjc+hY6IQo4JStpJulnPBZ5JQSbSBgCOzYWJJVBnnwMJKjNCd1th4znjxxMOe4LiDTtw+D3hQtzBU9FlI2sjWEUKf1xCyi9N41ApQC5eDWWd/0GN9+xAsxRjLL00CgYEA2/aH+4kNVsBHQ7vmv+sNsWeIgKg7PC7hRjcCYQG9ylBbBnFtv5XJYicXwqorqngzJPoGw+gB7iaSWL1UNAOSWRSFYe+woPpkY7n6Pbq211nzqV1avAdVrLylJwyE+EOQgTS30D+8BHv0I714PMd/QLK5NSUEr1IRtCfLeMpcSg6YYsCgYEAv3O86KxeTMTvyy9s3WVE+p4y8vhUDHi/iPbjhQBzJF3nhhJGrzE+xpGJG5jWDdpRQY15wuvqtDMkIKA8GmfWQ+3Hao0gKSV6z3VzCOdEKZQeILNAnsDVt7shm/eRRqoB7L48XLtQh37UJESUbY+qb6+L0fTZxTs2VjLBF1TY4mxGUUCgYEA1PLENKnJkA5/fowd8aA2CoKfbvgtPARyd9Bn+1aHPhEzPnabsGm7sBl2qFAEvCFoKjkgR7sd3nCHsUUetKmYTU7uEfLcN1YSS/oct+CLaMs92M53JCfZqsRrAvXc2VjX0i6Ocb49QJnph4tBHKC4MjmAuxWr8C9QPNxyfv+nAw9EOcCgYBYzejUzp6xiv5YzpwIncIF0A5E6VITcsW+LOR/FZOUPso0X2hQoIEs+wx8HjKCGfvX6628vnaWJC099hTmOzVwpEgik5zOmeAmZ//gt2I53Yg/loQUzH0CD+iXxrg/4Up7Yxx897w11ukOZv2xwmAFO1o52Q8k7d5FiMfEIzAkS3Pg==+-----END RSA PRIVATE KEY-----diff --git a/src/test/ssl/sslfiles.mk b/src/test/ssl/sslfiles.mkindex cc023667af..5f67aba795 100644--- a/src/test/ssl/sslfiles.mk+++ b/src/test/ssl/sslfiles.mk@@ -33,7 +33,7 @@ SERVERS := server-cn-and-alt-names \
server-multiple-alt-names \
server-no-names \
server-revoked
-CLIENTS := client client-dn client-revoked client_ext+CLIENTS := client client-dn client-revoked client_ext client-long
#
# To add a new non-standard key, add it to SPECIAL_KEYS and then add a recipe
diff --git a/src/test/ssl/t/001_ssltests.pl b/src/test/ssl/t/001_ssltests.plindex 58d2bc336f..4c7a8bd7a2 100644--- a/src/test/ssl/t/001_ssltests.pl+++ b/src/test/ssl/t/001_ssltests.pl@@ -666,6 +666,10 @@ $node->connect_fails(
"$common_connstr user=ssltestuser sslcert=ssl/client-revoked.crt " . sslkey('client-revoked.key'),
"certificate authorization fails with revoked client cert",
expected_stderr => qr/SSL error: sslv3 alert certificate revoked/,
+ log_like => [+ qr/client certificate verification failed at depth 0: certificate revoked/,+ qr/failed certificate had subject '\/CN=ssltestuser', serial number 2315134995201656577/,+ ],
# revoked certificates should not authenticate the user
log_unlike => [qr/connection authenticated:/],);
@@ -708,7 +712,35 @@ $node->connect_ok(
$node->connect_fails(
$common_connstr . " " . "sslmode=require sslcert=ssl/client.crt",
"intermediate client certificate is missing",
- expected_stderr => qr/SSL error: tlsv1 alert unknown ca/);+ expected_stderr => qr/SSL error: tlsv1 alert unknown ca/,+ log_like => [+ qr/client certificate verification failed at depth 0: unable to get local issuer certificate/,+ qr/failed certificate had subject '\/CN=ssltestuser', serial number 2315134995201656576/,+ ]);++$node->connect_fails(+ "$common_connstr sslmode=require sslcert=ssl/client-long.crt " . sslkey('client-long.key'),+ "logged client certificate Subjects are truncated if they're too long",+ expected_stderr => qr/SSL error: tlsv1 alert unknown ca/,+ log_like => [+ qr/client certificate verification failed at depth 0: unable to get local issuer certificate/,+ qr/failed certificate had subject '\.\.\.\/CN=ssl-123456789012345678901234567890123456789012345678901234567890', serial number 2315418733629425152/,+ ]);++# Use an invalid cafile here so that the next test won't be able to verify the+# client CA.+switch_server_cert($node, certfile => 'server-cn-only', cafile => 'server-cn-only');++# intermediate CA is provided but doesn't have a trusted root (checks error+# logging for cert chain depths > 0)+$node->connect_fails(+ "$common_connstr sslmode=require sslcert=ssl/client+client_ca.crt",+ "intermediate client certificate is untrusted",+ expected_stderr => qr/SSL error: tlsv1 alert unknown ca/,+ log_like => [+ qr/client certificate verification failed at depth 1: unable to get local issuer certificate/,+ qr/failed certificate had subject '\/CN=Test CA for PostgreSQL SSL regression test client certs', serial number 2315134995201656577/,+ ]);
# test server-side CRL directory
switch_server_cert($node, certfile => 'server-cn-only', crldir => 'root+client-crldir');
@@ -717,6 +749,10 @@ switch_server_cert($node, certfile => 'server-cn-only', crldir => 'root+client-c
$node->connect_fails(
"$common_connstr user=ssltestuser sslcert=ssl/client-revoked.crt " . sslkey('client-revoked.key'),
"certificate authorization fails with revoked client cert with server-side CRL directory",
- expected_stderr => qr/SSL error: sslv3 alert certificate revoked/);+ expected_stderr => qr/SSL error: sslv3 alert certificate revoked/,+ log_like => [+ qr/client certificate verification failed at depth 0: certificate revoked/,+ qr/failed certificate had subject '\/CN=ssltestuser', serial number 2315134995201656577/,+ ]);
done_testing();
diff --git a/src/test/ssl/t/SSL/Backend/OpenSSL.pm b/src/test/ssl/t/SSL/Backend/OpenSSL.pmindex 1546b5081b..cdfd14fcdf 100644--- a/src/test/ssl/t/SSL/Backend/OpenSSL.pm+++ b/src/test/ssl/t/SSL/Backend/OpenSSL.pm@@ -88,7 +88,7 @@ sub init
"client.key", "client-revoked.key",
"client-der.key", "client-encrypted-pem.key",
"client-encrypted-der.key", "client-dn.key",
- "client_ext.key");+ "client_ext.key", "client-long.key");
foreach my $keyfile (@keys)
{
copy("ssl/$keyfile", "$cert_tempdir/$keyfile")
--
2.25.1
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: pgsql-hackers@postgresql.org
Cc: pchampion@vmware.com, peter.eisentraut@enterprisedb.com
Subject: Re: [PATCH] Log details for client certificate failures
In-Reply-To: <9b8338210b865d79239ec35ca523792ce331c0a3.camel@vmware.com>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by DDX for PostgreSQL; see mirroring instructions
for how to clone and mirror all data and code used for this inbox