86

My git client claims

error: Peer's Certificate issuer is not recognized.

That means it can not find the corresponding ssl server key in the global system keyring. I want to check this by looking at the list of all system wide available ssl keys on a gentoo linux system. How can I get this list?

Jonas Stein
  • 4,078
  • 4
  • 36
  • 55

8 Answers8

157

It's not SSL keys you want, it's certificate authorities, and more precisely their certificates.

You could try:

awk -v cmd='openssl x509 -noout -subject' '
    /BEGIN/{close(cmd)};{print | cmd}' < /etc/ssl/certs/ca-certificates.crt

To get the "subject" of every CA certificate in /etc/ssl/certs/ca-certificates.crt (this works because openssl exits after reading an individual cert block, but awk relaunches openssl on the next print | cmd call).

Beware that sometimes, you get that error when SSL servers forget to provide the intermediate certificates.

Use openssl s_client -showcerts -connect the-git-server:443 to get the list of certificates being sent.

Note that the pathname of the certificates bundle may differ depending on operating system. The directory holding the certs sub-directory is given by the command openssl version -d. The actual certificates file in that directory may additionally have a different name.

Kusalananda
  • 333,661
  • 2
    // , This does not work on CEntOS 6, but I have added an answer for CEntOS 6 here: https://unix.stackexchange.com/a/363309/48498 – Nathan Basanese May 05 '17 at 21:25
  • 4
    The list from trust list from p11-kit package is essentially the same? – Pablo A Mar 27 '19 at 16:55
  • @F.Hauri, The command I gave should work in bash or any shell of the Bourne, rc, or fish families. If put on one line, it would work in any shell that I know, even csh, even the Unix V6 shell. – Stéphane Chazelas Oct 14 '20 at 16:34
  • I agree, your solution is correct and efficient, I've just posted an alternative, using bash's arrays and some pretty output formatting, showing some usefull bash features – F. Hauri - Give Up GitHub Oct 14 '20 at 17:10
  • @StéphaneChazelas, works great on Debian, thanks. Could you please provide a breakdown in your answer of what that first command line instruction to read the CA cert subject is actually doing? – Chris Halcrow Feb 01 '21 at 00:18
  • @JonasStein (Re: your edit suggestion) while it's true openssl exits upon seeing the END CERTIFICATE, it would still work even if it didn't as we close(cmd) which closes the pipe to openssl and waits for the corresponding process to exit upon the next BEGIN upon which openssl would see EOF and exit. Try with cmd=wc instead for instance. – Stéphane Chazelas Jun 29 '22 at 15:27
  • The openssl s_client tip to get the exact list of certs a server is sending is super useful (ran into an issue where a misconfigured server was only sending its leaf cert instead of the full chain. Browsers compensate for that, but most other SSL/TLS client libraries don't) – ncoghlan Jul 11 '22 at 06:18
  • 1
    That's one interesting way to use awk. – x-yuri Sep 01 '22 at 10:33
37

Not sure about Gentoo but most distros put their certificates soft-link in system-wide location at /etc/ssl/certs.

  • Key files go into /etc/ssl/private
  • System-provided actual files are located at /usr/share/ca-certificates
  • Custom certificates go into /usr/local/share/ca-certificates

Whenever you put a certificate in one of the above mentioned paths, run update-ca-certificates to update /etc/ssl/certs lists.

SHW
  • 14,786
  • 14
  • 66
  • 101
6

I had a requirement to list all the certs on our server and notify if they are due to expire. We came up with this command:

locate .pem | grep "\.pem$" | xargs -I{} openssl x509 -issuer -enddate -noout -in {}
Chris Davies
  • 116,213
  • 16
  • 160
  • 287
  • Note that openssl x509 format expects only a single cert in a pem file. Multiple certs if present need to follow some parsing given https://unix.stackexchange.com/questions/17744/how-do-i-extract-all-subjects-of-a-cacertfile-with-the-openssl-command-line – Akash Jul 27 '20 at 12:08
4

A quick way to list all currently trusted CA certificates by openssl (with Ubuntu default directories):

find /etc/ssl/certs -type l -iname "*.0" -exec cat "{}" \; | awk -v cmd='openssl x509 -noout -subject -enddate 2>/dev/null | tr "\n" " " ; echo' '/BEGIN/{cert=""};{cert=sprintf("%s\n%s",cert,$0)};/END/{print cert | cmd ;close(cmd)}' | sed -r 's:^subject=::' | sort -u
Mimmo
  • 41
3

Another one it this one:

openssl crl2pkcs7 -nocrl -certfile /etc/ssl/certs/ca-certificates.crt | openssl pkcs7 -print_certs -noout | grep subject
1

Most of the times, when examining ca certificates, you will want (and should) grep with fingerprint. You can also pass the output to less for searching/matching manually.
In general verifying the certificate fingerprint rather than just its name/issuer name/date e.t.c is very important.

# By piping to less you can manually search by hitting '/'
cat /etc/ssl/certs/ca-certificates.crt | keytool -printcert 2>/dev/null | 
grep "^Certificate\[" -A11 | less

Output:

Certificate[1]:
Owner: C=ES, O=ACCV, OU=PKIACCV, CN=ACCVRAIZ1
Issuer: C=ES, O=ACCV, OU=PKIACCV, CN=ACCVRAIZ1
Serial number: 5ec3b7a6437fa4e0
Valid from: Thu May 05 12:37:37 EEST 2011 until: Tue Dec 31 11:37:37 EET 2030
Certificate fingerprints:
         SHA1: 93:05:7A:88:15:C6:4F:CE:88:2F:FA:91:16:52:28:78:BC:53:64:17
         SHA256: 9A:6E:C0:12:E1:A7:DA:9D:BE:34:19:4D:47:8A:D7:C0:DB:18:22:FB:07:1D:F1:29:81:49:6E:D1:04:38:41:13
Signature algorithm name: SHA1withRSA (weak)
Subject Public Key Algorithm: 4096-bit RSA key
Version: 3

-- Certificate[2]: Owner: OU=AC RAIZ FNMT-RCM, O=FNMT-RCM, C=ES Issuer: OU=AC RAIZ FNMT-RCM, O=FNMT-RCM, C=ES Serial number: 5d938d306736c8061d1ac754846907 Valid from: Wed Oct 29 17:59:56 EET 2008 until: Tue Jan 01 02:00:00 EET 2030 Certificate fingerprints: SHA1: EC:50:35:07:B2:15:C4:95:62:19:E2:A8:9A:5B:42:99:2C:4C:2C:20 SHA256: EB:C5:57:0C:29:01:8C:4D:67:B1:AA:12:7B:AF:12:F7:03:B4:61:1E:BC:17:B7:DA:B5:57:38:94:17:9B:93:FA Signature algorithm name: SHA256withRSA Subject Public Key Algorithm: 4096-bit RSA key Version: 3

-- .... ....

And since the above command prints also a sequential number for each certificate (e.g. Certificate[3]) you can then pick the actual certificate with:

# Let's say you want to pick certificate number 3
awk -v n=3 '/BEGIN CERTIFICATE/ && ++k == n, /END CERTIFICATE/' /etc/ssl/certs/ca-certificates.crt

Output:

-----BEGIN CERTIFICATE-----
MIICbjCCAfOgAwIBAgIQYvYybOXE42hcG2LdnC6dlTAKBggqhkjOPQQDAzB4MQsw
CQYDVQQGEwJFUzERMA8GA1UECgwIRk5NVC1SQ00xDjAMBgNVBAsMBUNlcmVzMRgw
FgYDVQRhDA9WQVRFUy1RMjgyNjAwNEoxLDAqBgNVBAMMI0FDIFJBSVogRk5NVC1S
Q00gU0VSVklET1JFUyBTRUdVUk9TMB4XDTE4MTIyMDA5MzczM1oXDTQzMTIyMDA5
MzczM1oweDELMAkGA1UEBhMCRVMxETAPBgNVBAoMCEZOTVQtUkNNMQ4wDAYDVQQL
DAVDZXJlczEYMBYGA1UEYQwPVkFURVMtUTI4MjYwMDRKMSwwKgYDVQQDDCNBQyBS
QUlaIEZOTVQtUkNNIFNFUlZJRE9SRVMgU0VHVVJPUzB2MBAGByqGSM49AgEGBSuB
BAAiA2IABPa6V1PIyqvfNkpSIeSX0oNnnvBlUdBeh8dHsVnyV0ebAAKTRBdp20LH
sbI6GA60XYyzZl2hNPk2LEnb80b8s0RpRBNm/dfF/a82Tc4DTQdxz69qBdKiQ1oK
Um8BA06Oi6NCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD
VR0OBBYEFAG5L++/EYZg8k/QQW6rcx/n0m5JMAoGCCqGSM49BAMDA2kAMGYCMQCu
SuMrQMN0EfKVrRYj3k4MGuZdpSRea0R7/DjiT8ucRRcRTBQnJlU5dUoDzBOQn5IC
MQD6SmxgiHPz7riYYqnOK8LZiqZwMR2vsJRM60/G49HzYqc8/5MuB1xJAWdpEgJy
v+c=
-----END CERTIFICATE-----
0

openssl and pure bash way

Even if Stéphane Chazelas's answer, work fine and is efficient, I would like to post this script who will give near same result, but don't use awk:

#!/bin/bash
exec {sslout}<> <(:)
cnt=1
while read -u $certs line; do
    [ "$line" ] && case $line in 
        *BEGIN*)
            exec {ssl}> >(openssl x509 -noout -subject >&${sslout})
            echo $line 1>&$ssl
        ;;
        *END*)
            echo $line 1>&$ssl
            exec {ssl}>&-
            read -u $sslout subject
            printf "%03d  %s\n" $((cnt++)) "${subject#subject=}"
        ;;
        *)
            echo $line 1>&$ssl
        ;;
    esac;
