Java, I’m looking at you (though Chrome will get glared at as well).
The most tedious TLS rabbit holes are the ones that relate to inconsistencies between TLS clients. A certificate will work in most cases, and then one client will fail, and then down the rabbit hole you go, waving to a Cheshire cat along the way.
A quick diversion.
For example: Chrome/Chromium (since v58) does not support certificates without Subject Alternative Names (SANs). If your web server’s DNS record is in the Common Name, but you have no SAN as well, Chrome will generate NET::ERR_CERT_COMMON_NAME_INVALID
.
RFC6125 states clients ‘MAY as a last resort check’ the Common Name. It also states no client should check the common name if there are SANs present, so Chrome’s decision to do this had/has the effect of deprecating use of the Common Name. Other browsers, eg Firefox, are happy to use Common Name.
Version 3 extensions in version 1 certificates.
Another tedious thing in general is error messages that are almost entirely useless.
Error obtaining access token. Cannot access https://server.example.com from Jira.
I expected TLS issues, as it’s a private CA. The means, for Jira, adding the root CA to the JDK’s cacerts
trust store. In practice, I copied the original trust store, added the root to the copy, and directed the JDK to the modified one with -Djavax.net.ssl.trustStore=
.
I proved with curl that there’s no basic connectivity issue, and then I upped my game to use the ‘right’ client:
$ /opt/java/openjdk/bin/java -Djavax.net.ssl.trustStore=./cacerts SSLPoke server.example.com 443 java.security.cert.CertificateParsingException: no more data allowed for version 1 certificate at java.base/sun.security.x509.X509CertInfo.parse(X509CertInfo.java:679) at java.base/sun.security.x509.X509CertInfo.(X509CertInfo.java:169) at java.base/sun.security.x509.X509CertImpl.parse(X509CertImpl.java:1842) at java.base/sun.security.x509.X509CertImpl.(X509CertImpl.java:194) [snip]
(Atlassian have a copy of the class linked off their knowledge base)
The problem, thank $deity, is in the server certificate, and not the root.
$ openssl s_client -connect server.example.com:443 2>/dev/null | openssl x509 -noout -text Certificate: Data: Version: 1 (0x0) [snip] X509v3 extensions: X509v3 Subject Alternative Name:
SANs are not a version 1 feature. But Java is the first client I’ve encountered that cared.
My CA is Openssl based. I saw a comment on stack overflow or somewhere that the internet has instructions for how to do Openssl CAs wrong in this particular way.
I seem to have the fix already, somewhere ..
$ openssl x509 -noout -text -in root.cert.pem Certificate: Data: Version: 3 (0x2) [snip]
openssl fix
Kudos to garethTheRed and dave_thompson_085 on Stack exchange as their answers kept popping up in the relevant questions, and Gareth posted about the bug and a workaround as well.
The theory states that if openssl is properly instructed to put v3 extensions in certificates, it’ll make v3 certificates.
My CA has an Openssl configuration, and the key parameter is:
[ ca ] default_ca = CA_default [ CA_default ] [snip] copy_extensions = copy
This is the same as putting copy_extensions
in the ca
section, and from the comments I know I added it specifically because SANs were not being added.
It seems that there was a bug for a while in openssl, and RHEL7’s openssl has it, still.
$ openssl version OpenSSL 1.0.2k-fips 26 Jan 2017
The workaround is to make it explicit that V3 extensions are being added by adding an additional parameter and a dummy section.
copy_extensions = copy x509_extensions = cert_ext [ cert_ext ] [ policy_strict ]
Boom!
$ openssl x509 -text -noout -in server.example.com.cert.pem Certificate: Data: Version: 3 (0x2) [snip]
SSLPoke?
Successfully connected
Jira?
Error! Failed adding the account: [Error retrieving list of repositories]
One rabbit hole down .. another to go.