Ssl – Curl succeeds in sending https requests, apache2 can’t

Apache2sslssl-certificate

Ubuntu server 14.04.

I must connect to an application outside of my network, through https. I'm using apache2 to build a communication on the https layer.

On the other side it is requested a client certificate authentication. I installed in my Ubuntu all the certificate chain. The CA, intermediate and also their public certificate.

A practical example:

curl -lv https://this-application/receiving-link

* Hostname was NOT found in DNS cache
*   Trying 111.222.333.444...
* Connected to application-something (111.222.333.444) port 443 (#0)
* successfully set certificate verify locations:
*   CAfile: none
  CApath: /etc/ssl/certs
* SSLv3, TLS handshake, Client hello (1):
* SSLv3, TLS handshake, Server hello (2):
* SSLv3, TLS handshake, CERT (11):
* SSLv3, TLS alert, Server hello (2):
* SSL certificate problem: unable to get local issuer certificate
* Closing connection 0
curl: (60) SSL certificate problem: unable to get local issuer certificate
More details here: http://curl.haxx.se/docs/sslcerts.html

curl performs SSL certificate verification by default, using a "bundle"
 of Certificate Authority (CA) public keys (CA certs). If the default
 bundle file isn't adequate, you can specify an alternate file
 using the --cacert option.
If this HTTPS server uses a certificate signed by a CA represented in
 the bundle, the certificate verification probably failed due to a
 problem with the certificate (it might be expired, or the name might
 not match the domain name in the URL).
If you'd like to turn off curl's verification of the certificate, use
 the -k (or --insecure) option.

I expect exactly this result.

I loaded all the certificate chain + public (pem format and hashed, softlinked) here: /etc/apache2/mytrustedclientcerts

curl -lvvvvv --capath "/etc/apache2/mytrustedclientcerts/" https://this-application/receiving-link

* Hostname was NOT found in DNS cache
*   Trying 111.222.333.444...
* Connected to application-something (111.222.333.444) port 443 (#0)
* successfully set certificate verify locations:
*   CAfile: none
  CApath: /etc/apache2/mytrustedclientcerts/
* SSLv3, TLS handshake, Client hello (1):
* SSLv3, TLS handshake, Server hello (2):
* SSLv3, TLS handshake, CERT (11):
* SSLv3, TLS handshake, Server key exchange (12):
* SSLv3, TLS handshake, Request CERT (13):
* SSLv3, TLS handshake, Server finished (14):
* SSLv3, TLS handshake, CERT (11):
* SSLv3, TLS handshake, Client key exchange (16):
* SSLv3, TLS change cipher, Client hello (1):
* SSLv3, TLS handshake, Finished (20):
* SSLv3, TLS change cipher, Client hello (1):
* SSLv3, TLS handshake, Finished (20):
* SSL connection using ECDHE-RSA-AES256-GCM-SHA384
* Server certificate:
*        information about the certificate here
*        ...
*        ...
*        ...
*        ...
*        SSL certificate verify ok.
> GET /b2b/httpReceiver HTTP/1.1
> User-Agent: curl/7.35.0
> Host: application-something.com
> Accept: */*
> 
< HTTP/1.1 200 OK
< Date: Mon, 04 Jun 2018 13:16:20 GMT
* Server Server is not blacklisted
< Server: Server
< Content-Length: 155
< test: some_thing
< test: 0:1
< Content-Type: text/html; charset=ISO-8859-1
< 
<html><head><title>Server</title></head>
<body><h1>Hello</h1>
Ready.
</body></html>
* Connection #0 to host application-something.com left intact

Perfection. This is how I see if I'm able to connect, and I do.

Now it's Apache2 turn.

I added to my sites-enabled configuration.conf:

SSLCACertificatePath  "/etc/apache2/mytrustedclientcerts/"
SSLVerifyDepth 10
SSLVerifyClient optional #this must be optional because of many reasons

Just like I did in the test server, where the connection worked right after the change.
In this prod server (both of them Ubuntu 14.04) just does not work.

I read in my application log:

06/04/18 11:42:31 SenderModule: Connecting to: https://this-application/receiving-link [message-for-sending-hash]
06/04/18 11:42:32 SenderModule: Failed to connect to partner using SSL certificate. Please run the SSL certificate checker utility to identify the issue: https://this-application/receiving-link [message-for-sending-hash]

I tried to verify the certificate too:

openssl verify -verbose -x509_strict -CApath /etc/apache2/mytrustedclientcerts/ /etc/apache2/mytrustedclientcerts/4.https_public.pem

Which says:

/etc/apache2/mytrustedclientcerts/4.https_public.pem: OK

I restarted Apache2 for applying the changes – I do not want to use the '-k' option on CURL because that is not the point.

I'm asking if someone knows why Apache2 is not able to get these certificate and using them. Probably I missed something from the documentation: https://httpd.apache.org/docs/2.4/mod/mod_ssl.html#sslcacertificatepath but honestly I don't think so..
Any help is appreciated!

Best Answer

This is not what I wanted but at least I have it working now.

My goal was to tell Apache2 to use a folder made appositely for certificates that I wanted Apache2 only to trust and connect and not the whole system. This folder was /etc/apache2/mytrustedclientcerts/. Just like I did with CURL.

Due to the fact that I needed to have the connection ready, I trusted the certificates globally in the system:

  • Copied the encoded version of the certificate in .crt extension, inside /etc/ssl/cert
  • Ran the little script that I prepared for hashing and Linking the certificates (see it below).

After this, the HTTPS connection with Apache worked. Still, not what I wanted, but at least it works.

#!/bin/bash
hash=$(openssl x509 -noout -hash -in "$1")
if [ $(ls -1 "${hash}."* 2>/dev/null | wc -l) -gt 0 ]; then
  inc=$(ls -t "${hash}."* | head -1 | awk -F"." '{print $2}')
  ((inc+=1))
else
  inc=0
fi
ln -s "$1" "${hash}.${inc}"