Essential System Administration, Third Edition
Traditionally, with very few exceptions, user authentication on Unix systems occurs at login time. In recent years, however, a new scheme has emerged that allows the authentication process to be performed and customized for a variety of system contexts. This functionality is provided by the PAM facility. PAM stands for Pluggable Authentication Modules. PAM is a general user authentication facility available under and provided by current versions of FreeBSD, HP-UX, Linux, and Solaris. PAM's goal is to provide a flexible and administrator-configurable mechanism for authenticating users, independent of the various programs and facilities which require authentication services. In this way, programs can be developed independently of any specific user-authentication scheme instead of having one explicitly or implicitly embedded within them. When using this approach, utilities call various authentication modules at runtime to perform the actual user-validation process, and the utilities then act appropriately depending on the results the modules return to them. There are severalcomponents to the PAM facility:
The best way to understand how PAM works is with an example. Here is a simple PAM configuration file from a Linux system; this file is used by the su service:[18] [18] The format for the corresponding /etc/pam.conf file entries differs only slightly; the service name becomes the first field, with the remaining fields following, as in this example: su auth sufficient /usr/lib/security/pam_unix.so. auth sufficient /lib/security/pam_rootok.so auth required /lib/security/pam_wheel.so auth required /lib/security/pam_unix.so shadow nullok account required /lib/security/pam_unix.so password required /lib/security/pam_unix.so session required /lib/security/pam_unix.so As you can see, there are four types of entries that may appear within a PAM configuration file. Auth entries specify procedures for user authentication. Account entries are used to set user account attributes and apply account controls. Password entries are used when a password changes within the context of the current service. Session entries are generally used at present for login purposes to the syslog facility. The group of entries of a particular type are processed in turn and form a stack. In the example file, there is a stack of three auth entries and a single entry of each of the other three types. The second field in each entry is a keyword that specifies how the results of that particular module affect the outcome of the entire authentication process. In its simplest form,[19] this field consists of one of four keywords: [19] There is a newer, more complex syntax for the severity field, which we will consider later in this section.
The first two keywords are easy to understand, because they immediately either allow or deny access and terminate the authentication process at that point. The second two indicate whether the module is an essential, integral part of the authentication process. If no module denies or grants access before all of the modules in the stack have executed, authentication success or failure is determined by combining the results of all the required modules. If at least one of them grants access and none of them denies it, authentication is successful. Optional modules are used only when no definitive decision is reached by the required modules. The third field in each configuration file entry is the path to the desired module (sometimes, only a filename is given, in which case the default library location is assumed). Any required and/or optional arguments used by the module follow its path. Looking again at the su PAM configuration file, we can now decode the authentication process that it prescribes. When a user enters an su command, three modules are used to determine whether she is allowed to execute it. First, the pam_rootok module runs. This module checks whether or not the user is root (via the real UID). If so, success is returned, and authentication ends here because of the sufficient keyword (root does not need to enter any sort of password in order to use su); if the user is not root, authentication continues on to the next module. The pam_wheel module checks whether the user is a member of the system group allowed to su to root, returning success or failure accordingly (emulating a feature of BSD Unix systems), thereby limiting access to the command to that group. The authentication process then continues with the pam_unix module, which requests and verifies the appropriate password for the command being attempted (which depends on the specific user who is the target of su); it returns success or failure depending on whether the correct password is entered. This module is given two arguments in this instance: shadow indicates that a shadow password file is in use, and nullok says that a null password for the target account is acceptable (omitting this keyword effectively disables accounts without passwords). The other three entries in the configuration file all call the same module, pam_unix. In the account context, this module establishes the status of the target user's account and password, generating an automatic password change if appropriate; the password entry is invoked when such a password change is necessary, and it handles the mechanics of that process. Finally, this session entry generates a syslog entry for this invocation of su. Many PAM modules allow for quite a bit of configuration. The pam_wheel module, for example, allows you to specify which group su access is limited to (via its group option). It also allows you to grant access to everyone except members of a specific group (via the deny option). Consult the PAM documentation, usually found within the /usr/doc tree, for full details on the activities and options for available modules. Here is a more complex configuration file, for the rlogin service, again taken from a Linux system: auth requisite /lib/security/pam_securetty.so auth requisite /lib/security/pam_nologin.so auth sufficient /lib/security/pam_rhosts_auth.so auth required /lib/security/pam_unix.so account required /lib/security/pam_unix.so account required /lib/security/pam_time.so password required /lib/security/pam_cracklib.so retry=3 \ type=UNIX minlen=10 ocredit=2 \ dcredit=2 password required /lib/security/pam_unix.so \ use_authtok shadow md5 session required /lib/security/pam_unix.so session optional /lib/security/pam_motd.so motd=/etc/pmotd When a user attempts to connect to the system via the rlogin service, authentication proceeds as follows: the pam_securetty module presents connections to the root account via rlogin (if someone attempts to rlogin as root, the module returns failure, and authentication ends due to the requisite keyword). Next, the pam_nologin module determines whether the file /etc/nologin exists; if so, its contents are displayed to the user, and authentication fails immediately. When /etc/nologin is not present, the pam_rhosts_auth module determines whether the traditional Unix /etc/hosts.equiv mechanisms allow access to the system or not; if so, authentication succeeds immediately. In all cases, the pam_unix module prompts for a user password (the module uses the same arguments here as in the preceding example). If authentication succeeds, the account stack comes into play. First, user account and password controls are checked via the pam_unix module (which makes sure that the account is not expired and determines whether the password needs to be changed at this time). Next, the pam_time module consults its configuration file to determine whether this user is allowed to log in at the current time (discussed below). In order for system access to be granted, neither of these modules must deny access, and at least one of them must explicitly grant it. When a password change is required, the password stack is used. The first module, pam_cracklib, performs several different triviality checks on the new password before allowing it to be chosen. This module is discussed in more detail later in this section. Finally, the first session entry generates a syslog entry each time the rlogin service is used. The second session entry displays a message-of-the-day at the end of the login process, displaying the contents of the file specified with the pam_motd's motd option. 6.5.1 PAM Defaults
ThePAM facility also defines an additional service called other, which serves as a default authentication scheme for commands and facilities not specifically defined as PAM services. The settings for the other service are used whenever an application requests authentication but has no individual configuration data defined. Here is a typical other configuration file: auth required pam_warn.so auth required pam_deny.so These entries display a warning to the user that PAM has not been configured for the requested service, and then deny access in all cases. 6.5.2 PAM Modules Under Linux
As these examples have indicated, Linux systems provide a rich variety of PAM modules. Unfortunately, the other systems we are considering are not as well provided for by default, and you will have to build additional modules if you want them. We will now briefly list the most important Linux PAM modules. Two of the most important are discussed in more detail in subsequent subsections of this chapter. For each module, the stacks in which it may be called are given in parentheses.
6.5.2.1 Checking passwords at selection time
As we've seen, the pam_cracklib module can be used to check a proposed user password for strength. By default, the module checks the entered new password against each word in its dictionary, /usr/lib/cracklib_dict. It also checks that the new password is not a trivial transformation of the current one: not a reversal, palindrome, character case modification, or rotation. The module also checks the password against the module's list of previous passwords for the user, stored in /etc/security/opasswd. The arguments to this module specify additional criteria to be used for some of these checks. These are the most important:
As an example, consider our previous invocation of pam_cracklib: passwordrequiredpam_cracklib.so retry=3 type=Linux \ minlen=12 ocredit=2 dcredit=2 difok=3 In this case, the user is allowed three tries to select an appropriate password (retry=3), and the word "Linux" will be used in the new password prompt rather than Unix (type=Linux). Also, the password must have a minimum length-value of 12, where each character in the password counts as 1, and up to two numbers (dcredit=2) and two nonalphanumeric characters (ocredit=2) can each add an additional 1 to the "length." This effectively forces passwords to be at least seven characters long, and in that case, they must contain two digits and two non-alphanumeric characters (7 characters + 1 alpha + 2 digits + 2 other). Passwords containing only upper- and lowercase letters will have to be at least 10 characters long. The final option specifies that three characters in the new password must not be present in the old password. 6.5.2.2 Specifying allowed times and locations for system access
The pam_time module uses a configuration file, /etc/security/time.conf, that specifies hours when users may access defined PAM services. Here's an example: #services; ttys; users; times (Mo Tu We Th Fr Sa Su Wk Wd Al) login;tty*;!root & !harvey & !chavez;Wd0000-2400|Wk0800-2000 games;*;smith|jones|williams|wong|sanchez|ng;!Al0700-2000 The first line is a comment indicating the contents of the various fields (note that entries are separated by semicolons). Each entry within this configuration file specifies when access to the indicated services are allowed; the entry applies when all of the first three fields match the current situation, and the fourth entry indicates the times when access is allowed. In our example, the first line specifies that access to the login and rlogin services will be granted to any user except root, harvey, and chavez (the logical NOT is indicated by the initial !) all the time on weekends (Wd keyword in the fourth field) and on weekdays between 8:00 A.M. and 6:00 P.M., on any serial-line connected terminal. The second line prohibits access to any PAM-aware game by the listed users between 7:00 A.M. and 8:00 P.M. (again, regardless of tty); it does so by granting access at any time except those noted (again indicated by the initial exclamation point). Note that & and | are used for logical AND and OR, respectively, and that an asterisk may be used as a wildcard (although a bare wildcard is allowed only once within the first three fields). NOTE As you create entries for this configuration file, keep in mind that you are creating matching rules: use the first three fields to define applicability and the final field to specify allowed or denied access periods. Note that ampersands/ANDs usually join negative (NOT-ed) items, and vertical bars/ORs usually join positive items. Be aware that this module can provide time-based controls only for initial system access. It does nothing to enforce time limits after users have already logged in; they can stay logged in as long as they like. 6.5.2.3 MD5 passwords
Linux and some other Unix systems support much longerpasswords (up to at least 128 characters) using the MD5 encryption algorithm. Many PAM modules are also compatible with such passwords, and they provide an md5 option that may be used to indicate they are in use and to request their usage. These include pam_pwdb, pam_unix, pam_cracklib, and pam_pwcheck. If you decided to enable MD5 passwords, you will need to add the md5 option to all relevant modules in the configuration files for login, rlogin, su, sshd, and passwd services (and perhaps others as well).
6.5.3 PAM Modules Provided by Other Unix Systems
As we noted earlier, HP-UX, FreeBSD, andSolaris do not provide nearly as many PAM modules as Linux does by default. Each provides from 8 to 12 modules. All include a version of the basic password-based authentication module, pam_unix (named libpam_unix on HP-UX systems). There are also a few unique modules provided by these systems, including the following:
6.5.4 More Complex PAM Configuration
The latest versions of PAM introduce a new, more complex syntax for the final severity field: return-val=action [, return-val=action [,...]] where return-val is one of approximately fifteen defined values that a module may return, and action is a keyword indicating what action should be taken if that return value is received (in other words, if that condition occurs). The available actions are ok (grant access), ignore (no opinion on access), bad (deny access), die (immediate deny access), done (immediate grant access), and reset (ignore the results of all modules processed so far and force the remaining ones in the stack to make the decision). In addition, a positive integer (n) may also be specified as the action, which says to skip next n modules in the stack, allowing simple conditional authentication schemes to be created. Here is an example severity field using the new syntax and features: success=ok,open_err=ignore,cred_insufficient=die,\ acct_expired=die,authtok_expired=die,default=bad This entry says that a success return value from the module grants access; it will still need to be combined with the results of the other modules in order to determine overall authentication success or failure (as usual). A file open error causes the module to be ignored. If the module indicates that the user's credentials are insufficient for access or that his account or authentication token is expired, the entire authentication process fails immediately. The final item in the list specifies a default action to be taken when any other value is returned by the module; in this case, it is set to deny access. These examples have shown some of the features and flexibility of the PAM facility. Now it is time for you to experiment and explore it further on your own, in the context of the needs of your particular system or site. As always, be careful as you do so, and do some preliminary testing on a noncritical system before making any changes in a production system. Using PAM effectively requires experience, and everyone locks themselves out in some context as they are learning to do so. |