This article will help ensure your users are meeting password complexity requirements set by your organization. We will show you how to force password complexity for normal users on Red Hat 6 systems. This should also work on other Red Hat based systems like Fedora and CentOS.

What is Password Complexity?

For the most part this can be a very debatable discussion. Common thinking is a strong password would be comprised of AT LEAST 14 characters containing AT LEAST 1 capitalized alphabetic character, 1 lowercase alphabetic character, 1 digital, and 1 special character. Passwords should also not be based on a dictionary word.

Why Force Password complexity?

Left to their own devices most users will create a password they can remember easily. Unfortunately this usually means they will create a password also easily guessed by someone else. I have heard of people even using the word “password” or “letmein”. This poses real security concerns for a system and for user data.

Always Backup your Files

It's always a good idea to backup the files you are modifying, especially when working with pam.

cp /etc/pam.d/system-auth /root/system-auth

Configuring pam (Pluggable Authentication Modules)

Edit the file /etc/pam.d/system-auth with your favorite editor (vim, nano, etc..). Look for the line containing the pam_cracklib module like below:

password requisite pam_cracklib.so try_first_pass

We need to edit this line of the file and add the options we would like to enforce. To enforce the password complexity that we spoke about in the beginning of this article we will change the line to:

password requisite pam_cracklib.so try_first_pass retry=3 minlen=14 ucredit=-1 dcredit=-1 ocredit=-1 lcredit=-1

After changing the file be sure to save it and your done. If you have existing users on your system and you want to make sure they are meeting the password requirements you can force them to change their password on the next login. To do this we need to lock the user account, expire their password, and unlock the user account. Here are the simple step to accomplish this.

Lock an account

usermod -L johndoe

Expire their current password

chage -d 0 johndoe

Unlock their account

usermod -U johndoe

Check the status of their password

# chage -l johndoe
Last password change : password must be changed
Password expires : password must be changed
Password inactive : password must be changed
Account expires : never
Minimum number of days between password change : 0
Maximum number of days between password change : 99999
Number of days of warning before password expires : 7

Options

Below is a list of options that I chose to use for my password requirements.
For a complete list see here.

retry=N
Prompt user at most N times before returning with error. The default is 1.

minlen=N
The minimum acceptable size for the new password (plus one if credits are not disabled which is the default). In addition to the number of characters in the new password, credit (of +1 in length) is given for each different kind of character (other, upper, lower and digit). The default for this parameter is 9 which is good for a old style UNIX password all of the same type of character but may be too low to exploit the added security of a md5 system. Note that there is a pair of length limits in Cracklib itself, a “way too short” limit of 4 which is hard coded in and a defined limit (6) that will be checked without reference to minlen. If you want to allow passwords as short as 5 characters you should not use this module.

reject_username
Check whether the name of the user in straight or reversed form is contained in the new password. If it is found the new password is rejected.

dcredit=N
(N >= 0) This is the maximum credit for having digits in the new password. If you have less than or N digits, each digit will count +1 towards meeting the current minlen value. The default for dcredit is 1 which is the recommended value for minlen less than 10. (N < 0) This is the minimum number of digits that must be met for a new password.

lcredit=N 
(N >= 0) This is the maximum credit for having lower case letters in the new password. If you have less than or N lower case letters, each letter will count +1 towards meeting the current minlen value. The default for lcredit is 1 which is the recommended value for minlen less than 10. (N < 0) This is the minimum number of lower case letters that must be met for a new password.

ocredit=N 
(N >= 0) This is the maximum credit for having other characters in the new password. If you have less than or N other characters, each character will count +1 towards meeting the current minlen value. The default for ocredit is 1 which is the recommended value for minlen less than 10. (N < 0) This is the minimum number of other characters that must be met for a new password.

ucredit=N 
(N >= 0) This is the maximum credit for having upper case letters in the new password. If you have less than or N upper case letters each letter will count +1 towards meeting the current minlen value. The default for ucredit is 1 which is the recommended value for minlen less than 10. (N < 0) This is the minimum number of upper case letters that must be met for a new password.

A better explaination of how credits work can be found in "Creating Password Policies using pwquality".

Additional Reading