Client certificates and Apache

Does anyone have a guide that a newbie like me can use to setup client side certificates with FreeBSD and Apache.

I tried a few articles online but they are more aimed at Linux users and am finding it confusing trying to "translate" that into FreeBSD...:)

I basically have a subfolder off a web site like:

https://www.mydomain.com/secure

and I would like to JUST secure the "secure" sub folder.

Thank you.
 
Thanks but I have already looked at that link. I am relatively familiar with certificates but not so much on FreeBSD.

I setup a test alias in Apache as follows:

Code:
Alias /client "/usr/local/www/client/"

<Directory "/usr/local/www/client/">
Options Indexes FollowSymLinks
AllowOverride All
Order allow,deny
Allow from all
SSLVerifyClient require
SSLVerifyDepth 1
SSLCACertificateFile /usr/local/openssl/certs/mydomain.com-CAcert.pem
</Directory>

But it still lets me view my test page without prompting me to have a valid client side cert.

If I comment out the following options:

Code:
Alias /client "/usr/local/www/client/"

<Directory "/usr/local/www/client/">
#Options Indexes FollowSymLinks
#AllowOverride All
#Order allow,deny
#Allow from all
SSLVerifyClient require
SSLVerifyDepth 1
SSLCACertificateFile /usr/local/openssl/certs/mydomain.com-CAcert.pem
</Directory>

I then get:

Code:
Forbidden
You don't have permission to access /client/index.html on this server.

But still no prompt :\
 
It shouldn't matter that this is FreeBSD - Apache works the same here as other unixes. :)

