Wrestling with Postfix: Custom Authentication

webhat
Frontiers
Published in
4 min readMay 19, 2015

In a previous post, I discussed using Postfix’s modularity to create a custom mail delivery agent. I elaborate on some the reasons that one might want to do that including redundancy.

Why would you need custom authentication in Postfix?

For most use cases, this is not needed, however for certain integrations with custom applications, unsupported encryption methods and certain edge cases it can not be avoided.

The reason we needed a custom authentication is as we integrate with an application which uses bcrypt as its password hashing scheme and this is not supported by Postfix and Dovecot on Linux.

Dovecot?

There are two approaches to implementing custom authentication with Postfix:

Dovecot, like Postfix, is extremely modular and easy to use. It includes a SASL daemon for which can be used for authentication by both packages. Dovecot authentication can be done by a small script who’s only purpose is to verify that the user exists in the userdb and a matching password exists in the passdb. The script is run by Dovecot’s SASL daemon, which handles the identification and authentication for the Postfix and Dovecot tools and daemons.

To be able to write either you will need to have some knowledge about both. As it implements the Unix philosophy, as briefly described in the previous post, each only does one thing but does it extremely well. SASL handles the mechanism of identification and authentication, and the scripts handle the actual identification and authentication.

Identification and Authentication

SASL provides two services:

  • Identification — does this user exist?
  • Authentication — is this user who they say they are?

For mail, the identity is used to ensure the email is sent to the correct mailbox. Authentication is used to ensure only the intended recipient can read the mail.

The SASL daemon

The SASL daemon’s only task is to handle the communication to and from the identification and authentication scripts, which it does by passing messages from the services around using unix-sockets. The identification and authentication mechanisms are called upon to enrich the messages and pass the information back through the SASL daemon to the service.

The first message passed to the service, that is requesting identification or authentication, from the SASL daemon is a message which contains a list of the mechanisms it supports and a cookie. As a reply, the service sends an authentication request.

The message is build up out of a number of TAB separated components— in the examples below #011 represents the HT (horizontal tab) byte. The AUTH message contains the type of mechanism it is requesting, PLAIN. The resp field contains the authentication request, the username and password base64 encoded. Each line ends in a line-feed.

AUTH#0111#011PLAIN#011service=doveadm#011resp=d2ViaGF0AHBhc3N3b3JkAAo=

SASL can support numerous back-end authenticators, some which will handle one or more authentication methods. These can also be stacked, allowing different data sources to be addressed sequentially.

Finally a message is sent by SASL to the service which is requesting authentication with an OK or FAIL.

An example failure message would look like this:

FAIL#0111#011user=webhat

And a successful message would look like this:

OK#0111#011user=webhat

The Dovecot Authentication

Once the SASL daemon has determined which mechanism it needs it hands off to Dovecot which runs the identification (userdb) and/or authentication (passdb) script(s).

As identification requires little more than a database look up this can often be handled by using the internal configuration:

#/etc/dovecot/conf.d/auth-checkpassword.conf.ext
userdb {
driver = sql
args = /etc/dovecot/dovecot-sql.conf.ext
}
# /etc/dovecot/dovecot-sql.conf.ext
driver = mysql
connect = host=localhost dbname=oplerno_production user=dovecot \
pass=secret
user_query = SELECT 111 AS uid, 111 AS gid, '/tmp/' AS home \
FROM users WHERE users.username='%n'

This result in the following message being sent from the userdb:

user=webhat#011userdb_home=/tmp/#011userdb_uid=111#011userdb_gid=111#011

For the authentication, we could use add a similar method if we were using a supported password scheme.

# /etc/dovecot/dovecot-sql.conf.ext
password_query = SELECT password \
FROM users WHERE users.user = '%u'

Rather than that we are using a custom authentication script, using checkpassword.

#/etc/dovecot/conf.d/auth-checkpassword.conf.ext
passdb {
driver = checkpassword
args = /etc/dovecot/custom_authentication
}

What you really need to know!

The authentication process also passed a number of environment variables to the command it executes from args. It passed the location of the checkpassword-reply tool to the script. And as I said above when describing the workings of the SASL daemon: it uses unix-sockets to communicate.

/etc/dovecot/custom_authentication /usr/libexec/checkpassword-reply

Checkpassword-reply is used to handle the communication to the unix-sockets, so you don’t need to. (A program that does one thing, and does it really well.) It also relays back any additions or updates you might have made to the environment variables.

The environment variables include the username, password, mechanism and a host of other things you might require as input to your authentication. Like this AUTH_USER, AUTH_USERNAME and AUTH_PASSWORD.

After you have run your authentication schema for the user and were successful you run checkpassword-reply, and exit with 0 from your script. If the authentication failed return 1, and for any other failure return 111.

Finally

As you see there is no real way to explain the authentication scripts without explaining the SASL daemon, obviously writing your own SASL daemon would violate the separation of concerns. And having done so in the past I assure you that there is no advantage to writing your own.

Join Oplerno as a Developer

By Daniël W. Crompton (@webhat) at Oplerno — a global institution empowering real-world practitioners, adjunct lecturers, professors, and aspiring instructors to offer affordable, accessible, high-quality education to students from all corners of the globe.

http://www.dovecot.org/

http://www.postfix.org/

http://en.wikipedia.org/wiki/Unix_philosophy

http://wiki2.dovecot.org/AuthDatabase/CheckPassword

--

--

webhat
Frontiers

Former Security Consultant. Developer with a love of Education, Mashups and Folksonomy. Serial Entrepreneur. (+31646783584) Tech @Oplerno and @HigherEdRev