Author: Federico Kereki
When they hear the word PAM, most people think of a certain blonde Canadian Playmate, but readers of this Web site surely will recognize the basic element of Linux security: the Pluggable Authentication Modules. So let’s talk about how this PAM works, and look at some examples of how it is used.
If each Linux program had to include its own authentication logic, we’d go crazy. How could you trust that all your applications implemented the same checks? And how could you implement extra controls?
PAM gives us a simple alternative: if a program needs to authenticate a user, it can call the PAM application programming interface, and that API will take care of running whatever checks you need, according to whatever rules you specify in your PAM configuration files. You can even modify your authentication mechanisms on the fly, and all PAM-aware applications will automatically start using the new authentication method.
Want to use biometric controls, such as fingerprint readers or iris scanners? If the hardware maker provides a PAM, you are set; you just have to include that module in your configuration files, and from that point on your new device will be available for all applications.
The PAM library provides four distinct areas:
- auth has to do with user identification, for example through entering a user name and password
- account deals with account limitations; given that the user is a valid one, what is he allowed to do?
- session manages connection management, including logging, for example.
- password has to do exclusively with password-related functions.
For each application that will use PAM, you need a configuration file in the /etc/pam.d directory. Your login configurations go in the /etc/pam.d/login file. (There is another, older, method that uses just a single /etc/pam.conf file, but it is rarely used these days.) You need to define which modules will be applied for each group, creating a “stack” of actions. Whenever a request is processed, the PAM library starts running through the modules in the appropriate stack. Depending upon the modules’ output, the user request will either be granted or denied.
To make this happen correctly, you need to select whether any given module is mandatory or optional, according to the following list:
- A requisite module must return “success” to keep the process going. If such a module fails, the PAM library will return “failure,” and won’t run any more modules in the stack.
- A required module is also mandatory, but if it fails, though the PAM API will still return “failure,” the rest of the modules in the same stack will still run.
- If a sufficient module succeeds, the PAM library will immediately return “success” without running any other modules.
- Finally, optional modules can succeed or fail; approval will be given depending upon whether any module eventually succeeds.
The PAM configuration files themselves are simple. Comments start with a hash character (“#”). Long lines can be continued by ending them with a backslash (“”). Other lines have three fields: the context area (auth, account, session, or password); the control flag (requisite, required, sufficient, or optional); and the path to the module that will be run, along with any possible parameters. (Actually, the second field can be more complicated, but we’ll skip those details here. Also, you can also use “include,” as in “auth include common-account,” to include rules from another text file.)
For default values, there is a special service named “other” whose rules are automatically applied for any application without a specific configuration file. The safest setup for this file to deny all requirements (module pam_deny.so takes care of that) and send a warning to the administrator (via module pam_warn.so):
# # default; denying everything is the safest way # auth required pam_deny.so auth required pam_warn.so account required pam_deny.so password required pam_deny.so password required pam_warn.so session required pam_deny.so
You could substitute
pam_deny.so and then the standard authentication method (user and password) would be applied. (And if you don’t care about security, substitute
pam_permit.so instead, and all requests will be accepted — but don’t say you weren’t warned!) For security concerns, give a quick look at the /etc/pam.d directory, and rename any configuration files for applications you don’t use, thus making sure the “other” configuration will apply; should you decide you need an application again, just rename the configuration back to its original name.
There’s no canonical list of modules, but it’s a safe bet that you are likely to bump into at least some of the ones listed below. You can usually find PAM modules at /lib/security (/lib64/security for 64-bit versions) though some distributions opt for /usr/lib/security. If you want more detailed information, try running
pam_unix2provide classic Unix-style authentication based on the /etc/passwd and /etc/shadow files. You can also use
pam_userdbfor validation against a Berkeley database.
pam_timelets you restrict access to services depending on the day of the week and the current time based on file /etc/security/time.conf.
pam_accessallows or denies access according to rules in /etc/security/access.conf. Whenever a user tries to log in, rules are scanned sequentially, and permission is conceded or refused depending on the first matching rule. Another way of doing this is with
pam_succeed_if, which lets you check for specific desired account characteristics, such as belonging to a certain group.
pam_listfileprovides yet another way of allowing or denying services based on the contents of a file. For example, you can limit
sshdaccess by creating a list of approved users (let’s call it /etc/ssh_users) and including
auth required pam_listfile.so item=user sense=allow file=/etc/ssh_users onerr=failin /etc/pam.d/sshd.
pam_permitalso have to do with access; the first module always denies access, while the second one accepts everybody (careful!). More drastically,
pam_nologinblocks all logins if file /etc/nologin exists
pam_motdallow showing messages to the user; the first one shows any file, and the second shows the “message of the day” file. Similarly,
pam_lastlogshows the date and time of the user’s last login, and
pam_mailtells him if he has mail.
pam_limitslets you specify limits on system resources, per file /etc/security/limits.conf.
pam_rootokallows the root user access without further checks. This usually appears in /etc/pam.d/su, so root will be able to act as any other user, without any password. You need include
auth sufficient pam_rootok.soto achieve this. A way to allow, but limit, su usage is with
pam_wheel, which provides root access only to members of group “wheel.” You must include
auth required pam_wheel.soin order to force this check.
pam_pwcheckprovide checks for password strength. (See below.)
pam_warnjust registers login information in the system log.
You can even roll your own modules, but you will probably only need those mentioned above or the ones in this list.
In another article, we saw how to use PAM to secure a remote connection by using
pam_access. (Another possibility would have been using
pam_listfile.) Now let’s turn to another example — and figure out how to make users pick good passwords.
If it were up to users, most would just skip passwords altogether, while some sysadmins might like them to change their passwords daily. Without going to extremes, you can use PAM to enforce reasonably good password practices. To do this, you need to edit the “password” stack in /etc/pam.d/passwd so that your controls will be executed whenever users try to change their
passwords by using either
pam_pwcheck. Both have similar functions, including:
- rejecting passwords that are too short, by specifying the
- forbidding passwords that were used before, or that are too similar to the previous one.
- forbidding new passwords that are the same as the previous one, only with case changes (so “LiNuX” is out if earlier you had “liNUx”).
- rejecting rotated or backwards-written previous passwords (so you cannot use “comlinux” if you previously used “linuxcom”).
- forcing the user to include uppercase characters, non-alphabetic symbols, or numbers in the new password.
You can even specify the
cracklib parameter to use the cracklib library to reject dictionary-found keywords. A possible /etc/pam.d/passwd file could be:
# # The user is given three opportunities to enter a strong password. # The password needs be at least 6 characters long, with at least # two digits, one uppercase letter, and one non-alphabetic character, # and any number of lowercase letters. # password required pam_cracklib.so retry=3 minlen=6 dcredit=-2 ucredit=-1 ocredit=-1 lcredit=0 # # Using use_authtok in the pam_unix module ensures it doesn't prompt # for a password on its own, but uses the one provided by pam_cracklib # instead. The pam_cracklib module doesn't store passwords (only # checks them) so we need the standard pam_unix module in order to # accomplish that. # password required pam_unix.so use_authtok
Check the pam_cracklib documentation for even more options.
PAM usage is the basis for GNU/Linux security, and provides great flexibility. Though PAM configuration isn’t quite straightforward (no graphic interfaces here!) it really isn’t that hard, and you can greatly enhance your safety by using PAM appropriately.