A.4. Sample PAM Configurations
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.
A.4.1. Typical Login Services
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 filefrom the perspective of an administrator wanting to change the system to use a network password databaseare 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.
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 Debianand 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.
A.4.2. Password Services
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.
A.4.3. An Authentication Stack
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
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.