Stupid question maybe, but are browsing your server via SSL? (ie. https:// in browser address bar)
 
The test site I setup is not using SSL but when I finish testing this successfully I will be using SSL AND client side certificates.
 
I'm quite baffled about configuring client side certificates in Apache.

I setup a new test site in Apache as follows:

Code:
Alias /test "/usr/local/www/test/"

<Directory "/usr/local/www/test/">
Options Indexes FollowSymLinks
AllowOverride All
Order allow,deny
Allow from all
SSLRequireSSL
SSLVerifyClient require
</Directory>

If I browse the site httpS://www.mydomain.com/test it works perfectly over SSL. As soon as I enable "SSLVerifyClient require" then I can't browse the site anymore. It doesn't even prompy me to select a certificate to allow me access to that part of the site, whys this?
 
This is what /var/log/httpd-error.log says:

Code:
[Tue Jul 28 15:47:32 2009] [error] Re-negotiation handshake failed: Not accepted by client!?
 
Thats when testing it with IE8.

When I try from Firefox 3.5.1 I get:

Code:
Secure Connection Failed

An error occurred during a connection to www.mydomain.com.

SSL peer was unable to negotiate an acceptable set of security parameters.

(Error code: ssl_error_handshake_failure_alert)


    *   The page you are trying to view can not be shown because the authenticity of the received data could not be verified.

    *   Please contact the web site owners to inform them of this problem. Alternatively, use the command found in the help menu to report this broken site.
 
In one article I read it says:

Install the local CA's certificate into the Apache directory structure.

Code:
install -m 644 -o root -g sys ca.crt /usr/local/apache2/conf/ssl.crt/

Again, I dont have any .crt files and I also dont have an Apache conf directory (not that I can find anyway!).

Any ideas? I'm not sure what else to do...
 
.crt is just a file extension. It is used to denote a file containing a certificate only (as opposed to a private key or certificate+private key). Apache uses openssl, which needs PEM formatted files, so what you have should be fine once you've configured Apache to use the right files.

You should have these 3 things for apache:

1. CA certificate
2. Server certificate
3. Server private key

Do you have all of these setup?
 
Ok, good. You need to configure these:

Code:
SSLCertificateFile /path/to/www.mydomain.com-cert.pem
SSLCertificateKeyFile /path/to/www.mydomain.com-unencrypted-key.pem
SSLCACertificateFile /path/to/www.mydomain.com-CAcert.pem
SSLVerifyClient require
SSLVerifyDepth 1

Obviously replacing "/path/to" to the real path to each of those files. Verify depth must be set higher if you're signing more than 1 deep.

You need to make sure they're not overridden elsewhere in your config. Check that apache's SSL is not being misconfigured in an include somewhere.

Code:
grep -i include /usr/local/etc/apache2/httpd.conf

And check how SSLCipherSuite, SSLOptions, and SSLRequire is setup - it sounds like one of those might be breaking browser compatibility.
 
Thanks for that reply!

I put those entries into my "test.conf" file (not httpd.conf) and when I restarted Apache it said:

Code:
server# /usr/local/etc/rc.d/apache22 restart
Performing sanity check on apache22 configuration:
Syntax error on line 9 of /usr/local/etc/apache22/Includes/test.conf:
SSLCertificateFile not allowed here

If I run

Code:
grep -i include /usr/local/etc/apache22/httpd.conf

I get:

Code:
server# grep -i include /usr/local/etc/apache22/httpd.conf
LoadModule include_module libexec/apache22/mod_include.so
    #   Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews
# Possible values include: debug, info, notice, warn, error, crit,
    # If you include a trailing / on /webpath then the server will
    # To parse .shtml files for server-side includes (SSI):
    # (You will also need to add "Includes" to the "Options" directive.)
    #AddOutputFilter INCLUDES .shtml
# included to add extra features or to modify the default configuration of
#Include etc/apache22/extra/httpd-mpm.conf
#Include etc/apache22/extra/httpd-multilang-errordoc.conf
#Include etc/apache22/extra/httpd-autoindex.conf
#Include etc/apache22/extra/httpd-languages.conf
#Include etc/apache22/extra/httpd-userdir.conf
#Include etc/apache22/extra/httpd-info.conf
#Include etc/apache22/extra/httpd-vhosts.conf
#Include etc/apache22/extra/httpd-manual.conf
#Include etc/apache22/extra/httpd-dav.conf
#Include etc/apache22/extra/httpd-default.conf
Include etc/apache22/extra/httpd-ssl.conf
Include etc/apache22/Includes/*.conf
 
aragon said:
Please post your test.conf and extra/httpd-ssl.conf?

Here we go:

test.conf:

Code:
Alias /test "/usr/local/www/test/"

<Directory "/usr/local/www/test/">
Options Indexes FollowSymLinks
AllowOverride All
Order allow,deny
Allow from all
SSLRequireSSL
SSLCertificateFile /usr/local/openssl/certs/mydomain.com-cert.pem
SSLCertificateKeyFile /usr/local/openssl/certs/mydomain.com-unencrypted-key.pem
SSLCACertificateFile /usr/local/openssl/certs/mydomain.com-CAcert.pem
SSLVerifyClient require
SSLVerifyDepth 1
</Directory>

extra/httpd-ssl.conf:

Code:
Listen 443

AddType application/x-x509-ca-cert .crt
AddType application/x-pkcs7-crl    .crl

SSLPassPhraseDialog  builtin

SSLSessionCache        "shmcb:/var/run/ssl_scache(512000)"
SSLSessionCacheTimeout  300

SSLMutex  "file:/var/run/ssl_mutex"

<VirtualHost _default_:443>

DocumentRoot "/usr/local/www/securesite/"
ServerName www.mydomain.com:443
ServerAdmin admin@mydomain.com
ErrorLog "/var/log/httpd-error.log"
TransferLog "/var/log/httpd-access.log"

SSLEngine on

SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL

SSLCertificateFile "/usr/local/openssl/certs/www.mydomain.com-cert.pem"



SSLCertificateKeyFile "/usr/local/openssl/certs/www.mydomain.com-unencrypted-key.pem"

<FilesMatch "\.(cgi|shtml|phtml|php)$">
    SSLOptions +StdEnvVars
</FilesMatch>
<Directory "/usr/local/www/apache22/cgi-bin">
    SSLOptions +StdEnvVars
</Directory>


CustomLog "/var/log/httpd-ssl_request.log" \
          "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
ProxyPass /webmin/ http://www.mydomain.com:10000
ProxyPassReverse /webmin/ http://www.mydomain.com:10000

</VirtualHost>

I removed all the comments from httpd-ssl.conf as it was a rather lenghty file! :e
 
(Backup and) Delete test.conf and replace extra/httpd-ssl.conf with:

Code:
Listen 443

AddType application/x-x509-ca-cert .crt
AddType application/x-pkcs7-crl    .crl

SSLPassPhraseDialog  builtin

SSLSessionCache        "shmcb:/var/run/ssl_scache(512000)"
SSLSessionCacheTimeout  300

SSLMutex  "file:/var/run/ssl_mutex"

<VirtualHost _default_:443>

DocumentRoot "/usr/local/www/securesite/"
ServerName www.mydomain.com:443
ServerAdmin admin@mydomain.com
ErrorLog "/var/log/httpd-error.log"
TransferLog "/var/log/httpd-access.log"

SSLEngine on

SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL

SSLCACertificateFile /usr/local/openssl/certs/mydomain.com-CAcert.pem
SSLCertificateFile "/usr/local/openssl/certs/www.mydomain.com-cert.pem"
SSLCertificateKeyFile "/usr/local/openssl/certs/www.mydomain.com-unencrypted-key.pem"

<FilesMatch "\.(cgi|shtml|phtml|php)$">
    SSLOptions +StdEnvVars
</FilesMatch>
<Directory "/usr/local/www/apache22/cgi-bin">
    SSLOptions +StdEnvVars
</Directory>


CustomLog "/var/log/httpd-ssl_request.log" \
          "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
ProxyPass /webmin/ http://www.mydomain.com:10000
ProxyPassReverse /webmin/ http://www.mydomain.com:10000

Alias /test "/usr/local/www/test/"
<Directory "/usr/local/www/test/">
Options Indexes FollowSymLinks
AllowOverride All
Order allow,deny
Allow from all
SSLRequireSSL
SSLVerifyClient require
SSLVerifyDepth 1
</Directory>

</VirtualHost>
 
OK, I deleted the test.conf file and replaced the following in httpd-ssl.conf:

Code:
SSLCACertificateFile /usr/local/openssl/certs/mydomain.com-CAcert.pem

Alias /test "/usr/local/www/test/"

<Directory "/usr/local/www/test/">
Options Indexes FollowSymLinks
AllowOverride All
Order allow,deny
Allow from all
SSLRequireSSL
SSLVerifyClient require
SSLVerifyDepth 1
</Directory>

</VirtualHost>

Am still getting no prompt for a certificate though.

Still getting these in the /var/log/httpd-error.log:

Code:
[Tue Jul 28 21:32:48 2009] [error] Re-negotiation handshake failed: Not accepted by client!?
 
In the /var/log/httpd-access.log I get:

Code:
192.168.0.10 - - [28/Jul/2009:21:32:48 +0100] "GET /test/index.html HTTP/1.1" 403 -
192.168.0.10 - - [28/Jul/2009:21:38:45 +0100] "GET /test/ HTTP/1.1" 403 -
 
Perhaps newer browsers don't even bring up a prompt if there are no client certificates installed? Seeing as you will need a client certificate anyway, I think you should generate one and import it into the browser now.
 
Back
Top