The preceding presentation is fairly abstract and may be hard to digest without some examples. Here, then, are some concrete examples, taken from working Linux distributions. These include a login service, a password service, and a system that uses an authentication stack.
Login services include the login program (used by the console and the Telnet server); the X Display Manager (XDM) and its KDE and GNOME counterparts, KDM and GDM; the SSH server; POP and IMAP mail servers; and the FTP server. Other tools that are similar, but that deviate a bit more, include the su and sudo commands and password-protected screensavers.
Example A-1 shows the
/etc/pam.d/login file from a Debian Linux
system. (The original file has many comment lines, though, which
Example A-1 has omitted for brevity.) Because this
is a login configuration, the most important sections of this
file—from the perspective of an administrator wanting to change
the system to use a network password database—are the
auth and account stacks. These
stacks both contain calls to pam_unix.so, as
well as a few others that can restrict access in various ways or
display information.
Example A-1. Sample PAM login service configuration
auth requisite pam_securetty.so auth requisite pam_nologin.so auth required pam_env.so auth required pam_unix.so nullok account requisite pam_time.so account required pam_unix.so session required pam_unix.so session optional pam_lastlog.so session optional pam_motd.so session optional pam_mail.so standard noenv password required pam_unix.so nullok min=6 max=255 md5
To modify Example A-1 to use an LDAP server (just as
an example), you would add sufficient references
to the pam_ldap.so module to the
auth and account stacks just
before the existing
pam_unix.so calls. You may also want to add a
call to the pam_mkhomedir.so module to the
session stack, in order to create
users’ home directories if they
don’t already exist. Example A-2
presents all of these changes, with the changed and added material
shown in bold.
Example A-2. Sample PAM login service configuration with LDAP support
auth requisite pam_securetty.so auth requisite pam_nologin.so auth required pam_env.so auth sufficient pam_ldap.so auth required pam_unix.so nullok try_first_pass account requisite pam_time.so account sufficient pam_ldap.so account required pam_unix.so session required pam_unix.so session optional pam_lastlog.so session optional pam_motd.so session optional pam_mail.so standard noenv session required pam_mkhomedir.so skel=/etc/skel umask=0027 password required pam_unix.so nullok min=6 max=255 md5
Several variants on these changes are possible. For instance, instead
of adding pam_ldap.so before
pam_unix.so, you can add a
required call to pam_ldap.so
after pam_unix.so, but this requires changing
the status of pam_unix.so from
required to sufficient and also
associating the try_first_pass option with
pam_ldap.so. This order reversal can reduce
network traffic if significant numbers of users have locally defined
accounts. Debian’s configuration
doesn’t call any modules in the
auth or account stacks after
the pam_unix.so call, but some distributions do
make such calls. For them, the specification of which module is
called as sufficient has implications for the
conditions under which these subsequent modules are called.
Yet another option is to set the calls to both
pam_unix.so and pam_ldap.so
to sufficient and add calls to
pam_deny.so to the ends of these stacks. This
approach may be less confusing to configure because the order of
modules becomes a bit less important; however, a successful login
using any of the sufficient modules then bypasses
all subsequent modules in the stack, which may be undesirable.
If you want modules that must be placed after the actual
password-checking modules to be called in all cases, you may want to
look into using the pam_stack.so module. You can
then place your actual password-checking calls in a substack that
returns a single value, call pam_stack.so as a
required module, and have modules that appear
after this call in your individual service definitions execute no
matter what tool actually authenticated your users.
Unless your system uses the pam_stack.so module,
you should make changes similar to these on all of the PAM modules
corresponding to the login and other authentication services you use.
Of course, your files aren’t likely to be identical
to this one unless you use Debian—and even then, other Debian
PAM files aren’t identical to this one. You
therefore need to adjust your changes to suit your own files.
One login server requires a bit of extra attention: SSH. This server
sometimes doesn’t work well with PAM authentication.
If you can’t seem to get your SSH server to use your
new authentication tool, you may need to set one of two options in
the /etc/ssh/sshd_config file on the SSH server
system:
UsePAM yes UsePrivilegeSeparation no
I recommend trying UsePAM
yes
first. If that fails, try the second option. One of the two should
get SSH to play nicely with PAM.
The /etc/pam.d/passwd file on most systems
controls the passwd program’s
interactions with PAM. Example A-3 shows a sample
file from a SuSE system. This file is a bit simpler than a typical
login service definition.
Example A-3. Sample PAM password service configuration
auth required pam_unix2.so nullok account required pam_unix2.so password required pam_pwcheck.so nullok password required pam_unix2.so nullok use_first_pass use_authtok session required pam_unix2.so
Suppose that you want to enable users to change passwords on their
local accounts if they exist or on their LDAP accounts if they exist.
PAM can be rather picky about such arrangements; the
passwd command requires use of several PAM stacks
to do its work, from authentication through to the actual password
change. Thus, you must add references to
pam_ldap.so to three stacks. Example A-4 shows the result, with changed or added parts
highlighted in bold.
Example A-4. Sample PAM password service configuration with LDAP support
auth sufficient pam_ldap.so auth required pam_unix2.so nullok use_first_pass account sufficient pam_ldap.so account required pam_unix2.so password required pam_pwcheck.so nullok password optional pam_ldap.so use_first_pass use_authtok password required pam_unix2.so nullok use_first_pass use_authtok session required pam_unix2.so
This configuration enables users to change their passwords much as
they ordinarily do, by typing passwd and
answering the usual password-changing prompts. Making the actual
password call to pam_ldap.so
optional changes the LDAP password if it exists
but doesn’t cause the operation to fail if the LDAP
password doesn’t exist. Thus, this configuration
works for users who are defined locally, defined on the LDAP server,
or both. (The required nature of the
password stack call to
pam_unix2.so would seem likely to cause a
failure if the account isn’t defined locally, but in
practice, this isn’t a problem.)
This configuration does have one drawback: the root user is prompted for the LDAP password of users, if they have LDAP accounts, before being allowed to change them. As a practical matter, this means that system administrators must use LDAP tools, rather than the passwd command, to change users’ forgotten passwords or to set passwords on new accounts.
Of course, you can try variants on these changes. For instance, you
can require users to have LDAP accounts; however, this might be
undesirable if you want to maintain some local accounts (such as
root) independent of the LDAP
server. Alternatively, if you make the
pam_ldap.so call in the
password stack sufficient,
users with both LDAP and local accounts can change only their LDAP
passwords.
Some distributions, such as Red Hat, Fedora, and Gentoo, now use the
pam_stack.so module to place common
authentication options in a single file. This approach can greatly
simplify PAM configuration because you need to change only one file.
Example A-5 shows the
/etc/pam.d/system-auth file from a Gentoo
system. (The original includes the complete paths to the library
modules; Example A-5 omits these paths to keep line
lengths manageable.) In principle, this file is a combination of
other PAM configuration files, defining basic features used by all of
them. This file shouldn’t get too specific, though;
options that should apply only to a few authentication tools should
go in those tools’ configuration files.
Example A-5. Sample PAM stack service configuration
auth required pam_env.so auth sufficient pam_unix.so likeauth nullok auth required pam_deny.so account required pam_unix.so password required pam_cracklib.so retry=3 password sufficient pam_unix.so nullok md5 shadow use_authtok password required pam_deny.so session required pam_limits.so session required pam_unix.so
To modify Example A-5 to use LDAP in addition to the
local account database, you must add references to the
pam_ldap.so module in the
auth and account stacks. For
the latter, you may also want to change the existing call to
pam_unix.so to sufficient and
add a required call to
pam_deny.so to prevent too-easy bypassing of
account-maintenance requirements, should you implement any. You may
also want to add a call to the pam_mkhomedir.so
module in the session stack; however, you might
prefer putting this call in the individual server PAM modules to
better control home directory creation. Once all the changes are
made, the result looks like Example A-6, which shows
changed or added material in bold.
Example A-6. Sample PAM stack service configuration with LDAP support
auth required pam_env.so auth sufficient pam_ldap.so auth sufficient pam_unix.so likeauth nullok use_first_pass auth required pam_deny.so account sufficient pam_ldap.so account sufficient pam_unix.so account required pam_deny.so password required pam_cracklib.so retry=3 password sufficient pam_unix.so nullok md5 shadow use_authtok password required pam_deny.so session required pam_limits.so session required pam_unix.so session required pam_mkhomedir.so skel=/etc/skel/ umask=0022
Fedora and Red Hat autogenerate their
/etc/pam.d/system-auth files using a tool called
authconfig or its GUI equivalent,
system-config-authentication. If you make changes
to the raw PAM file, they may be wiped out if you run this tool.
Thus, you might want to modify the file by using the configuration
tool, rather than editing it directly. This tool also enables you to
set configuration options for specific network authentication tools,
such as locating your NT domain controller or LDAP server.
As always, many variants on this set of changes are possible. For
instance, you can make changes to the password
stack analogous with those described in the earlier Section A.4.2; however, I find that
implementing these changes directly in the
passwd file often produces better results.
This example configuration uses sufficient calls
to several modules along with pam_deny.so to
block accesses that fail all of these calls. This approach works well
when you have no calls subsequent to the
sufficient calls in a stack. In the case of a
stacked configuration like this, its calling stack can then place
additional module calls after the call to
pam_stack.so, no matter how the stack module
exits, if the calling stack calls pam_stack.so
as a required or requisite
module.
Changing a stack module’s configuration
doesn’t mean you can’t change
individual servers’ configurations. You can make
general changes to /etc/pam.d/system-auth and
then add other calls to the configuration files for
login, KDM, su, and other
tools, as you see fit.