#!/bin/blog

February 2, 2010

Dealing with lengthy SSL certificate chains

Filed under: Security — Tags: , , , , — martin @ 4:16 pm

Comodo delivers the cheapest widely-recognized certificates (available e.g. via psw.net), second only to the famed StartSSL Free CA, which I haven’t had the guts to try out so far. What I got from Comodo, is my server cert, along with no less than three intermediate certificates:

AddTrustExternalCARoot.crt
issuer= /C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root
subject= /C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root

UTNAddTrustServerCA.crt
issuer= /C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root
subject= /C=US/ST=UT/L=Salt Lake City/O=The USERTRUST Network/OU=http://www.usertrust.com/CN=UTN-USERFirst-Hardware

PositiveSSLCA.crt
issuer= /C=US/ST=UT/L=Salt Lake City/O=The USERTRUST Network/OU=http://www.usertrust.com/CN=UTN-USERFirst-Hardware
subject= /C=GB/ST=Greater Manchester/L=Salford/O=Comodo CA Limited/CN=PositiveSSL CA

Server.crt
issuer= /C=GB/ST=Greater Manchester/L=Salford/O=Comodo CA Limited/CN=PositiveSSL CA

You can obtain this information by running, e.g.:

for c in $(ls *crt); do echo -e "\n$c"; openssl x509 -issuer -subject -noout -in $c; done

Note how I have ordered them from the root certificate on top to the server certificate on the bottom, each being the issuer of the succeeding one. Did I say root certificate? Good news then: AddTrust is the root certificate, hence it does not need to be deployed, which leaves me with a chain of two.

I will need to deploy the certificates into Postfix and Dovecot, which use an all-in-one file that contains the complete chain, including the server certificate. Other servers, such as the Apache webserver, use a server certificate file and a separate file containing the intermediate certificates. Which is the method I prefer. But you just can’t always get what you want. 😉

I learned the hard way that certificate order does matter. RFC 5246 states:

The sender’s certificate must come first in the list. Each following
certificate must directly certify the one preceding it. Because
certificate validation requires that root keys be distributed
independently, the self-signed certificate that specifies the root
certificate authority may optionally be omitted from the chain,
under the assumption that the remote end must already possess it
in order to validate it in any case.

Thus, the all-in-one file needs to start with the server certificate, followed by the certificate that issued the server certificate, all the way down to the one that is farthest away from the server certificate: 1) Server, 2) PositiveSSLCA, 3) UTNAddTrustServerCA

For servers that use a separate intermediate file, the order is the same, with the difference that the server certificate resides in its own file.

I recommend to maintain the subject and issuer information of all components of the all-in-one file so it won’t have to be dissected at a later point in order to understand what it contains. My starting point is the server cert, to which I will append the intermediate certs:

1) Locate the issuing certificate of the server cert (-> output above) and append the respective certificate to the server cert.
2) Locate the issuing certificate of the previously appended certificate and append it to the server cert.
3) Repeat until the root CA certificate has been reached.

In my case:
openssl x509 -in server.crt -subject -issuer > server-allinone.crt
openssl x509 -in PositiveSSLCA.crt -subject -issuer >> server-allinone.crt
openssl x509 -in UTNAddTrustServerCA.crt -subject -issuer >> server-allinone.crt

Now I have a handy file ready for deployment:

subject= /OU=Domain Control Validated/OU=PositiveSSL/CN=server
issuer= /C=GB/ST=Greater Manchester/L=Salford/O=Comodo CA Limited/CN=PositiveSSL CA
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
subject= /C=GB/ST=Greater Manchester/L=Salford/O=Comodo CA Limited/CN=PositiveSSL CA
issuer= /C=US/ST=UT/L=Salt Lake City/O=The USERTRUST Network/OU=http://www.usertrust.com/CN=UTN-USERFirst-Hardware
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
subject= /C=US/ST=UT/L=Salt Lake City/O=The USERTRUST Network/OU=http://www.usertrust.com/CN=UTN-USERFirst-Hardware
issuer= /C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----

The main point is that you must understand how the certificates relate to each other. The issuer and subject fields are the key all the way through the procedure.

November 12, 2009

IMAP on the iPhone with SSL client certificates

Filed under: iphone — Tags: , , , — martin @ 11:02 pm

The IMAP server in my office is configured to not simply accept username/password authenticated connections from the internet. As an additional security measure, it requires the client to present a valid SSL client certificate, issued by the internal CA, resulting in mutual SSL authentication.

The Mail client on the iPhone, on the other hand, does not support SSL client certificates. While it is possible to deploy a client certificate using the iPhone configuration utility, this cert will only be presented to web servers, but not to mail servers.

My workaround is to use stunnel, the universal SSL wrapper, on the iPhone. This, of course, requires the iPhone to be jailbroken. I’ll leave the jailbreak and installation of stunnel as an excercise to you. 🙂

I’m running stunnel as the “mobile” user, thus all the required files reside in /var/mobile. The files are:

– The stunnel configuration: /var/mobile/stunnel.conf
– The SSL certificate: /var/mobile/cert.pem
– The key matching the SSL certificate: /var/mobile/key.pem

Stunnel is configured as an SSL client. The commented-out lines may be useful for troubleshooting. I have added 10000 to the regular IMAP and SMTP ports so they are beyond the privileged port range that may only be used by root.

cert=/var/mobile/cert.pem
key=/var/mobile/key.pem
pid = /var/mobile/stunnel.pid
sslVersion = TLSv1
# Resolve server hostname at every reconnect,
# not only on startup (for dyndns!):
delay = yes
#foreground = yes
#debug = 7

[imap]
accept=127.0.0.1:10143
connect=example.dyndns.org:993
client=yes

[smtp]
accept=127.0.0.1:10025
connect=example.dyndns.org:465
client=yes

My key is password protected, thus I start stunnel from Mobile Terminal after bootup:

stunnel stunnel.conf

Having a method for starting stunnel automatically with passphrase-less keys would be nice, but has no priority for me. Using a LaunchDaemons entry for this shouldn’t be a problem anyway.

The mail settings on the iPhone are configured to access IMAP and SMTP on localhost, port 10143 and 10025, respectively. SSL encryption is turned off for both.

This setup is surprisingly robust. The current running stunnel daemon has been started 4 days ago and has already survived a few changes of the dynamic IP address of the mail server. I have not had a single hiccup since I figured out that I need the “delay=yes” option in the configuration file to keep up with DynDNS changes. If your mail server isn’t on a dynamic IP address, all the better.

Create a free website or blog at WordPress.com.