Hack 47 Encrypt IMAP and POP with SSL

figs/expert.gif figs/hack47.gif

Keep your email safe from prying eyes while also protecting your POP and IMAP passwords.

Having your email available on an IMAP server is invaluable when you have to access your email from multiple locations. Unlike POP, IMAP stores all your email and any folders you create on the server, so you can access all of your email from whatever email client you decide to use. You can even set up a web-based email client so that messages can be accessed from literally any machine with an Internet connection and a web browser. But more than likely, you will need to cross untrusted networks along the way. How do you protect your email account password and email from others with less than desirable intentions? You use encryption, of course!

If you already have an IMAP or POP daemon installed that does not have the ability to use SSL natively, you can use stunnel [Hack #76] to wrap the service in an SSL tunnel. If you're starting from scratch, you have the luxury of choosing a daemon that has SSL support compiled directly into the binary.

One daemon that supports SSL out of the box is the University of Washington's IMAP daemon, otherwise known as UW-IMAP (http://www.washington.edu/imap/). The IMAP daemon is included with their IMAP software distribution.

To compile and install the IMAP daemon, download the compressed tar archive and run commands similar to these:

$ tar xfz imap.tar.Z 

$ cd imap-2002e

$ make lnp SSLDIR=/usr SSLCERTS=/usr/share/ssl/certs

The Makefile target specifies what type of system you are building for. In this case, lnp stands for Linux-PAM. Other popular Makefile targets are bsf for FreeBSD, bso for OpenBSD, osx for Mac OS X, sol for Solaris, and gso for Solaris with GCC. The SSLDIR variable is used to set the base directory for your OpenSSL installation. By default, the Makefile is set to use /usr/local/ssl, which would cause it to look for the libraries in /usr/local/ssl/lib and the headers in /usr/local/ssl/include. If a version of OpenSSL came installed with your operating system and you want to use that, you will most likely need to use SSLDIR=/usr as shown in the example. The SSLCERTS variable is used to tell the imapd and popd where to find their SSL certificates.

If the compile aborts due to errors, look for a message similar to this:

In file included from /usr/include/openssl/ssl.h:179,

                 from osdep.c:218:

/usr/include/openssl/kssl.h:72:18: krb5.h: No such file or directory

In file included from /usr/include/openssl/ssl.h:179,

                 from osdep.c:218:

This means that the compiler cannot find the Kerberos header files, a known issue with newer versions of Red Hat Linux. This happens because the files are located in /usr/kerberos/include, which is a nonstandard directory on the system.

To tell the compiler where to find the headers, use the EXTRACFLAGS variable. The make command from the previous example will now look like this:

$ make lnp SSLDIR=/usr SSLCERTS=/usr/share/ssl/certs \ 


After the binaries have been built, become root and copy them to a suitable place:

# cp imapd/imapd ipopd/ipopd /usr/local/bin

Next, to create self-signed certificates, run these two commands:

$ openssl req -new -x509 -nodes \

 -out /usr/share/ssl/certs/imapd.pem \

 -keyout /usr/share/ssl/certs/imapd.pem -days 3650

$ openssl req -new -x509 -nodes \

 -out /usr/share/ssl/certs/ipopd.pem \

 -keyout /usr/share/ssl/certs/ipopd.pem -days 3650

Alternatively, you can sign the certificates with your own Certificate Authority [Hack #45] . However, if you go this route, you must change the certificates' names to imapd.pem and ipopd.pem.

All that's left to do now is edit your /etc/inetd.conf file so that inetd will listen on the correct ports and spawn imapd and ipopd when a client connects. To do this, add the following lines at the end of the file:

imaps stream tcp nowait root /usr/libexec/tcpd /usr/local/bin/imapd

pop3s stream tcp nowait root /usr/libexec/tcpd /usr/local/bin/ipop3d

Now tell inetd to reload its configuration:

# kill -HUP `ps -ax | grep inetd | grep -v grep \

  | awk '{print $1}'`

That's the final task for the server end of things. All you need to do now is configure your email clients to connect to the secure version of the service that you were using. Usually, there will be a Use Encryption, Use SSL, or some other similarly named checkbox in the incoming mail settings for your client. Just check the box, reconnect, and you should be using SSL now. Be sure your client trusts your CA cert, or you will be nagged with annoying (but important!) trust warnings.