From a web site, you can do:
openssl s_client -showcerts -verify 5 -connect stackexchange.com:443 < /dev/null
That will show the certificate chain and all the certificates the server presented.
Now, if I save those two certificates to files, I can use openssl verify
:
$ openssl verify -show_chain -untrusted dc-sha2.crt se.crt
se.crt: OK
Chain:
depth=0: C = US, ST = NY, L = New York, O = "Stack Exchange, Inc.", CN = *.stackexchange.com (untrusted)
depth=1: C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert SHA2 High Assurance Server CA (untrusted)
depth=2: C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert High Assurance EV Root CA
The -untrusted
option is used to give the intermediate certificate(s); se.crt
is the certificate to verify. The depth=2 result came from the system trusted CA store.
If you don't have the intermediate certificate(s), you can't perform the verify. That's just how X.509 works.
Depending on the certificate, it may contain a URI to get the intermediate from. As an example, openssl x509 -in se.crt -noout -text
contains:
Authority Information Access:
OCSP - URI:http://ocsp.digicert.com
CA Issuers - URI:http://cacerts.digicert.com/DigiCertSHA2HighAssuranceServerCA.crt
That "CA Issuers" URI points to the intermediate cert (in DER format, so you need to use openssl x509 -inform der -in DigiCertSHA2HighAssuranceServerCA.crt -out DigiCertSHA2HighAssuranceServerCA.pem
to convert it for further use by OpenSSL).
If you run openssl x509 -in /tmp/DigiCertSHA2HighAssuranceServerCA.pem -noout -issuer_hash
you get 244b5494
, which you can look for in the system root CA store at /etc/ssl/certs/244b5494.0
(just append .0
to the name).
I don't think there is a nice, easy OpenSSL command to do all that for you.
The real fix for this is to ensure that your server presents all certificates in the chain and not just the end-entity (server) certificate.
Point your server administrator to RFC 5246 Section 7.4.2 which clearly states that This message conveys the server's certificate chain to the client.
If your admin refuses/can't do this for some reason, your alternative option is to try and get curl
to work with the malformed handshake.
According to a message on the Curl mailing list:
Can someone confirm if cURL supports (or not) intermediate certificate?
Yes it does.
All ca certificates have a certificate chain going up to the root. The ca
bundle you use with curl needs to consist of the certs for the entire chain.
/ daniel.haxx.se
You should be able to add the Root CA and all intermediates certificates to a bundle and point curl
to it using the --cacert <file>
option.
As your browsers work, you can access the correct CA certificates from there. On the certificates tab (different for each browser, but I'm sure you'll figure that one out), view the certificate chain. Double-click the Root CA first Globalsign Root CA - G1 and on the Details tab, click on Copy to file.... Save it as root.cer
. Do the same with the AlphaSSL CA - SHA256 - G2 and save it as issuing.cer
. Join the two together in a single file (e.g. chain.cer
) and use that as the argument to -cacert
.
As kindly pointed out by @A.B. the missing certificate can also be found here.
Your browsers work because they cache CA certificates. If you've navigated to a correctly configured website at some point in the past, whose certificate was issued by the same CA as your server's certificate, it will be cached by the browser. When you subsequently visit your incorrectly configured site, your browser will use the CA certificates in its cache to build the chain. To you, it seems like everything is fine, although behind the scenes, the server is mis-configured.
Note that on Windows, IE/Edge and Chrome share the same cache, while Firefox uses its own.
In addition to the above, IE/Edge and Chrome (as they share the same crypto stack) will use an extension within certificates called the AuthorityInformationAccess. This has a caIssuer option which provides a URL from which the end-entity certificate's CA certificate can be downloaded. Therefore, even if one of these browsers hasn't cached the missing certificates from previous browsing, it can fetch it if required. Note that Firefox doesn't do this, which is why sometimes Firefox can show certificate errors when IE/Edge and Chrome seem to work.
Best Answer
I don't personally use Arch Linux, but this procedure works on most distributions.
First, you need to extract the CA certificate from your bundle. p12 files are basically a bundle of several components of a certificate.
You'll get one or more certificates dumped to your console. If you get more than one, find the one where the
subject
is the same as theissuer
. This is your root certificate.Take your root certificate (everything between, and including, the
BEGIN CERTIFICATE
andEND CERTIFICATE
lines), and save it in a file in/etc/ssl/certs
with the extension.pem
.Then do the following: