This post describes the PAM pam_cracklib credit system in relation to Linux PAM password complexity.
Overview of PAM
The Pluggable Authentication Modules (PAM) is a central, flexible, modular framework used to manage system authentication policies and facilitate user authentication. PAM provides a general Application Programming Interface (API) that privilege granting programs defer to for user authentication.
The PAM authentication flow is as follows:
Application (login, ssh, sudo, su, ftp, etc.) -> PAM -> Authentication source (local password, LDAP, Kerberos, etc.)
PAM separates authentication tasks into four management groups:
- Account Management – check user permission to service, user password expiry, etc.
- Authentication Management – user authentication, user credentials, challenge/response (password), biometrics.
- Password Management – facilitates password management – change, updates, etc.
- Session Management – pre/post user service connection tasks e.g. audit trail, mount user’s home directory, etc.
PAM pam_cracklib Module
When added to the PAM password stack, the pam_cracklib module performs strength checking of proposed user passwords. The module calls the cracklib routine that compares passwords against a dictionary of known (common, weak, default, etc.) words before performing further strength checks, such as:
- Palindrome: Is the new password a palindrome i.e. a string that reads the same backwards and forwards e.g. radar, madam, etc.
- Case Change Only: Is the new password the same as the old one with only a change of case?
- Similar: Is the new password too similar to the old one?
- Simple: Is the new password too small? This is controlled by 6 arguments: minlen, maxclassrepeat, dcredit, ucredit, lcredit, and ocredit.
- Rotated: Is the new password a rotated version of the old password?
- Already used: Has the password been used previously?
- Same consecutive characters: Optional check for same consecutive characters.
- Contains user name: Optional check whether the password contains the user’s name.
When enabled without arguments, default pam_cracklib strength checking options/values help to ensure sufficiently secure passwords are accepted.
The pam_cracklib Credit System
The pam_cracklib module offers various options of which the following directly control password complexity:
- minlen – Minimum password length
- lcredit – Minimum number of lower case letters
- ucredit – Minimum number of upper case letters
- dcredit – Minimum number of numeric characters
- ocredit – Minimum number of non-alphanumeric characters
The minlen option defines the minimum acceptable size for a new password. However, in addition to the number of characters, a credit (i.e. score) is awarded for each different character type used i.e. lower, upper, digit, other. The credit value of each character type used counts toward meeting the defined minlen value.
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.
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.
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.
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.
When using the PAM credit system, it is quite possible for a password with a length less than that defined by minlen to be accepted i.e. the password may also contain characters of one or more character types – lower, upper, digit, other.
Consider the following pam_cracklib configuration:
--/etc/pam.d/system-auth-ac: ... password required pam_cracklib.so minlen=12 lcredit=1 ucredit=1 dcredit=2 ocredit=1 ...
Following is the pam_cracklib password credit calculation for a user password of “@1Bcdef2”:
- @1Bcdef2: 8 credits awarded i.e. one for each character
- @: 1 credit awarded (other)
- 1,2: 1 credit awarded (digit)
- B: 1 credit awarded (upper)
- cdef: 1 credit awarded (lower)
8 + 4 = 12 (minlen)
Given the number and type of characters used in the password above, the system accepts a minimum password length of 8 characters. Note that a password containing 11 lowercase letters only will also be accepted i.e.:
- abcdefghijk: 11 credits awarded – one for each character
- abcdefghijk: 0 credit awarded (other)
- abcdefghijk: 0 credit awarded (digit)
- abcdefghijk: 0 credit awarded (upper)
- abcdefghijk: 1 credit awarded (lower)
11 + 1 = 12 (minlen)
The following are detailed examples of accepted and unaccepted passwords:
|minlen||Password||Password Length (chars)||Credit||Password Accepted?|
|10||qwertasdf||9||9 (chars) + 1 (lower) = 10||Yes|
|12||qwertasdfgz||11||11 (chars) + 1 (lower) = 12||Yes|
|14||qwertasdfgzxc||13||13 (chars) + 1 (lower) = 14||Yes|
|14||qwertasdf1$||11||11 (chars) + 1 (lower) + 1 (digit) + 1 (other) = 14||Yes|
|10||qwertasd||8||8 (chars) + 1 (lower) = 9||No|
|12||qwertasdfg||10||10 (chars) + 1 (lower) = 11||No|
|14||qwertasdfgzx||12||12 (chars) + 1 (lower) = 13||No|
Enforcing Password Complexity with pam_cracklib Credit System
In all of the examples so far, note that the use of the credit system does not actually enforce password complexity. To enforce password complexity, specify negative values for pam_cracklib options lcredit, ucredit, dcredit, ocredit. When specifying negative values, credits are not awarded for the use of lower, upper, digit and other characters, however the password must still contain characters from each of the specified character groups.
Consider the following pam_cracklib configuration:
--/etc/pam.d/system-auth-ac: ... password required pam_cracklib.so minlen=8 lcredit=-1 ucredit=-1 dcredit=-2 ocredit=-1 ...
With the above, a successful user password must …
- be of at least 8 characters in length and
- contain at least 1 lower-case character and
- contain at least 1 upper-case character and
- contain at least 2 digits and
- contain at least 1 other character
Note: CentOS/RHEL 7 use pam_pwquality module instead of pam_cracklib and the pam_pwquality module is backward compatible with its options.
PAM_PWQUALITY(8) System Manager's Manual PAM_PWQUALITY(8) NAME pam_pwquality - PAM module to perform password quality checking SYNOPSIS pam_pwquality.so [...] DESCRIPTION This module can be plugged into the password stack of a given service to provide some plug-in strength-checking for passwords. The code was originally based on pam_cracklib module and the module is backward compatible with its options.