1

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>
  • Try removing the SSLOptions directive. – fuero Oct 5 '17 at 17:21
  • 1
    Have a look at bettercrypto.org and cipherli.st for recommendations on how to securely set up TLS – fuero Oct 5 '17 at 17:23
  • @fuero I did try w/ out that option with no success. Just not sure how to include both the public and private cert? Will take a look at the 2 sites you mentioned. Thanks, – Joel F. Oct 5 '17 at 17:34
  • Show us your complete SSL config. – fuero Oct 5 '17 at 18:10
  • @fuero Do I use the public key for the SSLCACertificateFile value? What do I do w/ the private binary key, if anything? Thanks. – Joel F. Oct 6 '17 at 12:32
0

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

0

For our situation, we ended up making three changes:

  1. Uncommented SSLCertificateChainFile and set it to RapidSSL's certificate chain file (who issued our certificate).

  2. Changed SSLCACertificateFile to the CA chain file of the 3rd party's issuer (who issues their certificate).

  3. Removed SSLCACertificateFile from the directive.

Once we changed those and restarted, the two-way auth worked and they were able to access the API.

Thanks to @fuero for the help.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.