Ssl – Two-Way SSL Authentication with Apache 2.2 and OpenSSL 1.0.1e-fips

apache-2.2opensslssl

I have a CentOS 6 server running Apache 2.2.15 with OpenSSL 1.0.1e-fips. I am trying to setup two-way SSL authentication for a specific location in my web root. A 3rd party has provided both a public (plain-text) and private (binary) certificate.

I need some guidance on how to include both the public and private certs to get the handshaking working, as I am getting the following error:

Re-negotiation handshake failed: Not accepted by client!?

Here's what I have in my /etc/httpd/conf.d/ssl.conf file pertaining to this section:

<Location /api/path/>
SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL
SSLCACertificateFile /etc/pki/tls/private/public.cer
SSLVerifyClient require
SSLVerifyDepth 10
SSLOptions +StdEnvVars +ExportCertData +OptRenegotiate
</Location>

Admittedly I am not an SSL expert. I know enough to get certs installed and working. I have turned logginf to 'debug' level. I have tried to follow these guides:

http://www.stefanocapitanio.com/configuring-two-way-authentication-ssl-with-apache/

http://www.cafesoft.com/products/cams/ps/docs32/admin/ConfiguringApache2ForSSLTLSMutualAuthentication.html

Thanks in advance!

Full ssl.conf file:

LoadModule ssl_module modules/mod_ssl.so
Listen 443

SSLPassPhraseDialog  builtin

SSLSessionCache         shmcb:/var/cache/mod_ssl/scache(512000)
SSLSessionCacheTimeout  300

SSLMutex default

SSLRandomSeed startup file:/dev/urandom  256
SSLRandomSeed connect builtin
#SSLRandomSeed startup file:/dev/random  512
#SSLRandomSeed connect file:/dev/random  512
#SSLRandomSeed connect file:/dev/urandom 512

SSLCryptoDevice builtin
#SSLCryptoDevice ubsec
<VirtualHost *:443>
DocumentRoot "/var/www/html/staging-site"
ServerName staging.site.com:443
ErrorLog logs/ssl_error_log
TransferLog logs/ssl_access_log
LogLevel debug

SSLEngine on
SSLProtocol all -SSLv2 -SSLv3
SSLCipherSuite ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM:+LOW

SSLCertificateFile /etc/pki/tls/certs/cert.crt
SSLCertificateKeyFile /etc/pki/tls/private/private.key
#SSLCertificateChainFile /etc/pki/tls/certs/server-chain.crt
SSLCACertificateFile /etc/pki/tls/certs/rapidssl.crt

#SSLVerifyClient require
#SSLVerifyDepth  10

#   Access Control:
#<Location />
#SSLRequire (    %{SSL_CIPHER} !~ m/^(EXP|NULL)/ \
#            and %{SSL_CLIENT_S_DN_O} eq "Snake Oil, Ltd." \
#            and %{SSL_CLIENT_S_DN_OU} in {"Staff", "CA", "Dev"} \
#            and %{TIME_WDAY} >= 1 and %{TIME_WDAY} <= 5 \
#            and %{TIME_HOUR} >= 8 and %{TIME_HOUR} <= 20       ) \
#           or %{REMOTE_ADDR} =~ m/^192\.76\.162\.[0-9]+$/
#</Location>

<Location /path/api/>
    SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL
    SSLCACertificateFile /etc/pki/tls/private/3rdpartyprivate.cer
    SSLVerifyClient require
    SSLVerifyDepth 10
    SSLOptions +StdEnvVars +ExportCertData +OptRenegotiate
</Location>

#   SSL Engine Options:
#SSLOptions +FakeBasicAuth +ExportCertData +StrictRequire
<Files ~ "\.(cgi|shtml|phtml|php3?)$">
    SSLOptions +StdEnvVars
</Files>
<Directory "/var/www/cgi-bin">
    SSLOptions +StdEnvVars
</Directory>

#   SSL Protocol Adjustments:
SetEnvIf User-Agent ".*MSIE.*" \
         nokeepalive ssl-unclean-shutdown \
         downgrade-1.0 force-response-1.0

#   Per-Server Logging:
CustomLog logs/ssl_request_log \
          "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
</VirtualHost>

Best Answer

