26

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?

Konstantin Shemyak
  • 2,369
  • 5
  • 21
  • 41

4 Answers4

22

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?.

Community
  • 1
  • 1
jww
  • 97,681
  • 90
  • 411
  • 885
  • 9
    OpenSSL certainly trusts certain certificates "automatically": any which are found in the "Directory for OpenSSL files", in either a file named `cert.pem` or in the subdirectory `certs/`. Source: [_What certificate authorities does OpenSSL recognize?_](https://www.madboa.com/geek/openssl/#what-certificate-authorities-does-openssl-recognize). Now, it may be that your installation has nothing in this directory, but my installation has a `cert.pem` symlinked to a collection of root Certificate Authority certificates, so my OpenSSL installation trusts many sites "automatically". – Jim DeLaHunt Dec 18 '17 at 08:36
  • 2
    This answer is technically correct, but inaccurate for nearly any actual use of OpenSSL. From a below comment: " If you install OpenSSL from source, you won't have installed any trusted certificate store. If you use your distro's package manager, distro packaging probably includes a dependency on whatever bundle of certificates the distro maintainers have decided to trust, so you do get a populated trust store." Since SSL/TLS is fairly useless if you don't know what root certs to trust, nearly any actual installation of OpenSSL will be configured with trusted root certs. – Jens Alfke Jul 08 '19 at 22:38
  • 2
    "No need" is a bad answer. Would like to see actual answer to this question – Alex Jun 10 '20 at 05:36
21

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.

Jim DeLaHunt
  • 10,960
  • 3
  • 45
  • 74
  • 1
    find -H `openssl version -d | sed -E 's/OPENSSLDIR: "([^"]*)"/\1/'`/(cert.pem|certs) \ -type f -exec cat {} \+ is not valid command – Ibrahim Magdy Oct 25 '21 at 22:56
  • @IbrahimMagdy the `find -H` command you posted lacks the back-ticks `` of the command in my answer. I just tested the command in my answer, with back-ticks, on macOS 10.14.6. It worked as expected. On what system did you test it? What was your result? Perhaps you should post your own StackOverflow question about what did not work for you. – Jim DeLaHunt Oct 26 '21 at 23:14
  • @JimDeLaHunt I actually run into the error myself on a RHEL Linux machine. On macOS, are you using bash or zsh? Not sure that if may be it OR minor differences in macOS (Darwin)'s `find` and the command on Linux. Also I think @IbrahimMagdy's post did have the back tics, but markdown escaped them as code rather than showing the back ticks. – Sir CodesALot Oct 28 '21 at 17:49
  • 1
    @Micah my shell on macOS is zsh. I experimented with bash and tcsh. The shell syntax `(cert.pem|certs)` may be the problem. zsh interprets it as "either the file cert.pem or the directory certs/ at that path". bash and tcsh don't like that syntax, but accept the file name "cert.pem". But the point of the question is OpenSSL certificates, not shell syntax. Also, good observation about markdown interpreting @IbrahimMagdy's back-ticks as markup, not as literal content. I think you are right about that. – Jim DeLaHunt Oct 28 '21 at 21:04
  • Thanks for checking into that! I’ve only recently started using zsh on my personal boxes, it’s been great thus far. It’s interesting to me that zsh works like that, you learn something new every day. BTW: I was running bash on a RHEL box at work, using bash. – Sir CodesALot Oct 29 '21 at 23:55
  • Bash-compatible command to list just the `# ` cert comments in `cert.pem` (for Mingw64): ```find -H `openssl version -d | sed -E 's/OPENSSLDIR: "([^"]*)"/\1/'`/cert.pem -type f -exec cat {} \+ | grep "# "``` Thanks to @IbrahimMagdy and @Jim for the puzzle pieces. – Zephan Schroeder Jul 26 '22 at 23:21
2

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?

em_bo
  • 624
  • 7
  • 13
  • 1
    Same behavior here. On 4 different Linux clients. Either OpenSSL do have a list of trusted CA or it looks in a default folder for trusted CA list. – STM Sep 21 '17 at 21:59
  • Same here. The root cert is this one: `depth=2 C = US, O = GeoTrust Inc., CN = GeoTrust Global CA`. There is a file `/etc/ssl/certs/GeoTrust_Global_CA.pem` on my system, which presumably makes OpenSSL trust that implicitly. Worth noting that `-showcerts` still doesn't actually print this root cert though. – Thomas Oct 03 '17 at 10:12
  • 4
    What's going on here is that we are talking about two different situations. If you install OpenSSL from source, you won't have installed any trusted certificate store. If you use your distro's package manager, distro packaging probably includes a dependency on whatever bundle of certificates the distro maintainers have decided to trust, so you *do* get a populated trust store. A server can send a stack of certificates which form its verification path, but the client should not trust the root certificate in that stack because it could be from anywhere, not necessarily somewhere *you* trust. – Mark Wood Apr 26 '18 at 10:42
0

Self-answer: this text suggest calling SSL_CTX_set_default_verify_paths() to trust the certificates in a system-dependent directory.

Konstantin Shemyak
  • 2,369
  • 5
  • 21
  • 41