Using a keystore with curl

Viewed 17820

I would like to execute the below curl command and specify my own key store.

I tried using --cacert option and specified the path of the cacert jks.

curl --ssl-reqd --url 'smtp://mailhost.myorg.com:587' --user 'usrid:pwd' --mail-from 'fromaddr@myorg.com' --mail-rcpt 'toaddr@myorg.com' --upload-file mail.txt -vv --cacert /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.272.b10-1.el7_9.x86_64/jre/lib/security/cacerts

But it resulted in an error.

curl: (77) Problem with the SSL CA cert (path? access rights?)
2 Answers

As Amit quoted, curl --cacert requires a file in PEM format -- but the Java cacerts file is in JKS format, which is massively different.

You can convert the certs from JKS format to PEM format with a script, something like:

jks=/usr/lib/jvm/$javaversion/jre/lib/security/cacerts
for c in $(keytool -keystore $jks -storepass changeit -list | awk -F, '/trustedCert/{print $1}'); do 
  keytool -keystore $jks -storepass changeit -exportcert -alias $c -rfc
done >pemfile
# for Java9 up use -cacerts instead of -keystore $jks

which maybe makes this marginally on-topic for SO, since your Q isn't about programming at all. Instead of doing all the certs you could do a selected one, or few, that are needed for the connections you want to make and validate.

But for RedHat (as tagged) this isn't necessary. In RedHat (and RH-based) Open JDK packages JRE/lib/security/cacerts is actually a symlink to /etc/pki/java/cacerts which is supplied by a different package ca-certificates.noarch -- which also supplies the same certs already in PEM format in /etc/pki/tls/cert.pem so you could use that directly (in spite of the name appearing singular it actually contains, or rather links to a file containing, many certs) AND in NSS format in /etc/pki/nssdb/* which is what the RH package of curl uses by default. Thus your curl already by default uses the same certs you can get from the Java cacerts file, so this effort accomplishes nothing at all.

when using --cacert you need to specify the certificate - e.g - /tmp/ca.crt

From the docs:

--cacert (HTTPS) Tells curl to use the specified certificate file to verify the peer. The file may contain multiple CA certificates. The certificate(s) must be in PEM format. If this option is used several times, the last one will be used.

--capath (HTTPS) Tells curl to use the specified certificate directory to verify the peer. The certificates must be in PEM format, and the directory must have been processed using the c_rehash utility supplied with openssl. Certificate directories are not supported under Windows (because c_rehash uses symbolink links to create them). Using --capath can allow curl to make https connections much more efficiently than using --cacert if the --cacert file contains many CA certificates. If this option is used several times, the last one will be used.

So, if you specify --cacert, the CA certs are stored in the specified file. These CA certificates are used to verify the certs of remote servers that cURL connects to.

The --capath option is used to specify a directory containing the CA certs rather than a single file.

Related