====== Exim4 - Enable SMTP-Auth with PAM ======
To use PAM for SMTP authentication, but with the possibility of passwords in a local file, say /etc/exim4/passwd, overriding those in PAM. In other words, the goal is to have the following:
* Check if the user ID exists, along with a password, in /etc/exim4/passwd
* If so, use the password in /etc/exim4/passwd to authenticate
* If not (or if /etc/exim4/passwd does not exist), use PAM to authenticate.
===== Configuring exim =====
tls_advertise_hosts = *
Make sure authentication is only enabled on an encrypted connection. This is due to the fact that passwords would otherwise be sent in clear text:
auth_advertise_hosts = ${if def:tls_in_cipher {*}{}}
and
begin authenticators
PLAIN:
driver = plaintext
server_prompts = :
server_condition = "${if pam{$auth2:$auth3}{yes}{no}}"
server_set_id = $auth2
LOGIN:
driver = plaintext
server_prompts = "Username:: : Password::"
server_condition = "${if pam{$auth1:$auth2}{yes}{no}}"
server_set_id = $auth1
Add or modify the following
begin authenticators
#########################################################################
plain_server:
# This authenticator implements the PLAIN authentication mechanism
# (RFC2595). Since the password is transmitted essentially as clear
# text, a user can only authenticate if the session is encrypted using
# TLS. The user name and password is first checked against
# /etc/exim4/passwd, then against the system database using PAM (in
# that order).
driver = plaintext
public_name = PLAIN
server_advertise_condition = ${if eq{$tls_cipher}{}{false}{true}}
server_prompts = :
server_set_id = $auth2
server_condition = "\
${if exists{CONFDIR/passwd}\
{${lookup{$auth2}lsearch{CONFDIR/passwd}\
{${if crypteq{$auth3}{\\\{md5\\\}${extract{1}{:}{$value}{$value}fail}}\
{true}{false} }}\
{${if pam{$auth2:${sg{$auth3}{:}{::}} }\
{true}{false}} } }}\
{${if pam{$auth2:${sg{$auth3}{:}{::}} }\
{true}{false}} }}"
#########################################################################
login_server:
# This authenticator implements the LOGIN authentication mechanism.
# Since the password is transmitted essentially as clear text, a user
# can only authenticate if the session is encrypted using TLS. The
# user name and password is first checked against /etc/exim4/passwd,
# then against the system database using PAM (in that order).
driver = plaintext
public_name = LOGIN
server_advertise_condition = ${if eq{$tls_cipher}{}{false}{true}}
server_prompts = Username:: : Password::
server_set_id = $auth1
server_condition = "\
${if exists{CONFDIR/passwd}\
{${lookup{$1}lsearch{CONFDIR/passwd}\
{${if crypteq{$auth2}{\\\{md5\\\}${extract{1}{:}{$value}{$value}fail}}\
{true}{false} }}\
{${if pam{$auth1:${sg{$auth2}{:}{::}} }\
{true}{false}} } }}\
{${if pam{$auth1:${sg{$auth2}{:}{::}} }\
{true}{false}} }}"
**NOTE**: It's important to use \\\{md5\\\} instead of \{md5\} in the crypteq function.
===== PAM config =====
Contents of /etc/pam.d/exim
auth required /lib/security/$ISA/pam_env.so
auth sufficient /lib/security/$ISA/pam_unix.so likeauth nullok
auth required /lib/security/$ISA/pam_deny.so
account required /lib/security/$ISA/pam_unix.so
password required /lib/security/$ISA/pam_cracklib.so retry=3 type=
password sufficient /lib/security/$ISA/pam_unix.so nullok use_authtok md5shadow
password required /lib/security/$ISA/pam_deny.so
session required /lib/security/$ISA/pam_limits.so
session required /lib/security/$ISA/pam_unix.so
This file must be readable by the exim group (the group your exim daemon runs as) otherwise you will get the error.
535 Incorrect authentication data (set_id='userid')
===== Configuring /etc/exim4/passwd =====
#########################################################################
# /etc/exim4/passwd: Client Passwords for Mail Submission to Exim #
#########################################################################
# This file allows a user to authenticate a mail submission to the Exim
# MTA without using their system password (found in /etc/shadow).
#
# Each line of this file should contain a "user:password:comment" field,
# where the password is encrypted using MD5 and encoded as a hexadecimal
# string. Please note that this format is NOT the same as is used by
# /etc/shadow! You can disable a user from ever sending (authenticated)
# messages by using "*" as the password.
#
# You can use the following Perl command line to generate the password:
#
# perl -MDigest::MD5=md5_hex -e 'print md5_hex($ARGV[0]),"\n"' password
#
# (replace "password" with your password, of course).
####################
# System users #
####################
root:*:
###################
# Local users #
###################
#test:68772f0946d616e78f18452f84e39da7:Test#Password#01a
The easiest way to generate a password is to use the Digest::MD5 package with Perl:
perl -MDigest::MD5=md5_hex -e 'print md5_hex($ARGV[0]),"\n"' password
Simply replace **password** with your password.
**NOTE**: The Perl **md5_base64** function is not compatible with Exim's **crypteq**: the former generates a 22-character string, the latter expects a 24-character string (i.e., it expects two additional characters, ==, on the end of the string).
===== References =====
https://github.com/Exim/exim/wiki/AuthenticatedSmtpUsingPamAndPasswords