I think you are not using the correct certificates in the correct place. You are supposed to use the server certificate issued by a trusted CA in the SSLCertificateFile (certificate in PEM format), SSLCertificateKeyFile (key in PEM format matching the cert), and SSLCertificateChainFile (certificates starting from the host cert's issuer certificate up to and including the root certificate in PEM format).

In SSLCACertificateFile you have to use the cert (in PEM format as well) of the CA that signed the clients' certs.

Here's a complete example, keep in mind that I'm using a server cert signed by the same CA that signs the clients' certs for this. Adjust if your needs differ.

  • Generating the certs openssl genrsa -des3 -out ca.key 4096 openssl req -new -x509 -days 365 -key ca.key -out ca.crt -subj "/C=US/ST=Some State/L=FancyTown/O=SomeOrg/CN=Self-Signed CA" openssl genrsa -out client.key 4096 openssl req -new -key client.key -out client.csr -subj "/C=US/ST=Some State/L=FancyTown/O=SomeOrg/CN=client" openssl x509 -req -days 365 -in client.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out client.crt openssl genrsa -out server.key 4096 openssl req -new -key server.key -out server.csr -subj "/C=US/ST=Some State/L=FancyTown/O=SomeOrg/CN=server" openssl x509 -req -days 365 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 02 -out server.crt

  • Moving them to a more convenient location mkdir /etc/ssl_ ; mv * /etc/ssl_

  • Install webserver and mod_ssl yum install -y httpd mod_ssl

  • Purge default TLS config truncate -s0 /etc/httpd/conf.d/ssl.conf

  • Common TLS config for all VHosts, /etc/httpd/conf.d/00-ssl.conf ``` LoadModule ssl_module modules/mod_ssl.so

Listen 443 https SSLCACertificateFile /etc/pki/tls/certs/ca-bundle.crt SSLStaplingCache shmcb:/run/httpd/stapling_cache(128000) SSLUseStapling off

SSLPassPhraseDialog exec:/usr/libexec/httpd-ssl-pass-dialog SSLSessionCache shmcb:/run/httpd/sslcache(512000) SSLSessionCacheTimeout 300 SSLRandomSeed startup file:/dev/urandom 256 SSLRandomSeed connect builtin SSLCryptoDevice builtin

SSLStrictSNIVHostCheck off SSLProtocol +TLSv1.2 -TLSv1.1 -TLSv1 -SSLv3 SSLHonorCipherOrder on

SSLCompression off SSLCipherSuite ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:-ECDHE-RSA-RC4-SHA:ECDHE-RSA-AE S256-SHA:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:-RC4-SHA:AES256- GCM-SHA384:AES256-SHA256:CAMELLIA256-SHA:ECDHE-RSA-AES128-SHA:AES128-GCM-SHA256:AES128-SHA256:AES128-SHA:CAMELLIA128-SHA ```

  • VHost config /etc/httpd/conf.d/50-ssl-vhost.conf

``` ServerAlias localhost.localdomain localhost ServerName server SSLEngine on SSLCertificateFile /etc/_ssl/server.crt SSLCertificateKeyFile /etc/_ssl/server.key SSLCertificateChainFile /etc/_ssl/ca.crt SSLCACertificateFile /etc/_ssl/ca.crt

    SSLVerifyClient require
    SSLVerifyDepth  10

    DocumentRoot /var/www/html

    <Directory /var/www/html>
            Require all granted
    </Directory>

    ErrorLog logs/ssl_error_log
    TransferLog logs/ssl_access_log

```

  • Create an index.html file for testing echo 'It works\!' > /var/www/html/index.html

  • Start httpd

systemctl enable --now httpd

  • Add hostname

echo '127.0.1.1 server' >> /etc/hosts

  • Test

This works (auth ok): ( echo -en 'GET / HTTP/1.1\r\nHost: server\r\n\r\n' ; sleep 2) | openssl s_client -CAfile /etc/_ssl/ca.crt -cert /etc/_ssl/client.crt -key /etc/_ssl/cli ent.key -connect server:443 -servername server

This doesn't, we didn't provide a correct cert:

( echo -en 'GET / HTTP/1.1\r\nHost: server\r\n\r\n' ; sleep 2) | openssl s_client -CAfile /etc/_ssl/ca.crt -connect server:443 -servername server