Mail SSL Setup
From Wiki99
↑ Computers ↑
← prev: Mail ssh Setup
next: Fetchmail →
Contents |
Introduction to SSL
SSL solves a slightly different problem from ssh, and it worth considering how the two differ so that you fully understand SSL.
Salient points regarding an ssh connection
Once an ssh connection is established between two machines, three important things have been established
- an encrypted link has been set up between the two machines
-
the server has been authenticated to the client
-
the client has been authenticated to the server
All this happened within a context of:
having one or a few individuals wanting authentication and security between
a few machines; and
the initial links being set up through some ad hoc mechanism for creating
and then distributing public and private keys across various machines.
How does SSL differ from these ssh points?
SSL wants to solves two particular problems:
- encryption (so that when I buy things from amazon.com, my credit card info can't be read from someone snooping the packets going into amazon)
-
authentication of the server (so when I connect to amazon.com, I can be sure that I'm really speaking to amazon.com)
SSL gives up on trying to also have, as part of its solution, our third property of ssh, ie authentication of the client with the server. Once you connect to the server using SSL, you will need to authenticate yourself with the server using some alternative mechanism (presenting a userID and password, using a web cookie etc).
SSL also does a less than ideal job of the second of our ssh properties, namely authentication of the server. You'll understand this better once you've gone through the details of how to set up SSL.
On the plus side, SSL is scalable to situations where many (perhaps anonymous) clients need to contact a server, ie it doesn't require any previous interaction between the server and the client.
Finally whereas ssh can be used transparently, by creating network tunnels between programs that have no idea that their data is being encrypted, SSL requires support for the protocol to be compiled into the relevant servers. Fortunately for us, that has been done for the various servers we care about.
Quick introduction to SSL concepts
The basic idea behind SSL is that a computer, which claims to have certain
properties (to be a particular web site, to be run by a particular person,
to have a particular geographic location etc), is certified as having
these properties by a certifying authority.
The proof that the certifying authority agrees that the computer has the
properties it claims is a particular file called a certificate listing these
properties along with a bunch of what looks like random characters.
The analogy here is that that the certifying authority is something like a government, and the certificate it gives your computer is something like a passport. A passport, like a certificate, lists a bunch of properties. Additionally a passport also includes things that makes it difficult to forge, for example watermarks and holograms printed behind the properties (photograph, name, etc) listed in the passport. The apparently random numbers of the certificate likewise make it difficult to forge a certificate, being dependent on the properties listed in the passport, and on the certifying authority.
Once a computer has a certificate, when a client wants to create an SSL connection, some sort of mutual negotiation takes place, the end result of which is that the client
- knows that this server is indeed what it claims to be
-
according to whatever certifying authority created the certificate, and
-
there exists an encrypted connection between the two machines
This whole scheme has a pretty obvious flaw, namely how do I know anything about the certifying authority that provided the certificate, and how do I know that someone didn't lie to them about being amazon.com?
We have the same problem with passports, of course. If someone presents you
with what they claim to be a passport from the Republic of Bitango, how do
you know that this is a real country? OK, that was easy.
Now what if the passport says it is from the State of Palestine?
Is there a State of Palestine legitimately producing passports?
How about the State of Chechnya?
or the State of Trans-Dnistria?
or the State of Taiwan
What's the difference between a "real" country and some random group printing
passports. The analogy to certifying authorities should be obvious.
But the fact that this is an unsolved problem shouldn't bother us. What we really care about is just getting an encrypted connection to our server, and the fact that we have to do some extra work, to "certify" that we are who we claim to be, is just some minor setup hassle.
Setting up SSL
So let's get to work. (Most of this material now is taking from http://www.macosxhints.com/article.php?story=20041129143420344)
We have six main steps ahead of us:
- Create a workspace
-
Creating a Certificate Authority
-
Generating a Domain Private Key
-
Generating a Domain Certificate Request
-
Signing the Certificate Request
-
Place files appropriates and tighten permissions
What we want, at the end of this, is a certificate which is a particular,
standalone file. A certificate certifies a server, and so can (perhaps with
some minor modifications) be used by different programs on the server, for
example by both bincimap and apache.
More specifically, a certificate
certifies a fully qualified domain, and so if you want to use multiple
domains, for example mail.bluecloud.com and
www.bluecloud.com each will need a separate certificate.
But if you use the same domain name, bluecloud.com, for both, which
is certainly the easiest way to do things, you will only need a single
certificate for that domain, that can be used by all your programs.
To get to the certificate, we need a certifying authority. If one were engaged in ecommerce or such, one would go to a "legitimate" certifying authority, who would charge one for this certificate. In our case, however, we will just create our own fake certifying authority (like deciding we'll invent our own country and print our own passports).
Create a workspace
First we need a workspace, a working directory. When everything is done, we will move our certificate to the appropriate place in the file system, and lock down our work so that outsiders can't see what we did. But for now, we'll create a standard directory to hold the files we create as we work. It should be of some comfort to you that the work we engage in will not create any files or make other changes to the system outside this working directory.
cd ~
mkdir ssl_certificates.d
cd ssl_certificates.d
Create a certifying authority
We now run a script that creates a dummy certifying authority called
demoCA.
(You may not like this name, hardwired into the script, but you'll never see
it again after this work is done, and the alternative of calling the various
command-line tools directly is a lot more hassle.)
Enter
/System/Library/OpenSSL/misc/CA.pl -newca
You will see output like this:
CA certificate filename (or enter to create)
Making CA certificate ...
Generating a 1024 bit RSA private key
..++++++.................................++++++
writing new private key to './demoCA/private/cakey.pem'
Enter PEM pass phrase: (enter a new secure password)
Verifying - Enter PEM pass phrase: (reenter the same password)
-----
You are about to be asked to enter information that will be incorporated
into your certificate request. What you are about to enter is what is
called a Distinguished Name or a DN. There are quite a few fields but
you can leave some blank. For some fields there will be a default value,
If you enter '.', the field will be left blank.
In theory you can put whatever nonsense
you want in these fields, but in practice you probably want to stick reasonably
close to the truth, especially if people other than yourself will, at some
point be viewing your certificates.
The only part of filling this form in that is not obvious is that the
Common Name refers to a domain name, which is the domain name of the
certifying authority. In the real world this would be the name of some
appropriate company, but we'll just use our domain name.
-----
Country Name (2 letter code) [AU]: US
State or Province Name (full name) [Some-State]: CA
Locality Name (eg, city) []: Los Angeles
Organization Name (eg, company) [Internet Widgits Pty Ltd]: Kramerica Inc
Organizational Unit Name (eg, section) []: I leave this blank
Common Name (eg, YOUR name) []: bluecloud.com
Email Address []: admin@bluecloud.com
With this done, you will find the following material has been created in your workspace directory:
ssl_certificates.d/demoCA (a directory)
ssl_certificates.d/demoCA/cacert.pem
ssl_certificates.d/demoCA/certs
ssl_certificates.d/demoCA/crl
ssl_certificates.d/demoCA/index.txt
ssl_certificates.d/demoCA/newcerts
ssl_certificates.d/demoCA/private
ssl_certificates.d/demoCA/serial
You'll never need to look at this stuff, it just needs to be there.
Most of these are used internally by the script.
The two items that might be of some interest are the key file, a magic random
number that (hopefully) secures everything we're doing, which lives in
ssl_certificates.d/demoCA/private/cakey.pem and which looks something
like
-----BEGIN RSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: DES-EDE3-CBC,B7DF61666B274AED usqqLmPIQdFYyDoawb1YD5oFzWQo2dvT8atrnm/rDCKypyO57zsRbdRh4BjY2X0b VRejJD2rf9H1dFqAs/JA87647Zqqmxlub+l5QpTLrzbIkMfsfaJnIAuOWayz0+Lk . . . HNJFsW1fRa3zAoVCqCf4LnnlKAvTPDA3XHlA6Tdo8qehU0pCZJyrUv== -----END RSA PRIVATE KEY-----
and the certificate authority file, ssl_certificates.d/demoCA/cacert.pem, which looks something like
-----BEGIN CERTIFICATE----- MIIEgDCCA2igAwIBAgIJAJrq8QYeqM0pMA0GCSqGSIb3DQEBBAUAMIGGMQswCQYD . . . xkGX8UJslMJplR9Z/ZFn8I2kEmh/LYw0E6S+TtscZ6fI1xQIV2By4Qw= -----END CERTIFICATE-----
Create a domain private key
Now we create a private key for our domain. In fact we'll generate two such keys, one password protected, one not. Again this is just infrastructure we need, it's not of much interest in itself.
Enter the line below (you can change domain.key to some other name if you prefer).
openssl genrsa -des3 -out domain.key 1024
which outputs
Generating RSA private key, 1024 bit long modulus
....................................++++++
.....................++++++
e is 65537 (0x10001)
Enter pass phrase for domain.key: (enter a new secure password)
Verifying - Enter pass phrase for domain.key: (reenter the same password)
now enter
openssl rsa -in domain.key -out domain.nopass.key
to create a non-password protected version of this same key. This outputs:
Enter pass phrase for domain.key: (enter the secure password created in the previous step)
writing RSA key
In this step we created two files:
ssl_certificates.d/domain.key
ssl_certificates.d/domain.nopass.key
The password protected key looks pretty much the same as the one generated when we created the certifying authority. The non-password protected key doesn't look much different either:
-----BEGIN RSA PRIVATE KEY----- MIICXAIBAAKBgQCtwATRck6dZOzmrkfqPj9hDTT14pLCOtX2WM/IhYS+KaMHI7nx . . . iItd9zjZnezo267sVGYoByGKH0/EYNKKHosgMJntWVZ= -----END RSA PRIVATE KEY-----
Create a certificate request
Now we create a certificate request which holds the information we want the certifying authority to place in our final certificate.
Enter the following command-line. Note that the name of the request file to be created, ie newreq.pem, should not be altered.
openssl req -config /System/Library/OpenSSL/openssl.cnf \
-new -key domain.key -out newreq.pem
You'll get output like below, which again asks you to enter some fields.
In theory these could be different from the values you entered in step 2.
Those values described the dummy certifying authority we are creating,
and, really, could be pretty much anything.
These values describe our host machine and do need to correspond to
reality.
At the very least, the Common Name entered below really does need to equal
the domain name of your server.
In practice, you should just enter the same (values in both places.
Enter pass phrase for server.key: (enter the secure password created in step 2)
You are about to be asked to enter information that will be incorporated
into your certificate request. What you are about to enter is what is
called a Distinguished Name or a DN. There are quite a few fields but
you can leave some blank. For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]: US
State or Province Name (full name) [Some-State]: CA
Locality Name (eg, city) []: Los Angeles
Organization Name (eg, company) [Internet Widgits Pty Ltd]: Kramerica Enterprises
Organizational Unit Name (eg, section) []:
Common Name (eg, YOUR name) []: bluecloud.com
Email Address []: admin@bluecloud.com
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []: leave blank
An optional company name []: leave blank
Files generated in this step:
ssl_certificates.d/newreq.pem
After what we've seen so far, the certificate request should not surprise us much. It looks like
-----BEGIN CERTIFICATE REQUEST----- MIIBuzCCASQCAQAwezELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMREwDwYDVQQH . . . 1V0+L0VE16hpyMyzlufU -----END CERTIFICATE REQUEST-----
Sign the certificate request
We now need to submit our request to the certifying authority and have it generate a certificate for us. Enter
/System/Library/OpenSSL/misc/CA.pl -signreq
You'll get output as below. Note that the certificate generated will be
valid for one year. If this is not acceptable, you need to change the
default duration in the file /System/Library/OpenSSL/openssl.cnf.
(The MacOSXHints page says you can set the duration of the certificate
using a command-line option, but it is wrong.)
Using configuration from /System/Library/OpenSSL/openssl.cnf
Enter pass phrase for ./demoCA/private/cakey.pem: (enter the secure password created in step 2)
Check that the request matches the signature
Signature ok
Certificate Details:
Serial Number: 1 (0x1)
Validity
Not Before: Nov 29 04:00:05 2007 GMT
Not After : Nov 27 04:00:05 2008 GMT
Subject:
countryName = as entered
stateOrProvinceName = as entered
localityName = as entered
organizationName = as entered
commonName = as entered
emailAddress = as entered
X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
Netscape Comment:
OpenSSL Generated Certificate
X509v3 Subject Key Identifier:
D8:C4:76:37:6F:8C:FA:8E:62:95:2C:A3:2E:E9:CC:5C:24:E2:5B:DB
X509v3 Authority Key Identifier:
keyid:DB:12:B4:DB:77:03:D1:64:DA:87:8A:61:79:AA:38:17:E4:7E:6B:ED
DirName:
emailAddress=
serial:00
Certificate is to be certified until Nov 27 04:00:05 2008 GMT (365
days)
Sign the certificate? [y/n]: (type y to confirm)
1 out of 1 certificate requests certified, commit? [y/n] (type y to confirm)
Write out database with 1 new entries
Data Base Updated
Signed certificate is in newcert.pem
Files generated at this point:
ssl_certificates.d/newcert.pem
which is a little more interesting as a file, looking like
-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQCtwATRck6dZOzmrkfqPj9hDTT14pLCOtX2WM/IhYS+KaMHI7nx
.
.
.
iItd9zjZnezo267sVGYoByGKH0/EYNKKHosgMJntWVQ=
-----END RSA PRIVATE KEY-----
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
a8:90:1b:54:48:9e:76:87
.
.
.
-----BEGIN CERTIFICATE-----
MIIDgjCCAuugAwIBAgIJAKiQG0RInhZnMA0GCSqGSIb3DQEBBAUAMHsxCzAJBgNV
.
.
.
r1SMsnogI9cXWXZzg0GkCTjAMQmdbkitWxpOTSl7BSZAfErw7xo=
-----END CERTIFICATE-----
This certificate file is (with some caveats) the standalone file we need to get SSL working.
Cleanup
At this point it might be nice to clean up all the domain specific material we have created into a new directory, and then secure all our work.
Type (you can call your new directory anything you like; I call it domain.d)
mkdir domain.d
mv domain.key domain.nopass.key newreq.pem newcert.pem domain.d
From now on we need to be superuser. So:
sudo su
We should store all this SSL material somewhere that's not visible to most users. A reasonable place is the home directory for root, ie /var/root, though this is your choice.
mv ~/ssl_certificates.d /var/root
chown -r root /var/root/ssl_certificates.d
chmod 700 /var/root/ssl_certificates.d
binc
binc configuration files
I said that the certificate file we created above was standalone, but that's not quite true. binc requires a slight variation on this file, a different single file that holds both the (non-password encrypted) key we generated above, and the certificate we were given, so let's created that file. Type
cd /var/root/ssl_certificates.d/domain.d
cat domain.nopass.key newcert.pem > bincimap.pem
We now need to tell binc to utilize SSL based on this certificate. I found it easiest to copy over the entire certificate to the binc prefs directory, otherwise you have to screw around to get the permission right so that binc can read the file at startup. Type
cd /opt/local/etc/bincimap
cp /var/root/ssl_certificates.d/domain.d/bincimap.pem .
Make sure (using ls -la) that binc can read this file, ie that it
is readable by other.
With this standalone certificate file in a place where binc can read it, the
final step is to modify the binc config file.
Type
pico bincimap.conf
Look for the lines
SSL {
pem file = "/opt/local/etc/bincimap/bincimap.pem", /* private key and
Ideally the pem file referred to is exactly as given above which, fortunately, is exactly the pem file we just created in binc's configuration folder, so no actual change to bincimap.conf is necessary. If the file listed is NOT as shown above, change the line in the config file to read as above.
binc startup
Recall that we created a launchd file that has binc listening to the IMAP port (port 143), restricted to only accept connections from local host. We now need to create a second launchd file that has binc listening on the secure IMAP port (port 993), and accepting SSL connections from the outside world, not just localhost. So (while still superuser) type
cd /Library/LaunchDaemons
pico imaps.plist
and enter
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>imaps</string>
<key>Nice</key>
<integer>-7</integer>
<key>ProgramArguments</key>
<array>
<string>/opt/local/bin/bincimap-up</string>
<string>--ssl</string>
<string>--conf=/opt/local/etc/bincimap/bincimap.conf</string>
<string>--logtype=syslog</string>
<string>--</string>
<string>/opt/local/bin/checkpassword-pam</string>
<string>-s</string>
<string>bincimap</string>
<string>/opt/local/bin/bincimapd</string>
</array>
<key>ServiceDescription</key>
<string>binc IMAPs xinetd server</string>
<key>Sockets</key>
<dict>
<key>imap993</key>
<dict>
<key>SockServiceName</key>
<string>imaps</string>
</dict>
</dict>
<key>inetdCompatibility</key>
<dict>
<key>Wait</key>
<false/>
</dict>
</dict>
</plist>
Now use Lingon to start this new config file, or, if you prefer to do things oldstyle, type in
launchctl load /Library/LaunchDaemons/imaps.plist
At this point we're done being superuser and should probably kill the shell in which we are superuser using exit or closing that terminal window or suchlike.
You will also, if you are using any sort of NAT as most of us are, need to tell your NAT box (eg an Airport base station) to route incoming requests on port 993 to your server's local network IP address and port 993, as we discussed much earlier when discussing IP addressing and NAT.
testing
At this point we should be done and things should just work.
From a remote machine (so we're not testing a localhost connection):
First see if port 993 is available to unencrypted connections.
Type
telnet bluecloud.com 993
You should get an attempted connection that waits for a few seconds and then gives up and disconnects you, with output like
Trying 62.166.134.215... Connected to bluecloud.com. Escape character is '^]'. Connection closed by foreign host.
Now connect using an SSL aware connection:
openssl s_client -connect bluecloud.com:993
You should now see a whole lot of debugging output that starts with
CONNECTED(00000003)
and ends with
Verify return code: 21 (unable to verify the first certificate)
---
- OK Welcome to Binc IMAP Copyright (C) 2002-2005 Andreas Aardal Hanssen at 2007-10-12 23:23:34 -0700
The last line is no longer SSL output but is the connection to binc. At this point you need to login to binc with a userID and password --- if you don't do so within a minute binc will give up and disconnect.
Mail.app
Now try things in Mail.app. For your Mail.app account,
- under the Account Information tab, change the Incoming Mail Server field (which was set to localhost) to the name of your server (eg bluecloud.com)
-
under the Advanced tab, change Port from 143 to 993, and check the box marked Use SSL
Quit Mail.app, and restart it.
What will now happen is that the app will complain that it is being asked to accept a certificate from a certifying authority that is has never heard of. You can tell it to just go ahead, but this warning message is going to appear every time you restart the program, so presumably you'd like to get rid of it.
The way you do this is that you need to tell OS X to trust the dummy certifying authority you created way up in step 2. To do this, you need to add the pem file describing our dummy CA in the Keychain application. The easiest way to do this is
-
On the server machine (or using ssh), copy the .pem file describing
the certifying authority to somewhere where you can read it without special
permissions (like your personal desktop on the server).
So
sudo cp /var/root/ssl_certificates.d/demoCA/cacert.pem ~yourusername/Desktop
-
Then, on every client machine where you plan to use Mail.app:
-
use AppleShare to mount your directory on the server
-
in Finder, doubleclick on the cacert.pem file in your desktop directory on the server.
This doubleclicking will launch Keychain.app which will ask if you want to add the certificate to a keychain.
From the popup menu, choose the last option, namely X509Anchors, and then hit the OK button.
Keychain will ask for your password, then add the dummy CA you created to its list of trusted CAs. -
With this done on your various client machines, it's probably best to now delete the cacert.pem file.
FWIW no-one yet seems to know much about how keychain on a Mac syncs with i Phone, but either some syncing occurs, or iPhone just doesn't bother telling you about problematic certificates, because the net result after doing all this is that your SSL secured mail connection will also work just fine with an iPhone.

