L8. PAM: How Linux Handles Authentication
Course outlineLesson 8 of 20
Pluggable Authentication Modules (PAM) is the framework that controls how Linux verifies user identity, enforces password policies, and locks accounts after failed attempts. This lesson covers how PAM works, its configuration structure, and the modules most relevant to security administration.
What Is PAM?
PAM (Pluggable Authentication Modules) is a framework that separates authentication logic from the applications that need it. Instead of every program (login, SSH, sudo, su) implementing its own password checking, account lockout, and session setup, they all delegate to PAM. PAM then decides which authentication checks to perform based on its configuration files.This design has two major security benefits:
- Centralized policy: You configure password strength rules, account lockout, and session limits in one place. PAM-aware services can share policy through included stacks; each service still has its own configuration.
- Modular design: You can add, remove, or reorder authentication steps (password checks, two-factor authentication, biometrics) without modifying any application code.
How PAM Works
When a user tries to log in via SSH, the sshd process does not check the password itself. Instead, it calls PAM with the username and credentials. PAM then processes a stack of modules defined in the relevant configuration file. Each module performs one check and returns a result (success, failure, or other). PAM combines these results according to its rules and tells sshd whether to allow or deny the login.
The Four PAM Module Types
PAM organizes its modules into four management groups. Applications invoke the groups they need; password changes are not a step in every login:
| Type | Purpose | Example |
|---|---|---|
| auth | Verify the user's identity (password, token, key) | Check password against /etc/shadow |
| account | Check if the account is allowed to log in | Verify account is not expired or locked |
| password | Handle password changes | Enforce strength requirements when changing a password |
| session | Set up and tear down the user's session | Create login records, set resource limits |
auth stack might first check a password, then check a two-factor token.
PAM Configuration Files
PAM configuration lives in the /etc/pam.d/ directory. Each file corresponds to a service (an application that uses PAM):
ls /etc/pam.d/Typical files:
| File | Controls Authentication For |
|---|---|
/etc/pam.d/sshd | SSH logins |
/etc/pam.d/login | Console logins |
/etc/pam.d/sudo | sudo commands |
/etc/pam.d/su | Switching users with su |
/etc/pam.d/common-auth | Shared auth config included by other files (Debian/Ubuntu) |
/etc/pam.d/system-auth | Shared auth config (RHEL/CentOS) |
/etc/pam.d/common-password | Shared password policy (Debian/Ubuntu) |
/etc/pam.d/password-auth | Shared password policy (RHEL/CentOS) |
Configuration Line Format
Each line in a PAM file follows this structure:
type control module [arguments]Illustrative authentication line (not a complete stack):
auth required pam_unix.so
Control Values
The control field determines how PAM handles the module's result:
| Control | Behavior |
|---|---|
required | Must succeed for overall success. If it fails, continue checking remaining modules but ultimately deny. |
requisite | Must succeed. If it fails, immediately deny (do not continue the stack). |
sufficient | If this succeeds and no prior required module failed, immediately allow. |
optional | Result is only significant if it is the only module in the stack. |
required and requisite matters. required continues processing even after failure (which can reduce differences in failure timing). requisite fails immediately (which can leak information but is faster).
Essential PAM Modules
pam_unix: Standard Password Authentication
This is the most fundamental module. It checks passwords against /etc/shadow.
auth required pam_unix.so
pam_pwquality: Password Strength Enforcement
pam_pwquality enforces password complexity rules when users set or change passwords:
# Install on Ubuntu if not present
sudo apt install libpam-pwqualityConfiguration in /etc/pam.d/common-password (Ubuntu):
password requisite pam_pwquality.so retry=3 minlen=12 difok=3 ucredit=-1 lcredit=-1 dcredit=-1 ocredit=-1
| Parameter | Meaning |
|---|---|
minlen=12 | Minimum password length of 12 characters |
difok=3 | At least 3 characters must differ from the old password |
ucredit=-1 | At least 1 uppercase letter required |
lcredit=-1 | At least 1 lowercase letter required |
dcredit=-1 | At least 1 digit required |
ocredit=-1 | At least 1 special character required |
retry=3 | Allow 3 attempts before failing |
/etc/security/pwquality.conf:
sudo cat /etc/security/pwquality.conf
pam_faillock: Account Lockout After Failed Attempts
pam_faillock (which replaced the older pam_tally2) locks accounts after a configurable number of failed login attempts:Use your distribution's supported PAM management tooling rather than pasting a generic stack into a live host. Configure policy in /etc/security/faillock.conf, for example:
deny = 5
fail_interval = 900
unlock_time = 900
silentThe auth stack must route failed authentication to pam_faillock.so authfail. Use authsucc to clear prior failures after success, or the documented account-module arrangement with a preauth check. A preauth check can reject an already locked account. Calling authfail unconditionally records successes as failures; omitting the success reset can count nonconsecutive failures. See the complete pam_faillock(8) examples and your distribution guidance before changing the stack.
| Parameter | Meaning |
|---|---|
deny=5 | Lock the account after 5 failed attempts |
unlock_time=900 | Automatically unlock after 900 seconds (15 minutes) |
audit | Log failed attempts to the system log |
silent | Do not reveal to the user that the account is locked (prevents enumeration) |
# View failed login attempts for a user
faillock --user idan# Unlock a locked account
sudo faillock --user idan --reset
pam_limits: Resource Limits
pam_limits enforces resource limits defined in /etc/security/limits.conf:
# /etc/security/limits.conf
# Limit the number of simultaneous logins
* hard maxlogins 3# Limit maximum number of open files
* soft nofile 1024
* hard nofile 65536
# Limit process count (prevents fork bombs)
* hard nproc 256
The nproc limit is a defense against fork bomb attacks (:(){ :|:& };:), which spawn processes recursively until the system runs out of resources.
Password Aging and Expiration
PAM works in conjunction with password aging settings stored in /etc/shadow and managed with the chage command:
# View password aging information for a user
sudo chage -l idan# Set password to expire after 90 days
sudo chage -M 90 idan
# Set minimum days between password changes (prevents rapid cycling)
sudo chage -m 7 idan
# Set warning period (days before expiry to warn user)
sudo chage -W 14 idan
# Force password change on next login
sudo chage -d 0 idan
Example Legacy Password Policy Settings
| Setting | Example Value | Purpose |
|---|---|---|
| Maximum age | 90 days | Force periodic password rotation |
| Minimum age | 7 days | Prevent users from immediately reverting to old password |
| Warning period | 14 days | Give users time to plan a change |
| Minimum length | 12+ characters | Resist brute-force attacks |
| Complexity | Mixed case, digits, special chars | Increase keyspace |
| History | Remember last 12 passwords | Prevent password reuse |
Putting It Together: A Hardened PAM Configuration
Here is what a security-focused PAM auth stack looks like conceptually:
- pam_faillock (preauth): Check if the account is already locked
- pam_unix: Verify the password against /etc/shadow
- pam_faillock: Route failures to authfail and successes to authsucc to reset the tally
- pam_pwquality: Enforce password strength on changes
- pam_limits: Apply resource limits for the session
This layered approach ensures that every login attempt is checked against lockout policy, authenticated against the password store, and constrained by resource limits. Each module does one thing, and the stack combines them into a comprehensive authentication flow.
Common Mistakes to Avoid
- Editing PAM files without a backup: A misconfigured PAM stack can lock everyone out. Always keep a root shell open while testing changes.
- Assuming control flags hide all failure details: required continues after a failure; requisite stops immediately. Messages and timing also depend on the application and modules.
- Setting
unlock_time=0: This means locked accounts never automatically unlock, which can cause denial-of-service if an attacker deliberately triggers lockouts. - Forgetting the root account: Ensure root is either excluded from lockout policies or has an alternative recovery method (physical console access).
References
- ✓PAM separates authentication logic from applications: PAM-aware services use service-specific stacks that can include shared policy.
- ✓The four PAM module types are auth (identity verification), account (access checks), password (credential changes), and session (setup/teardown).
- ✓The "required" control continues processing after failure (continuing the stack), while "requisite" fails immediately (faster but leaks information).
- ✓pam_faillock replaces pam_tally2 for account lockout: configure deny count, unlock_time, and use the "silent" flag to prevent account enumeration.
- ✓pam_pwquality enforces password strength rules (length, complexity, similarity to old password) during password changes.
1. What is the primary advantage of PAM's centralized authentication design?
2. What is the difference between the "required" and "requisite" PAM control values?
3. Why should the pam_faillock "silent" parameter be enabled?