Securing Linux with PAM

Like Unix, Linux system security has traditionally been based on the concept of passwords. But Linux also supports far more flexible authentication components that we'll look at this month, including shadow passwords, password-aging facilities, and its general authentication facility, PAM.

Guru/User Pwd Age
Figure One: linuxconf‘s password settings.

Like Unix, Linux system security has traditionally been based on the concept of passwords. But Linux also supports far more flexible authentication components that we’ll look at this month, including shadow passwords, password-aging facilities, and its general authentication facility, PAM.

Linux originally stored user passwords as the second field within the user-account database file, /etc/passwd. However, virtu-ally all current Linux distributions include the shadow package, which adds support for a shadow password file. This file is an alternate storage location for user account password data, and it has the advantage that it can be protected against anyone accessing it (even on a read-only basis) except the superuser. /etc/passwd can’t be similarly protected because many ordinary programs can’t function without accessing it.

When a shadow password file, /etc/shadow, is in use, the password field in /etc/passwd is usually replaced by a lowercase ‘x.’ Entries in a shadow password file use the following syntax:

username:coded password:

where username is the name of the user account, and coded password is the encoded user password, which is sometimes erroneously referred to as the “encrypted password.”

The remaining fields are the “pass-word aging” settings that determine when users are allowed or forced to change their passwords, and (optionally) when each account expires (see the Password Aging Fields Descriptions sidebar below for details).

Password Aging Field Descriptions

* last_change is the date of the last password change, measured as the number of days since January 1, 1970.

* max_days is the number of days that a user is allowed to keep the same password, and is often set to a very large value to effectively remove the limit.

* min_days determines how long a user must keep a new password before it can be changed again, and is intended to prevent a user from changing a password and then changing it back again to the old value. A value of zero disables this feature.

* warn_days indicates how many days in advance the user will be notified of an upcoming password expiration.

* inactive_days specifies the number of days after the password expires that the account will be automatically disabled if the password hasn’t changed.

* expire_date specifies the date on which the account expires and will be automatically disabled.

The last three entries in the shadow password file (warn_days, expire_ date, and inactive_days) can be left blank to disable those features. All the entries can be edited directly within the shadow password file, or you can use a graphical tool to examine and modify them, as shown in Figure One.

The top tool in the illustration is linuxconf from Red Hat Linux, which allows you to specify values for all of the shadow password fields. The middle tool in the illustration is the YaST program from a SuSE Linux system. It allows you to specify the amount of time before a password expires, the warning period for an about-to-expire password, the inactivity period after which the account will be locked, and an account expiration date. The bottom tool in the illustration, KDE’s User Manager, provides a different interface to the same underlying facility. You can enter specific dates for the various password-aging settings or disable them with a check box.

On SuSE Linux systems, the YaST administrative tool may also be used to set the values of the password-aging-related entries, as illustrated in Figure Two. While linuxconf does not provide an interface to login. defs, it does have entries for similar default settings, but these are linuxconf’s defaults, and they are ignored on systems where the shadow package is in use.

Guru/YaST Login
Guru/YaST Login#2
Figure Two: Specifying default password-aging settings on a SuSE system with the YaST administrative tool.

Default password-aging settings for new user accounts are in the shadow package’s configuration file, /etc/login.defs. The following sample entries specify a maximum password age of six months, a minimum password lifetime of three days, and a warning period of two weeks:


One Good Pick

Just as important to security as managing the passwords is making sure that good ones are selected in the first place. A “good” password is normally one that is easy to remember and type but difficult to guess. Checking the robustness of user passwords, often referred to as “triviality checking,” is typically performed when users select new passwords, although it may be done at other times as well. The well known Crack program is a popular way to test current user passwords. On a Linux system, triviality checking in the context of password changes also occurs in conjunction with the PAM (Pluggable Authentication Modules) facility, as we will explain below.

PAM is a general user-authentication facility available under Linux and Solaris version 7. PAM’s goal is to provide a flexible and administrator-configurable mechanism for authenticating users that is independent of programs that require authentication services. This allows programs to be developed separately from any authentication scheme. Instead they call various authentication modules at runtime to perform user-validation tasks and act appropriately based on the judgment of the modules. The home page for Linux PAM is www.us.kernel.org/pub/linux/ libs/pam/. PAM comprises of several components:

* PAM-aware versions of several traditional Unix authentication programs, called services, such as login and passwd.

* Modules to perform specific authentication tasks. These are implemented as shared libraries and are stored in the /lib/security directory. Each module is responsible for one small aspect of authentication. After executing, a module will return a result value to the PAM facility, indicating whether it will grant or deny access to the user, or even refrain from passing judgment by returning a neutral value.

* Configuration data indicating what authentication process should be performed for each supported service, specified via one or more PAM configuration files. Generally, each service has its own configuration file — having the same name as the service itself — in the directory /etc/pam.d. (The configuration file for the login service would be /etc/pam.d/login.) Alternatively, the entire facility may use a single configuration file, conventionally /etc/pam. conf. If both forms of configuration information are present and PAM has been compiled to allow multiple configuration sources, then files in /etc/pam.d take precedence over the contents of /etc/pam.conf.

Additional configuration settings are required by some of the PAM modules. These configuration files are stored in /etc/ security and have the same name as the corresponding service, with the extension .conf appended. As an example, Listing One shows the PAM configuration file /etc/pam.d/su.

