Firefox 3 is annoyingly picky about SSL certificates, which has been an issue for people trying to access my Trac wiki or Subversion repository. I finally had enough and decided to nail the problem. So here are clear steps for generating SSL certificates that will make Firefox 3 happy. I will be using Leopard’s Certificate Assistant for most of the certificate work, with a bit of openssl at the end. The primary source of information I used to determine the requirements for SSL server certificates and signing certificates up in the chain is Mozilla’s All About Certificate Extensions technote.
Creating a certificate authority
Although I haven’t tested a self-signed CA certificate as the SSL server’s certifiate, reading around the web suggests it will not make Firefox 3 happy. Since it doesn’t cost all that much time to do it, let’s generate a certificate authority.
- Open Keychain Access
- I’ve had issues with Certificate Assistant using my login keychain, so to avoid any problems, create a new keychain for certificates.
Use the Create a Certificate Authority… command from the Keychain Access > Certificate Assistant menu.
Enter the name of the CA certificate, select Self Signed Root CA as the type and make sure the Let me override defaults checkbox is checked.
Enter the desired serial number and validity period. Firefox 3 will actually remember certificate serial numbers and reject a new certificate with the same serial number as a previous certificate (coming from the same authority, that is), so make sure you’re keeping track of serial numbers.
The User Certificate Type must be set to SSL Server.
The other settings are for generating a pretty CA web page to let people make certificate requests for your new authority (you may want to use that), and to sign your certificate invitation.
Enter the basic contact information for the CA certificate. The Name (Common Name) field doesn’t have to be a valid domain name, since the CA certificate won’t be used by any server.
The default values for this step are fine.
This step allows to specify default key pair settings for any leaf certificate you create with the CA certificate as the root. The default values are fine.
The CA certificate must have a Key Usage Extension with at least the Signature and Certificate Signing capability bits set. If either one of those capabilities are not specified, Firefox 3 will reject any child certificate of the CA certificate.
This step allows to specify default key usage extension settings for any leaf certificate created with the CA certificate as the root. SSL server certificates must have at least the Key Encipherment and Key Agreement capability bits set. If either one of those capabilities are not specified, Firefox 3 will reject the certificate.
Although documentation suggests this may not be necessary, giving the CA certificate an extended key usage extension with at least the SSL Server Authentication capability bit set has no serious consequences and provides additional insurance that Firefox 3 will be happy. Note that the default value is All, which should include SSL Server Authentication, but again no harm done in being pedantic.
This step allows to specify default extended key usage extension settings for any leaf certificate created with the CA certificate as the root. SSL server certificates must have at least the SSL Server Authentication capability bit set. If that capability is not specified, Firefox 3 will reject the certificate.
The CA certificate must have a basic constraints extension with at least the Use this certificate as a certificate authority option specified. If it is not, Firefox 3 will reject any child certificate of the CA certificate.
This step allows to specify default basic constraints extension settings for any leaf certificate created with the CA certificate as the root. SSL server certificates must not have the Use this certificate as a certificate authority option specified (while having a basic constraints extension). If the extension is missing or that option is specified, Firefox 3 will reject the certificate.
Any certificate with the SSL Server type must have a subject alternate name extension specifying either the dNSName field or the iPAddress field. Obviously there are no special constraints on the value of either of those fields for the CA certificate.
Again, any certificate with the SSL Server type must have a subject alternate name extension specifying either the dNSName field or the iPAddress field. The value of those fields must match the domain name or IP address which clients will use to contact SSL servers using any child certificate of the CA certificate. Obviously, we will have to override this value when creating each such child certificate unless we’re creating them for the same server all the time. Nevertheless, Certificate Assistant requires a value to be specified to continue, so provide a reasonable default.
Select the keychain in which the CA certificate will be stored. If you want browsers using Keychain Services to accept child certificates of the CA certificate, check the On this machine, trust certificates signed by this CA checkbox. Note that, as the label implies, this will affect the trust setting for the CA certificate for the entire machine, not just your specific system user. Consider the consequences of that choice carefully. It is possible to change trust settings on a per-user basis.
We can finally appreciate the fruit of our labour. Double-clicking the CA certificate in Keychain Access will allow you to confirm that all the required settings, options and capabilities are properly configured. It should look like this:
Creating a SSL server leaf certificate
I will not repeat the entire sequence of operation presented for the CA certificate, but rather focus on the steps that are specific to the creation of a SSL server leaf certificate. Make sure to keep in mind the various restrictions mentioned above concerned leaf certificates, since we have to override the default values we specified during the creation of the CA certificate and Certificate Assistant is not nice enough to fill in those defaults .
Use the Create a Certificate… command from the Keychain Access > Certificate Assistant menu.
Enter the domain name that clients will be using to access the SSL server as the certificate’s name, and choose Leaf as the certificate type. Make sure to check Let me override defaults since we need to edit some of the certificate’s settings from the defaults we specified earlier.
Enter a serial number different than that of the CA certificate and different than that of any other leaf certificate you have already created, even if they were for the same domain. Firefox 3 checks and keeps track of certificate serial numbers and will reject a certificate re-using a serial number. Also make sure that the certificate type is set to SSL Server, otherwise Firefox 3 will reject the certificate.
The Name (Common Name) field must match the domain clients will use to connect to the SSL server, otherwise Firefox 3 will reject the certificate.
Select the CA certificate created earlier.
SSL server certificates must have a key usage extension with the Key Encipherment and Key Agreement bits set. If they are not, Firefox 3 will reject the certificate.
SSL server certificates must have an extended key usage extension with the SSL Server Authentication bit set. If it is not, Firefox 3 will reject the certificate.
SSL server certificates must have a basic constraints extension with the Use this certificate as a certificate authority option disabled.
SSL server certificates must have a subject alternate name extension with either the dNSName field or the iPAddress field specified. The values for those fields should match what clients will use to connect to the SSL server. In order words, the value for the dNSName field should match the value of the Name (Common Name) field of the certificate (specified in step 4) and the value iPAddress field should match the IP address to which the dNSName domain resolves.
We can once more appreciate the fruit of our labour. Double-clicking the certificate in Keychain Access will allow you to confirm that all the required settings, options and capabilities are properly configured. It should look like this:
Going from the keychain to Apache
As a common scenario, here’s the straightforward way to export certificates stored in a keychain in a format suitable for Apache’s mod_ssl.
- Select the desired certificate from the Certificates or My Certificates category in Keychain Access (with the containing keychain selected, of course). The certificate item should have a disclosure triangle which once expanded will reveal the certificate’s private key. Indeed, we need to export both the certificate and its private key.
- Use the File > Export Items… command.
Use the Personal Information Exchange (.p12) format to export the certificate.
Although you provide a password with which to encrypt the private key, since Apache requires it to be unencrypted in order to start automatically, simply don’t provide any password. You may want, however, to choose a secure export location, such as a private temporary folder that doesn’t get backed up by Time Machine or an encrypted disk image.
- Open Terminal.
- Run the following commands to export the certificate and the private key (unencrypted) to OpenSSL’s PEM format which mod_ssl requires.
openssl pkcs12 -in example.com.p12 -nokeys -nodes -out example.com.crt openssl pkcs12 -in example.com.p12 -nocerts -nodes -out example.com.crtkey
All that’s left to do is ship out the .crt and .crtkey files to your SSL server and to securely delete all 3 files (.p12, .crt and .crtkey) from your local computer.
Loose ends because Firefox 3 can’t bother to fully support Mac OS X
When you connect with Firefox 3 to your SSL server with its shiny new certificates, Firefox 3 is still going to give you one of its famous gray error pages, stating that the certificate authority that signed the server’s certificate is not trusted. This is because, unlike every other browser for Mac OS X, Firefox can’t bother to use Keychain Services to verify certificate trust and therefore doesn’t know anything about the CA certificate stored in one of your keychains.
However this is a simple matter to fix. In the same error page, click on the Or you can add an exception… link, then on the Add Exception button. In the dialog that follows, first click on the Get Certificate button, make sure the Permanently store this exception checkbox is checked and finally click on the Confirm Security Exception button.
I’ll take this time to mention that that dialog is so poorly designed, with the Cancel button on the right of the dialog and of the “confirm action” button, contrary to Mac OS X HIG guidelines, not to mention the default button is that Get Certificate button which itself shouldn’t even be there – Firefox 3 should clearly fetch the certificate automatically. End of design commentary .
After that, Firefox 3 will trust the certificate and you should be good to go. You could also export the CA certificate and add it to Firefox 3′s list of trusted roots, an exercise I leave to the reader.