Friday, July 12, 2013

NetBSD, sendmail and smtp auth

Firstly, I do like having a MTA on my laptop. It permits things like send-pr to work and allows me to queue up mails while I am off network and have them relay when a network appears. For better or worse, the default MTA that ships with recent versions of NetBSD is postfix.

I don't really like postfix much, I really prefer sendmail. I have used sendmail from back in the days when you had to hand craft your sendmail.cf, the m4 configuration stuff was not around. I am used to the rich debug options you get with sendmail, something I sorely miss with postfix. Being that postfix is the default MTA on NetBSD, I thought I would at least give it a chance and I have been using it for quite some time but a few days ago it did what I think is an unforgivable sin. Postfix refused to relay mail. It did so for no clear reason. Yes, initially there seemed to be a problem with my stunnel that securely tunnels a connection to my ISP smtps server but that resolved itself and yet mail still sat in the queue. A reboot (not that I rebooted due to that, my laptop gets rebooted a lot for other reasons) and also a restart of postfix did not move the mail. I had to tell postfix to push the mail out... that just sucks in my books, the MTA should try and flush the queue if there are pending messages when it starts up. So, time to bring sendmail back. This is how I configured sendmail to use the stunnel tunnel to my ISPs secure mail server and perform a smtp auth which my ISP requires.

Install stunnel from pkgsrc and then edit /usr/pkg/etc/stunnel/stunnel.conf. Add:

[smtps]
accept = 5000
connect = securemail.server.your.isp:smtps


setup stunnel to start at boot by adding an entry to the /etc/rc.conf and put a copy of /usr/pkg/share/examples/rc.d/stunnel into /etc/rc.d. Now stunnel should start on boot (actually, I have a dhclient hook script that restarts stunnel when I get an new IP). That should be it, if you start up stunnel then you should be able to test the connection by doing:

telnet localhost 5000


If all is well then telnet should connect and open a session, you should be able to see a smtp greeting. This is all you really need to do though it does make you vulnerable to a man in the middle attack where someone could manipulate your DNS to make stunnel think it is connecting to the secure mail server but is really connecting to the attackers host. Your ISP may provide a digital certificate that you can use to validate you are connecting to the correct machine (mine does). Put the certificate into /usr/pkg/etc/stunnel/certs.pem. My ISP only provided their certificate, I had to download the root certificate bundle from the certificate issuers web site myself. You can find out the issuer by running:

openssl x509 -in /usr/pkg/etc/stunnel/certs.pem -noout -issuer


Once you have the issuers certificate bundle, just append the certificates to the end of the certs.pem file (assuming all the certs are in PEM format of course). Then tell stunnel to start using the certificates by adding this to the stunnel.conf:

verify = 3
CAfile = /usr/pkg/etc/stunnel/certs.pem


Setting verify to 3 tells stunnel to verify the peer with a locally installed certificate. Restart stunnel and perform the telnet test again, you should again get a successful connection to your ISPs securemail server. If you don't then you have something broken, there is a debug option in the stunnel.conf if you set this on then a stunnel.log will be written into the location that stunnel is chroot'ed to. By default that is /var/chroot/stunnel/. If you see:

CERT: Verification error: unable to get local issuer certificate


Then your issuer certificate is either missing or incorrect.

Once stunnel configured and tested, it is time to move onto sendmail. Sendmail is available in pkgsrc, I normally build my own packages instead of installing binary ones. These are the steps I followed. To build sendmail with SASL support add this to /etc/mk.conf:

add PKG_OPTIONS.sendmail=   sasl


make and install sendmail. Copy the sendmail and smmsp in /usr/pkg/share/examples/rc.d/ to /etc/rc.d.
Also install cy2-plain otherwise you will get AUTH=client, available mechanisms do not fulfill requirements in the maillog if you try and use PLAIN for smtp authentication. I am guessing that if a different authentication scheme is used then you should install the matching cy2 package to get support for the scheme.

With sendmail installed we next turn to the sendmail config. Firstly create a file in /usr/pkg/share/sendmail/cf/. I normally use the convention of machinename.mc where machinename is the hostname of the machine the sendmail configuration is for. The file had the contents:

include(`../m4/cf.m4')
VERSIONID(`@(#)machine.mc $Revision: 1.1.1.1 $')
OSTYPE(bsd4.4)dnl
FEATURE(masquerade_envelope)dnl
FEATURE(`authinfo',`hash /home/sendmail/client-info')dnl
define(`confAUTH_MECHANISMS', `EXTERNAL GSSAPI DIGEST-MD5 CRAM-MD5 LOGIN PLAIN')dnl
define(`SMART_HOST', [127.0.0.1])dnl
define(`RELAY_MAILER_ARGS', `TCP $h 5000')dnl
define(`ESMTP_MAILER_ARGS', `TCP $h 5000')dnl
define(`confCHECKPOINT_INTERVAL', 10)dnl
define(`confMESSAGE_TIMEOUT', 3d/4h)dnl
MASQUERADE_AS(your.isp.domain)dnl
LOCAL_USER(root)
MAILER(local)dnl
MAILER(smtp)dnl

Usually people put the file for authinfo under /etc/mail, I have put mine in /home/sendmail mainly because my /home partition is encrypted using CGD so, without my CGD passphrase, people cannot steal my authentication details even if they have physical access to the machine. Note also that the number in the RELAY_MAILER_ARGS and ESMTP_MAILER_ARGS (in my case 5000) must match the number defined on the accept line in the stunnel.conf file.

Create the sendmail configuration file using:

make machinename.cf


Copy the resulting machinename.cf to /etc/mail/sendmail.cf. If this is a first time install of sendmail you may need to make and install the submit.cf file into /etc/mail too, the submit.mc is in the same directory as the custom configuration file source.

The above sendmail configuration expects a sendmail hash database in /home/sendmail/client-info, to create this we create a file /home/sendmail/client-info with the contents:

AuthInfo:127.0.0.1 "U:username@your.isp.domain" "I:username@your.isp.domain" "P:sekret!"


Since we have stunnel listening on port 5000 on localhost all we need to define is an entry for localhost. The U and I parameters are for authentication and authorisation, usually they are both the same and most places seem to use your email address. It is best to check these details with your mail provider. The P field is the password for the account.
After the client-info file is created, change directory to /home/sendmail (or where-ever you placed the file) and run:

makemap hash client-info < client-info


To create the hash database. Make sure the directory and all the files in it are only readable by root.

Next we need to update the /etc/mailer.conf to tell NetBSD to use sendmail instead of the default postfix. Just run this command:

ln -fs /usr/pkg/share/examples/sendmail/mailer.conf /etc/mailer.conf


Finally, edit /etc/rc.conf and add:

postfix=NO
sendmail=yes
smmsp=yes


To turn off postfix and start sendmail at boot. At this point you should be able to shut down postfix, start sendmail and test sending emails.