Many years ago I wrote an article on "Strong Password Enforcement with pam_cracklib". Since that time, there have been some changes in Linux:
So while the advice in my previous article is still valid for many Linux distributions, I wanted to develop new guidance based on the current set of available password enforcement modules. Testing for this article was done on a CentOS 7.1 system.
On RedHat-based systems, password checks are enabled via configuration in the /etc/pam.d/system-auth and /etc/pam.d/password-auth files. Actually, these files are just symbolic links to /etc/pam.d/system-auth-ac and /etc/pam.d/password-auth-ac, respectively.
The default configuration looks like this:
password requisite pam_pwquality.so try_first_pass local_users_only retry=3 authtok_type= password sufficient pam_unix.so sha512 shadow nullok try_first_pass use_authtok
The try_first_pass option tells a later module to try using the password entered for a previous module. In the configuration above, pam_pwquality will require the user to enter a strong password choice, and the try_first_pass option on pam_unix module tells pam_unix to try this choice. Similarly, use_authtok tells pam_unix to use the password from the stacked pam_pwquality module.
Frankly, the try_first_pass option is redundant with the use_authtok option on pam_unix. And try_first_pass isn't necessary for pam_pwquality since there are no modules stacked in front of it.
Other default options set on pam_pwquality above include local_users_only, which tells pam_pwquality to ignore users that are not in the local /etc/passwd file (for example, users whose accounts are in an LDAP or Active Directory database). The retry option is the number of tries a user gets to pick an acceptable password before the module returns an error.
By default, the prompt the user gets when entering their password is "New password:". If the administrator sets authtok_type=FOO, the prompt becomes "New FOO password:".
For pam_unix, the sha512 option means use a password hashing routine based on the SHA512 algorithm. blowfish is also supported along with several other, less secure, choices. The shadow option means maintain password hashes in a separate /etc/shadow file that is only readable by the root user. This option should always be set. nullok means allow user accounts that have null password entries. Personally, I would recommend removing this option.
Taking all of this advice together, a better default configuration for these modules would be:
password requisite pam_pwquality.so local_users_only retry=3 password sufficient pam_unix.so sha512 shadow use_authtok
pam_pwquality performs a number of basic checks, just like the old pam_cracklib module:
However, pam_pwquality adds several other checks that can be enabled at the administrator's discretion (none of these checks are enabled by default):
pam_pwquality uses a "scoring" system that combines password length requirements with a "credit" system based on the number of different types of characters used. This is identical to the old pam_cracklib module.
You start with the minlen=N parameter which sets the minimum acceptable length for a password. However, the user gets one "credit" each for using a lower-case letter, an upper-case letter, a number, and a punctuation character. So if minlen=15, the user could still use an 11 character password if it contained all four character classes.
It is important to note that even a monocase password gives the user one "length credit". So if you set minlen=15 you are really saying that you allow 14 character monocase passwords.
While users normally get a maximum of one credit per type of character, you can use the lcredit, ucredit, dcredit, and ocredit parameters to create a different scheme:
password requisite pam_pwquality.so minlen=19 lcredit=0 ucredit=1 dcredit=1 ocredit=2 ...
In the above example, no credits are given for lower-case letters (lcredit=0). Upper-case letters (ucredit=1) and digits (dcredit=1) can give up to one credit, which is the default. Users may receive credits for up to two punctuation characters (ocredit=2) if they are included in the password. Since minlen=19, the user must still come up with at least a 15 character password, even if they get all possible credits.
If you want to require users to use certain character classes, use negative values:
password requisite pam_pwquality.so minlen=15 lcredit=0 ucredit=0 dcredit=-1 ocredit=-1 ...
The above example requires a 15 character password with at least one digit and one punctuation-type character. Note that requiring the password to contain certain character types actually makes life easier for somebody who is trying to brute-force your user passwords, since they can skip testing strings that don't match your requirements.
pam_pwquality also supports a minclass=N parameter that requires characters from at least N of the four different character classes. This is probably a better way to go than specifically requiring a specific type of character.
On RedHat systems, all of the parameters we've been discussing in the last two sections can be set in /etc/security/pwquality.conf. This is probably easier than hacking the parameters into long lines in the PAM configuration files.
On RedHat systems, passwords are checked against a dictionary stored in /usr/share/cracklib/pw_dict.*. The files are in a database format that can be built using the create-cracklib-dict program. Use the cracklib-unpacker program to see the contents of the current system dictionary.
Debian systems typically place their dictionaries in /var/cache/cracklib. There's a nightly cron job that runs update-cracklib to rebuild the dictionary.
The password history checking code in pam_cracklib and pam_unix is being deprecated in favor of the new pam_pwhistory module. However, if you're familiar with the old way of doing things, you'll find that the paramaters used by pam_pwhistory are the same.
Here's a typical configuration stacking pam_pwhistory in with pam_pwquality and pam_unix:
password requisite pam_pwquality.so local_users_only retry=3 password required pam_pwhistory.so remember=400 use_authtok password sufficient pam_unix.so sha512 shadow use_authtok
The remember=N parameter says how many old passwords to remember for each user. The default is 10, and 400 is an internal hard-coded maximum. Even if you were to force users to change passwords monthly, that still gives you more than 30 years of password history. So remember=400 is effectively infinite.
The old password hashes for users are stored in /etc/security/opasswd.
Password expiration is still controlled by pam_unix. You get to control:
You can set defaults for the first three parameters in /etc/login.defs. The default setting for INACTIVE is found in /etc/default/useradd. Note that these defaults are only used if you use the built-in useradd command to make user accounts.
You can manually set these parameters on a user's account using the chage command. You can view the settings for a user by inspecting their /etc/shadow entry (see "man 5 shadow" for which field is which).
Constant brute-force password guessing attacks have made "lockout on failure" functionality a necessary evil. On modern Linux systems, this is handled by the pam_tally2 module.
For Redhat systems, add a line like this at the top of /etc/pam.d/system-auth-ac and password-auth-ac:
auth required pam_tally2.so deny=3 unlock_time=1800 even_deny_root
Accounts will be locked after three failures (deny=3) but automatically unlocked after 30 minutes (unlock_time=1800 uses seconds as the unit). If the unlock_time parameter is left off, then accounts stay locked until the administrator manually intervenes.
even_deny_root says to apply lockout on failure to the root account as well-- this is not the default. You can set a special timeout for the root account with the root_unlock_time=N parameter if you like. Generally speaking, you should not be allowing direct root logins to your system ("PermitRootLogin no" in your sshd_config file), so locking out the root account shouldn't be a factor.
Login failure and user lockout records are stored in /var/log/tallylog by default. You can change this with the file= option.
There is also a command-line program called pam_tally2. This is how admins query and unlock user accounts that have been locked out due to failures.
Here's a sample password-auth-ac file with a reasonable default configuration:
auth required pam_tally2.so deny=3 unlock_time=1800 even_deny_root auth required pam_env.so auth sufficient pam_unix.so nullok try_first_pass auth requisite pam_succeed_if.so uid >= 1000 quiet_success auth required pam_deny.so account required pam_unix.so account sufficient pam_localuser.so account sufficient pam_succeed_if.so uid < 1000 quiet account required pam_permit.so password requisite pam_pwquality.so local_users_only retry=3 minlen=19 gecoscheck maxrepeat=3 password required pam_pwhistory.so remember=400 use_authtok password sufficient pam_unix.so sha512 shadow use_authtok password required pam_deny.so session optional pam_keyinit.so revoke session required pam_limits.so -session optional pam_systemd.so session [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid session required pam_unix.so
Don't forget system-auth-ac:
auth required pam_tally2.so deny=3 unlock_time=1800 even_deny_root auth required pam_env.so auth sufficient pam_fprintd.so auth sufficient pam_unix.so nullok try_first_pass auth requisite pam_succeed_if.so uid >= 1000 quiet_success auth required pam_deny.so account required pam_unix.so account sufficient pam_localuser.so account sufficient pam_succeed_if.so uid < 1000 quiet account required pam_permit.so password requisite pam_pwquality.so local_users_only retry=3 minlen=19 gecoscheck maxrepeat=3 password required pam_pwhistory.so remember=400 use_authtok password sufficient pam_unix.so sha512 shadow use_authtok password required pam_deny.so session optional pam_keyinit.so revoke session required pam_limits.so -session optional pam_systemd.so session [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid session required pam_unix.so