Implementing SMTP Authorization with qpsmtpd running under SuSE 10.0 and Plesk 8.0

Receiving incoming email and making it available to your users via POP3 or IMAP is only the first half of running a Message Transfer Agent (MTA). The other half is to relay outgoing email from your users to the world.

We don't want to run an open relay, of course, so we we need some form of authorization.

qpsmtpd offers a number of plugins for implementing authorization in very varied environments. I'm using Plesk for managing my email users (as well as allowing some of them to manage themselves), and I was looking for a plugin that could blend in with the existing Plesk installation.

1st Attempt: checkpassword

I use qpsmtpd as a replacement for qmail-smtpd, which normally runs with parameters such as

   /var/qmail/bin/checkpassword /var/qmail/bin/true

checkpassword takes care of validating the given user name and password and if successful, it runs its parameter and returns a success code. SWsoft have patched qmail-smtpd for Plesk to accept two pairs of parameters, which both seem to follow the same protocol:

   /var/qmail/bin/smtp_auth /var/qmail/bin/true
   /var/qmail/bin/cmd5checkpw /var/qmail/bin/true

qpsmtpd has a plugin called authcheckpassword, which implements the checkpassword protocol, but I wasn't able to get this to authorize successfully with either smtp_auth or cmd5checkpw.

2nd Attempt: use PAM

My server installation uses PAM to implement authorization with the Plesk-managed MySQL user database, and qpsmtpd has an auth/auth_pam plugin. This looks perfect, doesn't it?

Well, the first problem was that it required installing a CPAN Perl module, Authen::PAM. That was surprisingly easy, but authorization still kept failing! After a lot of head scratching I found entries like the following in /var/log/warn:

   Unable to establish connection to the Plesk DB: db_connect:
     Unable to open admin password file: Permission denied

In order to access the MySQL database, PAM needs to read a file that holds the database user's password, and this file is only accessible to the Plesk user. It's definitely not accessible to the smtpd user, which is used for running qpsmtpd.

I'm sure there are ways to get this to work, but I didn't want to start messing with permissions, so I turned to...

3rd Attempt: use IMAP

But IMAP is for retrieving email, not for sending it?! Correct, but there's a qpsmtpd plugin auth_imap that piggy-backs on IMAP to authorize SMTP relaying. If your plan is to offer SMTP relaying to all of your POP3/IMAP users, then this is a neat trick: auth_imap takes the credentials from the SMTP session and tries to open an IMAP session with those credentials, and if it succeeds, then it allows SMTP relaying.

You may have to install the Net::IMAP::Simple::SSL CPAN module (see above). I had to apply two more tweaks:

  • give parameters to auth_imap...
    auth_imap localhost 143

    ... even though these are supposed to be the defaults, and

  • remove "::SSL" from
    my $server = Net::IMAP::Simple::SSL->new(
           $imapserver )

    There's no need to use SSL to talk to yourself, and I didn't want to bother getting IMAP to run over SSL.

This works fine now, but there's still one small fly in the ointment: auth_imap only supports the plain and login mechanisms, i.e. the password is transmitted unencrypted. Fortunately, there's a cure for this as well: create a wildcard CAcert certificate (to support multiple domains) and install the tls plugin to encrypt the entire SMTP session, including the password dialog.

Yet Another Alternative

Just as auth_imap piggy-backs on a running IMAP server, auth_smtpd can piggy-back on another SMTP server. So, if nothing seems to work, you can try to run qmail-smtpd on a different port and let auth_smtpd authenticate qpsmtpd relaying by attempting to authorize to qmail-smtpd.