done {certs}< /etc/ssl/certs/ca-certificates.crt
exec {certs}>&- {sslout}>&-

One step further

Searching for certs in all dirs mentionned by SHW's answer, sorting by hashes and count

#!/bin/bash

exec {sslout}<> <(:) cnt=0 hashed=() while read -u $certs line; do [ "$line" ] && case $line in BEGIN) exec {ssl}> >(openssl x509 -noout -hash -subject >&${sslout}) echo $line 1>&$ssl ;; END) echo $line 1>&$ssl exec {ssl}>&- read -u $sslout hash read -u $sslout subject ((cnt++)) hashed[16#$hash]+="${subject#subject=}"$'\t' ;; *) echo $line 1>&$ssl ;; esac done {certs}< <(find /etc/ssl/certs /usr/{local/,}share/ca-certificates
-type f -exec cat {} +) exec {certs}>&- {sslout}>&- echo "$cnt certs read, ${#hashed[@]} different hashes." for i in ${!hashed[@]};do IFS=$'\t' read -a subj <<<"${hashed[i]}" printf "%8x %s\n" $i "$subj" ((${#subj}>1)) && printf " %s\n" "${subj[@]:1}" done

may output something like:

    256 certs read, 128 different hashes.
 3179a64  C = NL, O = Staat der Nederlanden, CN = Staat der Nederlanden EV Root CA
          C = NL, O = Staat der Nederlanden, CN = Staat der Nederlanden EV Root CA
 62cdee6  OU = GlobalSign Root CA - R3, O = GlobalSign, CN = GlobalSign
          OU = GlobalSign Root CA - R3, O = GlobalSign, CN = GlobalSign
 64e0aa9  C = BM, O = QuoVadis Limited, CN = QuoVadis Root CA 2 G3
          C = BM, O = QuoVadis Limited, CN = QuoVadis Root CA 2 G3
...
-2

Find with crt or key files shall also work

find / -type f -name *.key
find / -type f -name *.crt