OpenSSL notes

Creating personal certificates and using them for HTTP authentication
=====================================================================
To make a personal certificate (like the ones you can buy from Verisign) we 
simply make a new certificate as usual and export it in pkcs12 format.

openssl genrsa -out me.key -des3 1024
openssl req -new -days 365 -key me.key -out me.csr
./sign.sh me.csr
openssl pkcs12 -clcerts -export -inkey me.key -in me.crt -out me.p12 -descert

You are asked for the private key password and then prompted to enter an 
export password.  This is a different password that is needed when importing 
the cert into your browser.

Importing the certificate
-------------------------
( Netscape: Security -> Certificates -> Yours -> Import a certificate: p12 )
To import the certificate into Netscape 4.x, click the padlock icon at the 
bottom left of the browser window, select Certificates, then Yours and choose 
Import a certificate.  Netscape presents you with a *.p12 fileselector.  Find 
the me.p12 file and import it.  Type the Export Password when requested.

( Mozilla: Preferences -> Priv & Sec -> Certificates -> Manage -> Restore: p12 )
To import the the certificate into Mozille, choose Preferences from the Edit 
menu and select Privacy & Security.  Click Certificates and press the 
Manage Certificates button.  Then hit Restore, browse to the me.p12 file and 
enter the Export Password when requested.

( IE: Internet Options -> Certificates -> Personal -> Import: p12 )
To associate the certificate with your Windows profile (it's available to IE 
and Outlook etc) open the Internet Options control panel item and enter the 
Certificates submenu.  Under Personal, click Import and browse to the me.p12 
file.  Enter the Export Password when required.

( KDE: kcontrol -> Personalization -> Crypto -> Your certs -> Import: p12 )
To associate the certificate with your KDE profile and make it available to 
kmail and konqueror etc, open kcontrol and choose Crypto from the 
Personalization menu.  Under Your Certificates hit Import and locate the me.p12 
file.  Enter the Export Password when required.

Note: konqueror seems to (stupidly) require the Export Password and *not* the 
private key password when presenting the cert to remote sites.  Bad.

Making apache require a valid certificate
-----------------------------------------
If you haven't already done so, add the CA cert in text format to ca-bundle.crt 
so it can be trusted by apache.

openssl x509 -in ca.crt -text >> /etc/ssl/certs/ca-bundle.crt

Now tell apache to require a certificate signed by one of the CAs in the 
ca-bundle.crt list.

SSLCACertificateFile /etc/ssl/certs/ca-bundle.crt
SSLVerifyClient require
SSLVerifyDepth 1

Telling apache to bypass username/password authentication with a certificate
----------------------------------------------------------------------------
* DOES NOT WORK WITH mod_auth_mysql *
We can tell apache to accept a cert as sufficient for authentication to a 
protected resource but fall back to username and password if no cert is 
presented.
To do this we take advantage of mod_ssl's FakeBasicAuth feature, which takes 
the Distinguished Name of the cert and makes a username out of it, with 
password 'password'.
We can use openssl x509 to find out the DN (or subject).

openssl x509 -noout -subject -in crt

Since 'password' hashes to 'xxj31ZMTZzkVA' we need to add that to our 
password file.

openssl x509 -noout -subject -in crt \
| sed 's/^[^ ]* //;s/.*/&:xxj31ZMTZzkVA/' >> /opt/apache/passwords/ssl

Now we add the following rules to our protected resource.

AuthType basic
AuthName "whatever"
AuthUserFile /opt/apache/passwords/ssl
require valid-user
SSLVerifyClient optional
SSLVerifyDepth 1
SSLOptions +FakeBasicAuth

IF the browser presents a cert its DN is checked in the password file.  Normal 
username/password authentication is attempted otherwise.  Put the standard 
htpasswd entries in the same AuthUserFile!

Accepting connections from the internet with a cert
---------------------------------------------------
We can have apache accept connections from arbitrary hosts if they present a 
valid cert and also let in people on specified IPs without one.  In this 
example we will also require a username and password, since that's useful in 
our admin server setting.

Follow the steps above but add these extra directives.

SSLOptions +FakeBasicAuth +StrictRequire
SSLRequire (    %{SSL_CIPHER} !~ m/^(EXP|NULL)-/ \
            and %{SSL_CLIENT_S_DN_O} eq "ViaGold Direct Network" \
            and %{SSL_CLIENT_S_DN_OU} in {"Technical staff", "CA"} ) \
             or %{REMOTE_ADDR} eq "203.153.65.252"

SSLOptions +StrictRequire is like mod_auth_XXX_authoritative and stops apache 
falling through to basic authentication if our SSL conditions are not met.  
And those conditions are that a useful cipher is used, that the cert 
organisation is ViaGold, that the organisational unit of the holder is 
techstaff or similar OR that the client address is on our subnet.