Password Policies, PAM, and Account Locking
Understand Linux PAM authentication, password and account states, aging controls, lockout concepts, and safe policy-change practices.
Learning objectives
By the end of this lesson
- Explain how an application, PAM stack, identity source, and account policy cooperate during authentication.
-
Interpret password status and aging information with
passwd -Sandchage -l. - Distinguish password expiration, password locking, account expiration, and failed-login controls.
- Inspect PAM and policy files without exposing secrets.
- Apply and verify a reversible password-aging policy on a temporary lab account.
1. Authentication is a stack
A login service such as SSH, a console login, sudo, or
a display manager does not usually implement every authentication
and account rule itself. It invokes the Pluggable Authentication
Modules framework. A service-specific PAM configuration selects
modules for authentication, account eligibility, credential changes,
and session setup.
flowchart TD C["Login client"] --> S["Service: sshd, login, sudo, or display manager"] S --> P["Service PAM stack"] P --> A["auth: prove identity"] P --> K["account: allowed now?"] P --> M["password: change credentials"] P --> E["session: initialize and audit"] A --> I["Local or external identity source"] K --> Q["Aging, expiry, lockout, access rules"] E --> H["User session with credentials"]
PAM files are policy code. Module order, control flags, and include relationships determine whether a failure is fatal, ignored, or combined with another result. A copied line from a different distribution can lock out every administrator or weaken authentication silently.
Never experiment with PAM on a production host without a tested console or rescue path, a backup of the exact files, syntax and policy review, and a second authenticated session kept open for recovery.
2. Separate password and account states
Because services can use different PAM stacks and authentication
methods, test the exact entry point. A successful
su test does not prove SSH policy, and a locked local
password says nothing about an external identity provider.
3. Password verifiers and aging metadata
The protected shadow record stores an encoded password verifier or a marker indicating a locked/unusable password, plus day-based aging fields. Tools should interpret those fields for you. Do not parse or publish password hashes unless a specialized, authorized recovery process explicitly requires it.
account=${USER:?USER is not set}
# Read account status through supported tools
sudo passwd --status "$account"
sudo chage --list "$account"
# Inspect site defaults and relevant PAM entry points without secrets
sed -n '/^[[:space:]]*[^#[:space:]]/p' /etc/login.defs 2>/dev/null | head -n 80
ls -l /etc/pam.d
# Identify authentication-related packages and modules carefully
find /usr/lib /lib -path '*security/pam_*.so' -type f 2>/dev/null | sort | head -n 40
/etc/login.defs often supplies defaults to
account-management tools; it is not necessarily a universal runtime
policy. Existing accounts keep their configured aging values, PAM
modules may enforce additional rules, and directory-backed accounts
may be governed elsewhere.
4. Read PAM configuration safely
A PAM line generally contains a module type, a control expression, a
module path/name, and arguments. Distribution configurations often
include shared stacks such as common-auth or
system-auth. Follow include chains before drawing
conclusions.
# Read-only inventory: service files and active non-comment lines
for file in /etc/pam.d/sudo /etc/pam.d/sshd /etc/pam.d/login; do
if [[ -r $file ]]; then
printf '\n=== %s ===\n' "$file"
grep -Ev '^[[:space:]]*(#|$)' "$file"
fi
done
# Search for commonly deployed aging and lockout modules
# Names and locations vary by distribution.
grep -RHE 'pam_(unix|faillock|tally2|pwquality|pwhistory|access)\.so' /etc/pam.d 2>/dev/null || true
Finding a module name does not prove it is effective. Control flags, ordering, includes, service selection, module arguments, and external configuration all matter.
5. Design usable authentication policy
Authentication policy balances attack resistance, recovery, usability, and automation reliability. Excessively frequent password expiration can encourage predictable password changes; lockout thresholds can become a denial-of-service vector; and policies designed for humans may break service accounts. Prefer multi-factor authentication where supported, strong secret handling, risk-based controls, and centralized lifecycle management.
Human, service, emergency, local fallback, and directory-backed accounts need different controls.
List SSH, console, sudo, application, API, and automation authentication paths.
Establish console access, break-glass credentials, ownership, monitoring, and rotation.
Use a lab host and negative tests before applying policy broadly.
Monitor failures, lockouts, support load, bypasses, and automation incidents.
6. Hands-on lab: apply reversible aging controls
This lab changes only a temporary local account on a disposable VM. It does not modify PAM. You will configure aging, inspect the result, distinguish password lock from account expiration, and remove the account.
lab_user=da_policy_lab
if getent passwd "$lab_user" >/dev/null; then
printf 'Refusing to reuse existing account: %s\n' "$lab_user" >&2
exit 1
fi
sudo useradd --create-home --shell /bin/bash "$lab_user"
# Configure password aging values without setting a password.
sudo chage --mindays 1 --maxdays 90 --warndays 14 "$lab_user"
sudo passwd --status "$lab_user"
sudo chage --list "$lab_user"
# Lock the password verifier and inspect status.
sudo passwd --lock "$lab_user"
sudo passwd --status "$lab_user"
# Set and then remove an account-expiration date.
sudo chage --expiredate "$(date -d '+30 days' +%F)" "$lab_user"
sudo chage --list "$lab_user"
sudo chage --expiredate -1 "$lab_user"
# Force password change at next password-based login only after
# an administrator has securely assigned an initial password.
# sudo chage --lastday 0 "$lab_user"
sudo userdel --remove "$lab_user"
The account begins without a usable password, so unlocking it without first assigning a valid password may fail or create an unintended state. Treat password provisioning as a separate secure workflow.
Verification checklist
7. Common mistakes
Treating password lock as full deactivation
Keys, tokens, existing processes, and non-password services may remain active.
Editing PAM over the only remote session
One mistake can prevent every new login and sudo operation, leaving no recovery path.
Assuming login.defs changes existing accounts
Many values are defaults used at creation time; inspect each account and the active authentication stack.
Applying human password rules to automation
Unattended identities need non-interactive credential rotation, secret storage, and failure monitoring rather than manual password prompts.
8. Knowledge check
Question 1. What are the four common PAM module types?
auth proves identity, account checks
eligibility, password changes authentication tokens,
and session initializes or tears down the session
environment and auditing.
Question 2. Why does locking a password not necessarily disable an account?
Question 3. Why should PAM changes be tested with a second session kept open?
9. Summary
Linux authentication is composed from service-specific PAM stacks, identity sources, password/account metadata, and session controls. Diagnose the exact service path, distinguish password state from account state, use supported tools to interpret aging, and treat PAM edits as high-risk policy changes that require staging and recovery.
10. Further reading
-
pam(8),pam.d(5), and module-specific manuals. -
shadow(5),passwd(1), andchage(1). - Your distribution's PAM, password-quality, and failed-login documentation.
- Current organizational authentication, MFA, password, and account-recovery standards.
Keep the academy open
Support free, practical DevOps education.
Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0
Send only Ethereum/ERC-20 compatible assets to this
address.