Configuring SMTP AUTH and TLS in Postfix

To setup AUTH means configuring SASL for your MTA.  Once this is tested you can go ahead and add TLS encryption.  (It is easier to trouble-shoot AUTH without encrypting first.)  Here’s the steps on Fedora Core 5 to make use Postfix is running at the only MTA, to configure SASL for it, to create a PKI CA certificate used in turn to create a PKI email certificate, and finally to configure Postfix for SASL and for TLS and to test it all.

Since the initial AUTH tests will send usernames and passwords in the clear, first create a dummy test account to use:

/etc/postfix# useradd -c 'Anne User' -m auser
/etc/postfix# passwd auser
Changing password for user auser.
New UNIX password: secret
BAD PASSWORD: it is based on a dictionary word
Retype new UNIX password: secret
passwd: all authentication tokens updated successfully.

Next configure Postfix as the only MTA (initially only listening on localhost):

/etc/postfix# alternatives --config mta

There are 3 programs which provide 'mta'.

  Selection    Command
-----------------------------------------------
*+ 1           /usr/sbin/sendmail.sendmail
   2           /usr/sbin/sendmail.exim
   3           /usr/sbin/sendmail.postfix

Enter to keep the current selection[+], or type selection number: 3
//etc/postfix# /etc/init.d/sendmail stop
Shutting down sm-client:                    [  OK  ]
Shutting down sendmail:                     [  OK  ]
/etc/postfix# chkconfig sendmail off
/etc/postfix# chkconfig postfix on
/etc/postfix# /etc/init.d/postfix start
Starting postfix:                           [  OK  ]

Now configure SASL and Postfix for SMPT AUTH, using PAM as the authentication method.  That means only system users will be able to authenticate, but we can configure PAM to control how that happens.  Since PAM wants a username and password, the only SASL mechanism we will accept is PLAIN.  While not safe by itself later we will add TLS encryption:

/etc/postfix# cp main.cf main.cf.ORIG
/etc/postfix# vi main.cf
/etc/postfix# postfix check
/etc/postfix# diff main.cf.ORIG main.cf
106c106
< #inet_interfaces = all
---
> inet_interfaces = all
109c109
< inet_interfaces = localhost
---
> #inet_interfaces = localhost
666a667,681
>
> # Support SMTP AUTH (via SASL):
> # (also must configure /usr/lib/sasl2/smtpd.conf with the line:
> #    pwcheck_method: saslauthd
> # and make sure saslauthd is started with the "-a pam" argument; this
> # is the default on Fedora Core 5 /etc/sysconfig/saslauthd.
> # Finally make sure saslauthd is started before postfix at boot time.)
>
> smtpd_sasl_auth_enable = yes
> smtp_sasl_security_options = noanonymous
> broken_sasl_auth_clients = yes
> smtpd_sasl_authenticated_header = yes
> smtpd_sasl_local_domain = $myhostname
> smtpd_recipient_restrictions =
>    permit_mynetworks permit_sasl_authenticated reject_unauth_destination

/etc/postfix# vi /usr/lib/sasl2/smtpd.conf
/etc/postfix# vi /etc/sysconfig/saslauthd
/etc/postfix# chkconfig saslauthd on
/etc/postfix# /etc/init.d/saslauthd start
Starting saslauthd:                         [  OK  ]

/etc/postfix# postfix reload
/etc/postfix# printf 'auser\0auser\0secret' | base64
YXVzZXIAYXVzZXIAc2VjcmV0

/etc/postfix# telnet whoopie 25
Trying 192.168.0.5...
Connected to whoopie.kaos.coop (192.168.0.5).
Escape character is '^]'.
220 whoopie.kaos.coop ESMTP Postfix
EHLO localhost
250-whoopie.kaos.coop
250-PIPELINING
250-SIZE 10240000
250-VRFY
250-ETRN
250-AUTH PLAIN LOGIN
250-AUTH=PLAIN LOGIN
250 8BITMIME
auth plain YXVzZXIAYXVzZXIAc2VjcmV0
235 Authentication successful
quit
221 Bye
Connection closed by foreign host.

Finally it is time to add encryption.  Openssl no longer comes with a CA.pl script (which had an option of "--newreq-nodes" to create certificates without encrypting the key file) but it does provide a more limited "CA" shell script (it just has "--newreq" option) you can modify.

First make a backup copy of that script.  Then edit the script, finding the part that says:

 -newreq)
   # create a certificate request
   $REQ -new -keyout newkey.pem -out newreq.pem $DAYS
   RET=$?
   echo "Request is in newreq.pem, private key is in newkey.pem"
   ;;