Listing One: The su Configuration File

auth sufficient /lib/security/pam_rootok.so
auth required /lib/security/pam_wheel.so
auth required /lib/security/pam_pwdb.so shadow nullok
account required /lib/security/pam_pwdb.so
password required /lib/security/pam_pwdb.so
session required /lib/security/pam_pwdb.so

The first field of each entry indicates its entry type. This file has all four types of entries that can 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 for a password change within the context of the current service, and session entries are used for setting up and tearing down an environment, as well as logging activity via the syslog facility. The entries of a particular type are processed in turn and form a stack. In the su 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 specifies how the results of that particular module affect the outcome of the entire authentication process. In its simplest form, this field consists of one of four keywords: sufficient (if this module grants access to the user, then skip any remaining modules in the stack and return an authentication success), requisite (if this module denies access, then immediately return an authentication failure value and skip any remaining modules in the stack), required (similar to requisite, except that a failure still results in the other modules in the stack being invoked), and optional (the result of this module will be used to determine access only if no other module is deterministic).

The first two keywords 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 or not.

Once 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, then 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 (if only a filename is given, /lib/security is the assumed directory). Any required and/or optional arguments used by the module follow its path.

We can now decode the authentication process described in /etc/pam.d/ su. When a user enters an su command, three modules are used to determine whether execution should be allowed. First, the pam_rootok module checks whether the user is root or not (via the real UID). If so, success is returned and authentication ends here because of the sufficient keyword; if not, then authentication continues with the next module. pam_wheel returns success only if the user is a member of group 0, thereby limiting access to the command to that group.

The authentication process then continues with the pam_pwdb module, which requests and verifies the appropriate password for the command being attempted, which also depends on the specific user that is the target of su. The module returns success if the correct password is entered, and returns failure otherwise. pam_pwdb is passed two arguments: shadow indicates that a shadow password file is in use, while nullok specifies that a null password for the target account is acceptable.

The other three entries in the configuration file all call the same module, pam_pwdb. 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, the session entry generates a syslog entry for this invocation of su.

Many PAM modules are highly configurable. For example, the pam_wheel module allows you to specify an alternate group to which to grant su access other than the group 0, and it also allows you to grant access to everyone except members of a specific group. Consult the PAM documentation, usually found within the /usr/doc tree, for full details on the activities and options available for modules.

In comparison to the su file, the rlogin service has a much more complex configuration, as can be seen in Listing Two below.

Listing Two: The rlogin Configuration File

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_pwdb.so shadow nullok
account required /lib/security/pam_pwdb.so
account required /lib/security/pam_time.so
password required /lib/security/pam_cracklib.so retry=3, type=Linux, minlen=10, ocredit=2, dcredit=2
password required /lib/security/pam_pwdb.so nullok use_authtok shadow
session required /lib/security/pam_pwdb.so

When a user attempts to connect to the system via the rlogin service, the authentication process begins with the pam_securetty module, which 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 or not; if so its contents are displayed to the user, and authentication fails immediately. When /etc/nologin is not present, pam_rhosts_auth determines whether the traditional Unix rhosts mechanisms allow access to the system; if so, authentication succeeds immediately. In all cases, the pam_ pwdb module prompts for a user password, and the module uses the same arguments here as in the su example.

If authentication succeeds, the account stack comes into play. First, user- account and password controls are checked via the pam_pwdb module, which makes sure that the account isn’t expired and determines whether the password needs to be changed. Next, the pam_time module consults its configuration file to determine if this user is allowed to log in at the current time or not. 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 accepting it; the arguments to this module specify criteria used for some of these checks: The user is allowed three tries to select an appropriate password, the term Linux will be used in the new password prompt rather than Unix, and the password must have a minimum length-value of 10 (where each letter in the password counts as one and numbers and nonalphanumeric characters count as two for up to two of each of them — see the module documentation for more details on this rather bizarre scheme for forcing passwords to contain a variety of different kinds of characters). As usual, the session entry generates a syslog entry each time the rlogin service is used.

PAM also defines an additional service which is called other. 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   /lib/security/pam_warn.so
auth required /lib/security/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.

Circles Within Circles

The latest versions of PAM introduce a new, more-complex syntax for the severity field:

return-val=action[, return-val=action[,...]]

return-val is one of about 15 defined values that a module may return; action is a keyword indicating what action should be taken if that value is received. The available actions are: ok (grant access), ignore (no opinion on access), bad (deny access), die (immediate deny access), done (immediately grant access), reset (ignore the results of all modules processed so far and force those remaining in the stack to make the decision). 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. A severity field using the new syntax might be:


This says that a success return value from the module will grant access; it will still need to be combined with the results of the other modules in order to determine overall authentication success or failure. A file open error will cause 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, then the entire authentication process will fail immediately. The final item in this field specifies a default action when no other value is returned by the module, “deny access” in this case.

This will give you a taste of PAM’s power and flexibility. Be careful when you start working with something this powerful and complex; make sure that you test your changes on a noncritical system before attempting to apply them in a production environment. Using PAM effectively requires patience and experience, but the reward is worth the effort.

Æleen Frisch is the author of Essential System Administration. She can be reached at aefrisch@lorentzian.com.

Comments are closed.