This means, the SMTP server needs new certificates. So I started investigating how this can be done. First thing I noticed is, that there are two SSL/TLS implementations in the open source world. First the above mentioned GnuTLS and second the honorable OpenSSL. Why is this?
Wikipedia knows the story. The OpenSSL article states:
The OpenSSL license requires the phrase "This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit" to appear in advertising material and any redistributions [...]. Due to this restriction it is incompatible with the GPL.And the GnuTLS article says:
GnuTLS was initially created to allow applications of the GNU project to use secure protocols such as TLS. Although OpenSSL already existed, OpenSSL's license is not compatible with the GPL.I don't know any further details but I hardly believe that the OpenSSL was not asked to change their license. Must be important to them to have this little sentence included everywhere. Anyway, we now have the same functionality implemented and distributed twice.
I decided to use GnuTLS without having much arguments for that. I went through the documentation and here is how it worked. I created a new root certificate authority and new certificates for Postfix, Apache, lighttpd and ejabberd.
First of all we have to get a grip on all those abbreviations:
- X.509 is the standard behind the whole thing with certificates, signatures and the trust model of TLS/SSL.
- DER stands for Distinguished Encoding Rules. It is an encoding which is used for certificates.
- PEM stands for Privacy-enhanced Electronic Mail. It is a file format which puts a simple header and a simple footer around the base64 encoded DER certificate or key.
- .cer and .crt are common file extension for certificate files.
- .key is a common file extension for private keys.
certtool --generate-privkey > ca.key.pem
If it takes too long help the system to gather entropy by using the keyboard, moving the mouse or causing some network traffic.
Next we need a certificate, which is the public key that we can pass around. As there is no other authority which validates the certificate, we have to sign the signature ourselves. This is done with (using zsh):
certtool --generate-self-signed --outfile ca.crt.pem \ --load-privkey ca.key.pem --template =( echo "cn = your name"; echo "ca"; echo "cert_signing_key"; echo "expiration_days = 3650"; )
cnis the common name of the certificate owner,
caindicates that this is a CA certificate,
cert_signing_keystates that this key will be used to sign other certificates and finally
expiration_daysdefines how long this certificate is valid.
Now we have two files, the secret
ca.key.pemand the public
ca.crt.pem. Next we want to create a certificate for the server. First thing to do, again is to create a secret key, the identity of the server.
certtool --generate-privkey > mail.spamt.net.key.pem
Next we create a corresponding certificate and sign it with the root CA:
certtool --generate-certificate \ --outfile mail.spamt.net.crt.pem \ --load-privkey mail.spamt.net.key.pem \ --load-ca-certificate ca.crt.pem \ --load-ca-privkey ca.key.pem \ --template =( echo "organization = spamt.net community"; echo "cn = mail.spamt.net"; echo "tls_www_server"; echo "encryption_key"; echo "expiration_days = 730"; )
organizationis - as far as I can tell - an arbitrary string identifying the organization of the subject.
cnagain is the common name and must match the domain name of the server, because the domain name is how clients identify the server. I am not sure about
tls_www_server, but I think this flag indicates that the certificate will be used by a TLS server, rather than a client.
encryption_keyis a flag which indicates that this certificate will be used to encrypt data. I didn't had much time to play around with the various options. This is the set that worked for me, maybe there are better choices.
Next we have to configure the server to use the given key and certificate file. In case of Postfix this are the options
smtpd_tls_key_file. In contrast to that lighttpd wants a single file with both information. Due to the PEM file format this is no problem. We simply have to
catboth files into a single new one.
Finally we want to distribute the certificate of our root CA through a authenticated channel to the users of the clients. They can import it in order to make an automated authentication possible. They can also check the validity of the certificates of the services manually with:
certtool --verify-chain \ --infile =(cat mail.spamt.net.crt.pem ca.crt.pem)
Some clients like firefox just present the certificate's fingerprint to the user if the corresponding root CA is not imported. For this and other cases it is convenient for the users to have this fingeprint at hand. The fingerprint of a certificate can be retrieved with:
certtool --certificate-info \ --infile mail.spamt.net.crt.pem \ | grep -A 1 fingerprint
Again is must be transmitted to them over an authenticated channel, otherwise the whole chain of trust is undercut.
Update: Now, two years later, the certicates have expired. To set a new expiration date, you can do the following:
mv mail.spamt.net.crt.pem mail.spamt.net.crt.pem.expired certtool --update-certificate \ --load-certificate mail.spamt.net.crt.pem.expired \ --outfile mail.spamt.net.crt.pem \ --load-ca-privkey ca.key.pem \ --load-ca-certificate ca.crt.pem