and add the following immediately below, like this:

 -newreq-nodes)
   # create a certificate request
   $REQ -new -nodes -keyout newkey.pem -out newreq.pem $DAYS
   RET=$?
   echo "Request is in newreq.pem, private key is in newkey.pem"
   ;;

(You might want to edit the help message too.)  Now use this script to generate CA and then email cedrtificates:

/etc/postfix# cd /etc/pki/tls/misc
/etc/pki/tls/misc# ./CA.sh -newca
CA certificate filename (or enter to create)

Making CA certificate ...
Generating a 1024 bit RSA private key
.....................++++++
........................++++++
writing new private key to '../../CA/private/./cakey.pem'
Enter PEM pass phrase:secret
Verifying - Enter PEM pass phrase:secret
-----
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) [GB]:US
State or Province Name (full name) [Berkshire]:Florida
Locality Name (eg, city) [Newbury]:Tampa
Organization Name (eg, company) [My Company Ltd]:Kaos.coop
Organizational Unit Name (eg, section) []:.
Common Name (eg, your name or your server's hostname) []:whoopie.kaos.coop
Email Address []:security@whoopie.kaos.coop

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:secret		[used with SCEP]
An optional company name []:Kaos.coop
Using configuration from /etc/pki/tls/openssl.cnf
Enter pass phrase for ../../CA/private/./cakey.pem:
Check that the request matches the signature
Signature ok
Certificate Details:
        Serial Number: 0 (0x0)
        Validity
            Not Before: Dec  1 04:40:05 2006 GMT
            Not After : Nov 30 04:40:05 2009 GMT
        Subject:
            countryName               = US
            stateOrProvinceName       = Florida
            organizationName          = Kaos.coop
            commonName                = whoopie.kaos.coop
            emailAddress              = security@whoopie.kaos.coop
        X509v3 extensions:
            X509v3 Basic Constraints:
                CA:FALSE
            Netscape Comment:
                OpenSSL Generated Certificate
            X509v3 Subject Key Identifier:
                01:C1:4E:A2:C8:3A:8E:49:B6:0C:36:EF:CC:23:F3:98:58:D8:91:75
            X509v3 Authority Key Identifier:
                keyid:01:C1:4E:A2:C8:3A:8E:49:B6:0C:36:EF:CC:23:F3:98:58:D8:91:75

Certificate is to be certified until Nov 30 04:40:05 2009 GMT (1095 days)

Write out database with 1 new entries
Data Base Updated

Having created a certificate authority certificate, we can now use it to create and sign an email certificate.  Note that in real life you would generate a CSR and not sign it yourself, but rather sent it to some CA (that you send money to) to sign it for you.

/etc/pki/tls/misc# ./CA.sh -newreq-nodes
Generating a 1024 bit RSA private key
..++++++
...............++++++
writing new private key to 'newkey.pem'
-----
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) [GB]:US
State or Province Name (full name) [Berkshire]:Florida
Locality Name (eg, city) [Newbury]:Tampa
Organization Name (eg, company) [My Company Ltd]:Kaos.coop
Organizational Unit Name (eg, section) []:.
Common Name (eg, your name or your server's hostname) []:whoopie.kaos.coop
Email Address []:postmaster@whoopie.kaos.coop

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:secret
An optional company name []:Kaos.coop
Request is in newreq.pem, private key is in newkey.pem

/etc/pki/tls/misc# ./CA.sh -sign
Using configuration from /etc/pki/tls/openssl.cnf
Enter pass phrase for ../../CA/private/cakey.pem:secret
Check that the request matches the signature
Signature ok
Certificate Details:
        Serial Number: 1 (0x1)
        Validity
            Not Before: Dec  1 04:42:29 2006 GMT
            Not After : Dec  1 04:42:29 2007 GMT
        Subject:
            countryName               = US
            stateOrProvinceName       = Florida
            localityName              = Tampa
            organizationName          = Kaos.coop
            commonName                = whoopie.kaos.coop
            emailAddress              = postmaster@whoopie.kaos.coop
        X509v3 extensions:
            X509v3 Basic Constraints:
                CA:FALSE
            Netscape Comment:
                OpenSSL Generated Certificate
            X509v3 Subject Key Identifier:
                34:06:94:1E:E4:72:CD:5D:EA:9F:4D:55:31:C4:58:C8:93:0B:07:F7
            X509v3 Authority Key Identifier:
                keyid:01:C1:4E:A2:C8:3A:8E:49:B6:0C:36:EF:CC:23:F3:98:58:D8:91:75

Certificate is to be certified until Dec  1 04:42:29 2007 GMT (365 days)
Sign the certificate? [y/n]:y

1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 1 (0x1)
        Signature Algorithm: sha1WithRSAEncryption
        Issuer: C=US, ST=Florida, O=Kaos,coop, CN=whoopie.kaos.coop/emailAddress=security@whoopie.kaos.coop
        Validity
            Not Before: Dec  1 04:42:29 2006 GMT
            Not After : Dec  1 04:42:29 2007 GMT
        Subject: C=US, ST=Florida, L=Tampa, O=Kaos.coop, CN=whoopie.kaos.coop/emailAddress=postmaster@whoopie.kaos.coop
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
            RSA Public Key: (1024 bit)
                Modulus (1024 bit):
                    00:d5:17:eb:0b:c1:82:d9:a8:3f:ba:ed:20:7d:69:
                    b0:e1:49:9c:e6:b1:bd:e4:af:6b:8a:40:01:69:91:
                    bd:67:f1:a2:a6:64:20:52:c9:d3:a9:ee:09:3c:46:
                    ab:cc:3b:83:32:a4:f0:18:4c:89:f0:6f:22:ed:a3:
                    ff:a6:9d:9b:6c:87:d8:bb:10:33:75:00:52:5e:56:
                    06:1d:92:ce:d1:b2:98:11:6e:b4:3d:41:73:f2:c9:
                    a6:c5:9d:b8:9d:2d:1e:fc:7c:15:dc:0f:ca:ce:70:
                    23:30:4e:a0:70:26:24:b3:e8:33:e6:20:19:2b:12:
                    43:c4:dd:c2:4b:a4:0a:1d:6b
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Basic Constraints:
                CA:FALSE
            Netscape Comment:
                OpenSSL Generated Certificate
            X509v3 Subject Key Identifier:
                34:06:94:1E:E4:72:CD:5D:EA:9F:4D:55:31:C4:58:C8:93:0B:07:F7
            X509v3 Authority Key Identifier:
                keyid:01:C1:4E:A2:C8:3A:8E:49:B6:0C:36:EF:CC:23:F3:98:58:D8:91:75

    Signature Algorithm: sha1WithRSAEncryption
        78:59:64:f8:a1:02:db:57:51:05:35:b1:28:59:32:0d:b5:89:
        5f:e2:13:84:4f:47:aa:7b:d3:10:d9:95:3b:a9:1f:b2:64:7c:
        90:e0:a2:75:65:0d:4a:40:b8:2d:5c:94:64:77:7a:c8:de:4e:
        3e:5b:f1:6e:7d:58:dd:eb:cd:10:af:48:01:d6:84:a4:fd:c6:
        2c:12:dd:44:6a:d0:44:94:01:bf:a8:78:0e:3c:67:60:e8:23:
        a7:d7:54:e0:3f:b4:58:59:12:12:c4:e6:d9:ab:ca:d0:ca:ed:
        2b:c0:db:70:eb:52:81:50:45:fb:25:c4:86:d1:dc:15:9c:1b:
        ae:7e
-----BEGIN CERTIFICATE-----
MIIC+DCCAmGgAwIBAgIBATANBgkqhkiG9w0BAQUFADB6MQswCQYDVQQGEwJVUzEQ
MA4GA1UECBMHRmxvcmlkYTESMBAGA1UEChMJS2Fvcyxjb29wMRowGAYDVQQDExF3
cGhvbWUxLmthb3MuY29vcDEpMCcGCSqGSIb3DQEJARYac2VjdXJpdHlAd3Bob21l
MS5rYW9zLmNvb3AwHhcNMDYxMjAxMDQ0MjI5WhcNMDcxMjAxMDQ0MjI5WjCBjDEL
MAkGA1UEBhMCVVMxEDAOBgNVBAgTB0Zsb3JpZGExDjAMBgNVBAcTBVRhbXBhMRIw
EAYDVQQKEwlLYW9zLmNvb3AxGjAYBgNVBAMTEXdwaG9tZTEua2Fvcy5jb29wMSsw
KQYJKoZIhvcNAQkBFhxwb3N0bWFzdGVyQHdwaG9tZTEua2Fvcy5jb29wMIGfMA0G
CSqGSIb3DQEBAQUAA4GNADCBiQKBgQDVF+sLwYLZqD+67SB9abDhSZzmsb3kr2uK
QAFpkb1n8aKmZCBSydOp7gk8RqvMO4MypPAYTInwbyLto/+mnZtsh9i7EDN1AFJe
VgYdks7RspgRbrQ9QXPyyabFnbidLR78fBXcD8rOcCMwTqBwJiSz6DPmIBkrEkPE
3cJLpAodawIDAQABo3sweTAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQfFh1PcGVu
U1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUNAaUHuRyzV3qn01V
McRYyJMLB/cwHwYDVR0jBBgwFoAUAcFOosg6jkm2DDbvzCPzmFjYkXUwDQYJKoZI
hvcNAQEFBQADgYEAeFlk+KEC21dRBTWxKFkyDbWJX+IThE9HqnvTENmVO6kfsmR8
kOCidWUNSkC4LVyUZHd6yN5OPlvxbn1Y3evNEK9IAdaEpP3GLBLdRGrQRJQBv6h4
DjxnYOgjp9dU4D+0WFkSEsTm2avK0MrtK8DbcOtSgVBF+yXEhtHcFZwbrn4=
-----END CERTIFICATE-----
Signed certificate is in newcert.pem

/etc/pki/tls/misc# mv newcert.pem ../certs/whoopie-email-cert.pem
/etc/pki/tls/misc# mv newkey.pem ../private/whoopie-email-key.pem
/etc/pki/tls/misc# mv newreq.pem /etc/postfix/whoopie-email-req.pem

/etc/pki/tls/misc# cd /etc/postfix
/etc/postfix# vi main.cf
/etc/postfix# postfix check
/etc/postfix# diff main.cf.ORIG main.cf
106c106
< #inet_interfaces = all
---
> inet_interfaces = all
109c109
< inet_interfaces = localhost
---
> #inet_interfaces = localhost
666a667,695
>
> # Support SMTP AUTH (via SASL):
> # (also must configure /usr/lib/sasl2/smtpd.conf with the line:
> #    pwcheck_method: saslauthd
> # and make sure saslauthd is started with the "-a pam" argument; this
> # is the default on Fedora Core 5 /etc/sysconfig/saslauthd.
> # Finally make sure saslauthd is started before postfix at boot time.)
>
> smtpd_sasl_auth_enable = yes
> smtp_sasl_security_options = noanonymous
> broken_sasl_auth_clients = yes
> smtpd_sasl_authenticated_header = yes
> smtpd_sasl_local_domain = $myhostname
> smtpd_recipient_restrictions =
>     permit_mynetworks permit_sasl_authenticated reject_unauth_destination

>
> # Support SSL/TLS (STARTTLS):
> smtpd_use_tls = yes
> smtpd_tls_cert_file = /etc/pki/tls/certs/whoopie-email-cert.pem
> smtpd_tls_key_file = /etc/pki/tls/private/whoopie-email-key.pem
> smtpd_tls_CAfile = /etc/pki/CA/cacert.pem
> smtpd_tls_received_header = yes
> # The following means only offer AUTH after STARTTLS.  This is a good
> # idea as AUTH is configured to use SASL, which is configured to use
> # PAM, which in turn allows system users with their passwords.  But,
> # THIS IS DANGEROUS SINCE THE USERNAME/PASSWORD IS SENT IN PLAIN TEXT!
> # (OK it is base64 encoded but that is trivial to reverse.)  So it
> # makse a lot of sence to only allow AUTH with SSL/TLS encryption.
> smtpd_tls_auth_only = yes

/etc/postfix# telnet whoopie 25
Trying 192.168.0.5...
Connected to whoopie.kaos.coop (192.168.0.5).
Escape character is '^]'.
220 whoopie.kaos.coop ESMTP Postfix
ehlo localhost
250-whoopie.kaos.coop
250-PIPELINING
250-SIZE 10240000
250-VRFY
250-ETRN
250-STARTTLS
250 8BITMIME
starttls
220 Ready to start TLS
^C
Connection closed by foreign host.

Now try it out using openssl s_client:

user> openssl s_client -connect whoopie:25 -starttls smtp -prexit
CONNECTED(00000003)
depth=1 /C=US/ST=Florida/O=Kaos,coop/CN=whoopie.kaos.coop/emailAddress=security@whoopie.kaos.coop
verify error:num=19:self signed certificate in certificate chain
verify return:0
---
Certificate chain
 0 s:/C=US/ST=Florida/L=Tampa/O=Kaos.coop/CN=whoopie.kaos.coop/emailAddress=postmaster@wphome1.kaos.coop
   i:/C=US/ST=Florida/O=Kaos,coop/CN=whoopie.kaos.coop/emailAddress=security@whoopie.kaos.coop
 1 s:/C=US/ST=Florida/O=Kaos,coop/CN=whoopie.kaos.coop/emailAddress=security@whoopie.kaos.coop
   i:/C=US/ST=Florida/O=Kaos,coop/CN=whoopie.kaos.coop/emailAddress=security@whoopie.kaos.coop
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIC+DCCAmGgAwIBAgIBATANBgkqhkiG9w0BAQUFADB6MQswCQYDVQQGEwJVUzEQ
MA4GA1UECBMHRmxvcmlkYTESMBAGA1UEChMJS2Fvcyxjb29wMRowGAYDVQQDExF3
cGhvbWUxLmthb3MuY29vcDEpMCcGCSqGSIb3DQEJARYac2VjdXJpdHlAd3Bob21l
MS5rYW9zLmNvb3AwHhcNMDYxMjAxMDQ0MjI5WhcNMDcxMjAxMDQ0MjI5WjCBjDEL
MAkGA1UEBhMCVVMxEDAOBgNVBAgTB0Zsb3JpZGExDjAMBgNVBAcTBVRhbXBhMRIw
EAYDVQQKEwlLYW9zLmNvb3AxGjAYBgNVBAMTEXdwaG9tZTEua2Fvcy5jb29wMSsw
KQYJKoZIhvcNAQkBFhxwb3N0bWFzdGVyQHdwaG9tZTEua2Fvcy5jb29wMIGfMA0G
CSqGSIb3DQEBAQUAA4GNADCBiQKBgQDVF+sLwYLZqD+67SB9abDhSZzmsb3kr2uK
QAFpkb1n8aKmZCBSydOp7gk8RqvMO4MypPAYTInwbyLto/+mnZtsh9i7EDN1AFJe
VgYdks7RspgRbrQ9QXPyyabFnbidLR78fBXcD8rOcCMwTqBwJiSz6DPmIBkrEkPE
3cJLpAodawIDAQABo3sweTAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQfFh1PcGVu
U1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUNAaUHuRyzV3qn01V
McRYyJMLB/cwHwYDVR0jBBgwFoAUAcFOosg6jkm2DDbvzCPzmFjYkXUwDQYJKoZI
hvcNAQEFBQADgYEAeFlk+KEC21dRBTWxKFkyDbWJX+IThE9HqnvTENmVO6kfsmR8
kOCidWUNSkC4LVyUZHd6yN5OPlvxbn1Y3evNEK9IAdaEpP3GLBLdRGrQRJQBv6h4
DjxnYOgjp9dU4D+0WFkSEsTm2avK0MrtK8DbcOtSgVBF+yXEhtHcFZwbrn4=
-----END CERTIFICATE-----
subject=/C=US/ST=Florida/L=Tampa/O=Kaos.coop/CN=whoopie.kaos.coop/emailAddress=postmaster@whoopie.kaos.coop
issuer=/C=US/ST=Florida/O=Kaos,coop/CN=whoopie.kaos.coop/emailAddress=security@whoopie.kaos.coop
---
No client certificate CA names sent
---
SSL handshake has read 2137 bytes and written 350 bytes
---
New, TLSv1/SSLv3, Cipher is DHE-RSA-AES256-SHA
Server public key is 1024 bit
Compression: NONE
Expansion: NONE
SSL-Session:
    Protocol  : TLSv1
    Cipher    : DHE-RSA-AES256-SHA
    Session-ID: 7440731E52B11A8578C4B2250787B4413C944A5EA05B062CFB9E1D6CC316A6AC
    Session-ID-ctx:
    Master-Key: DD9F22850F7CE2F6D356B2458777C3B5DD79AB535B68FC542A5673EA7B60F1255FB3DFD25D2D7ED9014A99FE0379B3E1
    Key-Arg   : None
    Krb5 Principal: None
    Start Time: 1165004565
    Timeout   : 300 (sec)
    Verify return code: 19 (self signed certificate in certificate chain)
---
220 whoopie.kaos.coop ESMTP Postfix
ehlo localhost
250-whoopie.kaos.coop
250-PIPELINING
250-SIZE 10240000
250-VRFY
250-ETRN
250-AUTH PLAIN LOGIN
250-AUTH=PLAIN LOGIN
250 8BITMIME
auth plain d3BvbGxvY2sAd3BvbGxvY2sAcmFiYXV0MjE=
235 Authentication successful
mail from: <wpollock@whoopie.kaos.coop> size=91
250 Ok
rcpt to: <wpollock@localhost>
250 Ok
data
354 End data with <CR><LF>.<CR>^lt;LF>
From: me
To: you
Subject: test of email from whoopie via postfix with starttls and auth
hi
.
250 Ok: queued as 421322DEFC7
quit
221 Bye
---
SSL handshake has read 2689 bytes and written 1499 bytes