Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to list certificates, trusted by OpenSSL?

As I understand, any software working with X.509 certificates may have own basis to decide, whether a certificate is trusted or not.

AFAIK OpenSSL just consults a list (such as, for example, /etc/ssl/certs) and checks if the certificate is present there.

Is there a way for OpenSSL to list all certificates which it trusts? I know that I can consult that file myself (on my particular installation of OpenSSL), but is there a (installation-independent) way to get the trusted list from OpenSSL itself?

like image 308
Konstantin Shemyak Avatar asked Aug 06 '14 09:08

Konstantin Shemyak


3 Answers

AFAIK OpenSSL just consults a list (such as, for example, /etc/ssl/certs) and checks if the certificate is present there.

No, OpenSSL trusts nothing by default. You have to instruct it what to trust. There's even a FAQ topic covering it: Why does <SSL program> fail with a certificate verify error?:

This problem is usually indicated by log messages saying something like "unable to get local issuer certificate" or "self signed certificate". When a certificate is verified its root CA must be "trusted" by OpenSSL this typically means that the CA certificate must be placed in a directory or file and the relevant program configured to read it. The OpenSSL program 'verify' behaves in a similar way and issues similar error messages: check the verify(1) program manual page for more information.

You can also test your connection to Google to see how OpenSSL behaves:

$ openssl s_client -connect google.com:443
CONNECTED(00000003)
depth=2 C = US, O = GeoTrust Inc., CN = GeoTrust Global CA
verify error:num=20:unable to get local issuer certificate
verify return:0
...
Start Time: 1407377002
Timeout   : 300 (sec)
Verify return code: 20 (unable to get local issuer certificate)

Notice the above fails because OpenSSL does not trust GeoTrust Global CA by default. Actually, there's another trust point in the chain and that's Google Internet Authority G2.

You can remedy the situation by telling OpenSSL what to trust. Below, I use -CAfile option with Google Internet Authority G2:

$ openssl s_client -connect google.com:443 -CAfile google-ca.pem 
CONNECTED(00000003)
depth=3 C = US, O = Equifax, OU = Equifax Secure Certificate Authority
verify return:1
depth=2 C = US, O = GeoTrust Inc., CN = GeoTrust Global CA
verify return:1
depth=1 C = US, O = Google Inc, CN = Google Internet Authority G2
verify return:1
depth=0 C = US, ST = California, L = Mountain View, O = Google Inc, CN = google.com
verify return:1
...
Start Time: 1407377196
Timeout   : 300 (sec)
Verify return code: 0 (ok)

Next, you can act like a browser by going to cURL and download cacert.pem. cacert.pem has lots of CAs in it:

$ openssl s_client -connect google.com:443 -CAfile cacert.pem 
CONNECTED(00000003)
depth=3 C = US, O = Equifax, OU = Equifax Secure Certificate Authority
verify return:1
depth=2 C = US, O = GeoTrust Inc., CN = GeoTrust Global CA
verify return:1
depth=1 C = US, O = Google Inc, CN = Google Internet Authority G2
verify return:1
depth=0 C = US, ST = California, L = Mountain View, O = Google Inc, CN = google.com
verify return:1
...
Start Time: 1407377356
Timeout   : 300 (sec)
Verify return code: 0 (ok)

You're not quite as bad as a browser with its hundreds of CAs and subordinate CAs, but you're getting close:

$ cat cacert.pem | grep -o "\-\-\-\-\-BEGIN" | wc -l
     153

OpenSSL security model is in contrast to the web app/browser security model, where the browser carries around a list of trust anchors or trust points known as Certificate Authorities (CAs). Note: in this model, the wrong CA could claim to certify a site, and the browser would be no wiser.

This has happened in the past, and it will likely happen again in the future. For a good history of PKIX funny business, see CAcert's Risk History. For example, you know Google Internet Authority G2 and GeoTrust Global CA certify Google's sites. There's no reason for a Dutch CA called Diginotar to claim to certify them, or a French Cyberdefense Agency to claim to certify them.

Related to security models: another problem with the web app/browser model is you cannot package the one trust anchor or CA needed for your app and use it (assuming you have a trusted distribution channel). Your certificates gets tossed in the pile with the CA Zoo. Others can still claim to certify your site, and you can claim to certify other sites.

The security model one of the reasons web apps are relegated to low value data. Web apps should not handle medium value or high value data because we can't place the needed security controls.


Is there a way for OpenSSL to list all certificates which it trusts?

No need since the list has 0 members :)


Also see How to find out the path for openssl trusted certificate?.

like image 139
jww Avatar answered Oct 25 '22 18:10

jww


I recently looked into this, and found no way to get OpenSSL to list the certificates in its trusted set. The best way I found was to, as you point out, "consult that file [/etc/ssl/certs] myself (on my particular installation of OpenSSL)".

You can be more installation-independent about finding the directory which OpenSSL consults. openssl version -d prints the path to it.

% openssl version -d
OPENSSLDIR: "/opt/local/etc/openssl"

OpenSSL looks here for a file named cert.pem and a subdirectory certs/. Certificates it finds there are treated as trusted by openssl s_client and openssl verify (source: the article, What certificate authorities does OpenSSL recognize?).

So, you can do something like:

% find -H `openssl version -d | sed -E 's/OPENSSLDIR: "([^"]*)"/\1/'`/(cert.pem|certs) \ 
-type f -exec cat {} \+  

This prints out the entire contents of the files which OpenSSL expects to contain certificates. If you want less than the entire file, then replace cat with the appropriate commands.

like image 39
Jim DeLaHunt Avatar answered Oct 25 '22 18:10

Jim DeLaHunt


I'm wonder if this has changed in some way since jww's response.

If I submit: $ openssl s_client -connect google.com:443

It works successfully, retrieves 4 total certs, and returns:

Start Time: 1484661709
Timeout   : 300 (sec)
Verify return code: 0 (ok)

I believe this is because servers should be setup to send, along with the certificate, any intermediate and root certificates that are needed to verify the full chain, right?

like image 32
em_bo Avatar answered Oct 25 '22 17:10

em_bo