IF your curl
was built to use OpenSSL -- as you tagged but which is not the only option for curl
, verify with curl -V
-- AND the server is correctly serving any/all intermediate cert(s), THEN to trust the server curl-with-openssl needs a local 'truststore' containing the root cert for the server's cert chain (NOT the server's cert itself) in PEM format. (Some other SSL/TLS implmentations will accept nonroot anchor(s), but older versions of OpenSSL cannot do so at all, and even 1.0.2 doesn't do so by default.)
METHOD 0: maybe already there. Packages of curl often include a 'bundle' of widely-trusted CA roots such as Symantec GoDaddy etc., or link to another package that does (typically named something like ca-bundle or trusted-cas). The format(s) of the certs in such a bundle depend on the SSL/TLS library(ies) you use; check curl -V
as above. Check if you have such a bundle installed, and if so whether your curl
is using it. If you don't have or can't get a package (including the case you build curl yourself) AND use OpenSSL, curl upstream has a bundle of CA roots extracted from Mozilla NSS/Firefox extracted into the concatenated-PEM format needed for OpenSSL (and a tool to do this yourself).
openssl
commandline need not use the same default truststore location(s) as curl
-- and even if it does, until recent versions the s_client
command had a bug that didn't use the default truststore correctly. If you do have a concatenated-PEM bundle, specify it to s_client
with -CAfile bundlefile
and see if that makes a difference.
If method 0 doesn't apply, you need to get the server's root and add it to your truststore, or just use it as a truststore by itself.
METHOD 1: get from browser. IF you can connect to the server with a browswer like IE/Edge, Firefox, Chrome, etc. (this requires there be a URL you can enter that the server will respond with a successful webpage), THEN doubleclick on the padlock and click on whichever buttons or links lead to displaying the certificate chain (exact ones vary per browser). Select the topmost cert in the chain and look for an option to export it, preferably in single-cert PEM format (again exact method varies per browser). If you can't get single-cert PEM format, comment what format you did get (give the first line if it looks like -----BEGIN something
) and I'll tell you how to convert it.
Take this file (copy to the curl
machine if you created it somewhere else) and either add it to your truststore (depends on your packaging system; may be a simple as concatenating it to the existing concatenated-PEM file) or specify it by itself to curl
with option --cacert filename
.
METHOD 2: s_client plus. Run openssl s_client -connect host:port -showcerts
and capture (redirect or scrape) the output. Take the last block of lines -----BEGIN CERTIFICATE-----
to ----END CERTIFICATE-----
and put it in a file, for example topcert
. If the s:
and i:
names (subject and issuer) immediately preceding this block are exactly the same, this is the root cert and you're all set. Use this file as above, but only if you are satisified this CA is honest and competent (even though they apparently didn't convince the browser makers if method 1 didn't work) because you are putting the security of your data in their hands.
If the top cert from the server is not a root, you need to get its parent cert, which must be the root. Alternatively, in some cases this is a 'bridge' or 'transition' cert that links a new CA back to another (older) CA, and there is also a sibling cert for the new CA that is a root cert. First do openssl x509 -in topcert -noout -text
and look under x509v3 extensions
then Authority Information Access
for CA Issuers
. If present, accessing this URL (or any of them) should provide the parent cert. This is usually in DER format; if so convert with openssl x509 -in input -inform der -out output
.
Otherwise, look at any OCSP address(es), any CRL Distribution Point(s), and any URL(s) or domain name(s) in Certificate Policies or the Issuer name for the domain name(s) used by the CA and poke around there to try to find the parent root. Similarly look at any URL(s) or domain name(s) in Policies or Subject name and poke around for a sibling root. Or google for the Issuer name and/or Subject name. Or post the cert here. Or some combination.