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