Editor's note: Our previous set of recipes from Linux Security Cookbook covered two intermediate-level Linux security solutions. This week we offer recipes that fall into an advanced category. Learn how to use PAM to restrict authentication on Linux systems and how to use SMTP to accept connections from arbitrary clients securely.
Author's note: PAM (Pluggable Authentication Modules) is a flexible infrastructure for controlling authentication on Linux systems. In this recipe, taken from Chapter 4, "Authentication Techniques and Infrastructures," we show you how to restrict authentication to a given set of users by creating an access control list.
You would like to apply an access control list (ACL) to an existing service that does not
explicitly support ACLs (e.g.,
First, make sure the server in question uses PAM for authentication, and find out which PAM service name it uses. This may be in the server documentation, or it may be clear from examining the server itself and perusing the contents of /etc/pam.d. For example, suppose you're dealing with the IMAP mail server. First notice that there is a file called /etc/pam.d/imap. Further, the result of:
# locate imapd ... /usr/sbin/imapd
shows that the IMAP server is in /usr/sbin/imapd, and:
# ldd /usr/sbin/imapd libpam.so.0 => /lib/libpam.so.0 (0x40027000) ...
shows that the server is dynamically linked against the PAM library (libpam.so), also suggesting that it uses PAM. In fact, the Red Hat 8.0 IMAP server uses PAM via that service name and control file ("imap").
Continuing with this example, create an ACL file for the IMAP service, let's say /etc/imapd.acl, and make sure it is not world-writable:
# chmod o-w /etc/imapd.acl
Edit this file, and place in it the usernames of those accounts authorized to use the IMAP server, one name per line. Then, add the following to /etc/pam.d/imap:
account required /lib/security/pam_listfile.so file=/etc/imapd.acl \ item=user sense=allow onerr=fail
With this configuration, only those users listed in the ACL file will be allowed access to the IMAP service. If the ACL file is missing, PAM will deny access for all accounts.
The PAM "listfile" module is actually even
more flexible than we've indicated. Entries in your ACL file can be not only
item=user), but also:
Terminal lines (
Remote host (
Remote user (
Group membership (
Login shell (
sense keyword determines how the
ACL file is interpreted.
sense=allow means that access
will be allowed only if the configured
item is in the
file, and denied otherwise.
sense=deny means the
opposite: access will be denied only if the item is in the file, and allowed
onerr keyword indicates what to do if some unexpected error occurs during PAM processing of
the listfile module - for instance, if the ACL file does not exist. The values are
fail is a more conservative option from a security standpoint, but can also lock you out of your system because of a configuration mistake!
], limits the restriction in
question to apply only to particular users or groups. This is intended for use with the
shell items. For example, using
apply=@foo would restrict access to connections from hosts listed in the ACL file, and furthermore only to local accounts in the
To debug problems with PAM modules, look for PAM-specific error messages in /var/log/messages and /var/log/secure. (If you don't see the expected messages, check your system logger configuration. [Recipe 9.28])
Note that not all module parameters have defaults. Specifically, the
sense parameters must be supplied; if not, the module will fail with an error message like:
Dec 2 15:49:21 localhost login: PAM-listfile: Unknown sense or sense not specified
You generally do not need to restart servers using PAM: they usually re-initialize the PAM library for every authentication and reread your changed files. However, there might be exceptions.
There is no standard correspondence between a server's name
and its associated PAM service. For instance, logins via Telnet are actually
mediated by /bin/login, and thus use the
login service. The SSH server
the same-named PAM service (
sshd), whereas the IMAP server
imapd uses the
imap (with no "d") PAM
service. And many services in turn depend on other services, notably
See /usr/share/doc/pam-*/txts/README.pam_listfile for a list of parameters to tweak.
Author's note: A good mail server is configured to accept SMTP mail from only a predetermined set of clients: say, all hosts within your Intranet. However, in this recipe, selected from Chapter 8, "Protecting Email," we show you how to configure your mail server to accept connections from arbitrary clients, without creating a dreaded open relay to be abused by spammers.
You want your SMTP server to relay mail from arbitrary places, without creating an open relay.
Use SMTP authentication. To set up the server:
Find this line in /etc/mail/sendmail.mc:
and change it to:
The default setting restricts
sendmail to accepting
connections only from the same host, for security; now it will accept
connections from elsewhere.
Make sure this line in /etc/mail/sendmail.mc appears uncommented (i.e., it is not preceded by the comment symbol
TRUST_AUTH_MECH(`EXTERNAL DIGEST-MD5 CRAM-MD5 LOGIN PLAIN')
If you have changed /etc/mail/sendmail.mc, rebuild
sendmail configuration file and restart
Rebuild the configuration:
# m4 /etc/mail/sendmail.mc > /etc/sendmail.cf
# /etc/init.d/sendmail restart
Establish an account for SMTP authentication, say, with username mailman:
# /usr/sbin/saslpasswd -c mailman Password: ******** Again (for verification): ********
Your mail server should now be ready to do SMTP authentication. To set up the email client:
Configure your mail client to use SMTP authentication for outbound email,
using either the
DIGEST-MD5 (preferred) or
Your client might also have an option nearby for a "secure connection" using SSL. Do not turn it on; that is a separate feature.
Try sending a test message via relay: address it to a domain considered non-local to your server. Instead of replying with a "relay denied" error (which you should have gotten previous to this setup), you should be prompted for a username and password. Use the mailman account you established previously. The mail message should get sent.
An SMTP server accepts Internet email. There are two kinds of email messages it may receive:
Local mail: Intended to be delivered to a local user on that host. This mail usually arrives from other mail servers.
Non-local mail: Intended to be forwarded to another host for delivery. This mail usually comes from email programs, such as Pine and Ximian Evolution, configured to use your SMTP server to send mail.
A mail server that forwards non-local mail is called a relay. Normally, you'll want your SMTP server to accept local mail from anywhere, but restrict who may use your server as a relay for non-local mail. If you don't restrict it, your SMTP server is called an open relay. Open relays invite trouble: spammers seek them out as convenient drop-off points; your machine could be co-opted to send unwanted email to thousands of people. Say goodbye to your good Internet karma... and you will shortly find your mail server blacklisted by spam-control services, and hence useless. In fact, you might come home one day to find your ISP has shut down your Net access, due to complaints of mail abuse! You really don't want an open relay.
ISP mail servers normally accept relay mail only from addresses on their network, restricting them to use by their customers. This makes good business sense, but is inconvenient for mobile users who connect to various ISPs for Net access at different times. It's a pain to keep switching email program settings to use the different required relays (or even to find out what they are).
Our recipe demonstrates how to set up your SMTP server to get around this inconvenience, by requiring authentication before relaying mail. Thus, a single SMTP server can accept non-local mail no matter where the client is connected, while still avoiding an open relay. One caveat: the email clients must support SMTP authentication, as do Evolution, Pine, the Mail program of Macintosh OS X, and others.
Our recipe depends on two lines in /etc/mail/sendmail.mc. The first, once you disable it,
sendmail to accept mail from other
hosts; by default, it only listens on the network loopback interface and accepts
mail only from local processes. The second line, once enabled, tells
sendmail which authentication mechanisms to
accept as trusted: that is, if a client authenticates using one of these
methods, it will be allowed to relay mail.
When you send your test message, if your mail client claims the server does not support SMTP authentication, try this on the server:
# sendmail -O LogLevel=14 -bs -Am EHLO foo QUIT # tail /var/log/maillog
and look for any enlightening error messages.
This configuration by itself does not secure the entire SMTP session, which
is still a plaintext TCP connection. So don't use simple password
authentication, as your passwords can then be stolen by network eavesdropping.
sendmail accepts only the
authentication methods, which do not send the password in plaintext.
It is also possible to configure
sendmail to use SSL to protect the entire SMTP session. If you understand
the security properties and limitations of the authentication mechanisms
mentioned above, and consider them inadequate for your application, this might
be a necessary step to take. However, don't do it out of some notion to
"protect" the content of your email. Unless you have a
closed system, your email will be further relayed across other networks on the
way to its destination, so securing this one hop is of little value. For more
security, use an end-to-end approach, encrypting messages with GnuPG, PGP, or
S/MIME (see Recipe 8.1 through Recipe 8.8).
Learn more about SMTP authentication at ftp://ftp.isi.edu/in-notes/rfc2554.txt, and
sendmail's particular implementation at http://www.sendmail.org/~ca/email/auth.html.
The SASL RFC is at ftp://ftp.isi.edu/in-notes/rfc2222.txt.
Return to the Linux DevCenter.
Copyright © 2009 O'Reilly Media, Inc.