1
votes

I would like to get all certificates of the certicate chain of a http-site. Using openssl I connect to the http-site and store output to file out.txt:

openssl s_client -connect www.openssl.org:443 -showcerts > out.txt

The content of out.txt looks like below. It contains two certificates:

...
 0 s:CN = www.openssl.org
   i:C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3
-----BEGIN CERTIFICATE-----
MIIFVTCCBD2gAwIBAgISAwk9QUiwVmoQAtcCLKybaK7yMA0GCSqGSIb3DQEBCwUA
...
mQBom1EISBOiNyu5koR6iRZcXsn6x/4kwA==
-----END CERTIFICATE-----
 1 s:C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3
   i:O = Digital Signature Trust Co., CN = DST Root CA X3
-----BEGIN CERTIFICATE-----
MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/
...
KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg==
-----END CERTIFICATE-----
---
...

Now I want to store every certificate in a file ending with extension .cer. For the above example the files Let's Encrypt Authority X3.cer and www.openssl.org.cer should be created.

Using command openssl x509 I was only able to store first certifcate contained in out.txt.

cat out.txt | openssl x509 > www.openssl.org.cer

But I want to store all certifcates contained in out.txt not just the first one.

Can this be done with openssl somehow ? Or with awk ?

1

1 Answers

2
votes

Yes, this can be done with awk. I would like to present my solution piece by piece.

Step 1: extract everything between "BEGIN CERTIFICATE" and "END CERTIFICATE"

Only write lines between "BEGIN CERTIFICATE" and "END CERTIFICATE" to output:

awk '
/BEGIN CERTIFICATE/,/END CERTIFICATE/ {
print $0
}
' out.txt

Step 2: extract line containing CN

selects line which contains CN (e.g. 0 s:CN = www.openssl.org)

awk '
/^ [0-9]+ s:.*CN = / {
print $0
}
' out.txt

This yields output:

 0 s:CN = www.openssl.org
 1 s:C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3

Step 3: extract content of field CN

awk '
BEGIN {
# change field separator, so that $2 returns everything after "CN = "
FS="CN = "
}
# selects line which contains CN (e.g.  0 s:CN = www.openssl.org)
/^ [0-9]+ s:.*CN = / {
# use CN (e.g. www.openssl.org) as filename
print $2
}
' out.txt

This yields output:

www.openssl.org
Let's Encrypt Authority X3

Step 4: Full Solution

This creates files Let's Encrypt Authority X3.cer and www.openssl.org.cer:

awk '
BEGIN {
# change field separator, so that $2 returns everything after "CN = "
FS="CN = "
}
# selects line which contains CN (e.g.  0 s:CN = www.openssl.org)
/^ [0-9]+ s:.*CN = / {
# use CN (e.g. www.openssl.org) as filename
filename=$2".cer"
}
# write all lines between "BEGIN CERTIFICATE" and "END CERTIFICATE" to filename
/BEGIN CERTIFICATE/,/END CERTIFICATE/ {
print $0 > filename
}
' out.txt

AWK Documentation: https://www.gnu.org/software/gawk/manual/html_node/index.html