-
Notifications
You must be signed in to change notification settings - Fork 187
AuthenticatedSmtpUsingPamAndPasswords
You may be faced with a situation in which you would like 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.
This document shows you how to do this.
You need to configure and build Exim 4 to support PAM for this
configuration to work. See the page on Authenticated SMTP using
PAM for more details. On Debian
GNU/Linux, this is as simple as installing Exim 4; you most likely need
the exim4-daemon-heavy package. You also need to add the Debian-exim
user into the shadow group, so as to give Exim access to /etc/shadow
via PAM.
In the configuration file, typically /etc/exim4/exim4.conf or similar, 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 eq{$tls_cipher}{}{}{*}}
Naturally, you will need to set up an appropriate encryption certificate. For example:
tls_advertise_hosts = *
tls_certificate = /etc/ssl/certs/smtp-with-ca.pem
tls_privatekey = /etc/ssl/private/smtp.pem
In this case, /etc/ssl/certs/smtp-with-ca.pem contains the certificate
for SMTP, signed by a Certification Authority, along with that
Certification Authority's certificate. The file
/etc/ssl/private/smtp.pem would then contain the private key; it must be
readable by Exim (typically by making it group-readable by the
Debian-exim group, on Debian systems).
Finally, add the following authenticators:
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}} }}"
CONFDIR is assumed to be a macro pointing to the configuration
directory. In other words, something like the following should appear in
the Exim configuration file:
CONFDIR = /etc/exim4
You need to create an appropriate password file to use with these authenticators. You might like to use the following as a template:
#########################################################################
# /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.
Please note that 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 (ie, it expects two additional characters,
==, on the end of the string).
This document showed you how to consult both a password file and the
PAM system password databases, in that order, for authenticated SMTP.
The main reason for writing this document is the number of hours the
author spent debugging the authenticators before discovering (a) the
-d+expand command line argument and (b) the need for \\\{md5\\\}
instead of \{md5\} in the crypteq function! --
JohnZaitseff