Users, Groups and sudoLesson 2 of 4
Passwords, aging and account policy
Set and reset passwords, force changes, and apply aging rules per user and as system defaults.
passwdchagepasswd --stdinchpasswd/etc/login.defs/etc/security/pwquality.conf
After this lesson you can
- Set, expire, lock and unlock passwords, non-interactively when scripting.
- Read and set aging with chage: minimum, maximum, warning, inactivity and expiry.
- Change the defaults new users receive, and know that existing users keep their old values.
The idea
A password has a lifetime. /etc/shadow stores, for each account, the password hash and these aging fields, and chage is the tool that edits them.
| Field | chage option | Meaning |
|---|---|---|
| Minimum days | -m | Days that must pass before the password can be changed again |
| Maximum days | -M | Days after which the password must be changed |
| Warning days | -W | Days before expiry the user is warned at login |
| Inactive days | -I | Days after expiry before the account is locked |
| Expire date | -E | The date the account stops working, regardless of password |
| Last change | -d | Date of last change. -d 0 forces a change at next login |
Note the difference: the password expires after the maximum days, the account expires on a fixed date.
New accounts copy their defaults from /etc/login.defs (PASS_MAX_DAYS, PASS_MIN_DAYS, PASS_WARN_AGE) at creation time. Changing the file does not touch existing users: use chage for those.
Try it
sudo useradd dana
echo 'Temp#2026' | sudo passwd --stdin dana
sudo passwd -e dana
sudo chage -l dana
Changing password for user dana.
passwd: all authentication tokens updated successfully.
Expiring password for user dana.
passwd: Success
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
sudo chage -m 7 -M 60 -W 10 -I 5 dana
sudo chage -E 2027-06-30 dana
sudo chage -l dana
Last password change : password must be changed
Password expires : password must be changed
Password inactive : password must be changed
Account expires : Jun 30, 2027
Minimum number of days between password change : 7
Maximum number of days between password change : 60
Number of days of warning before password expires : 10
Once dana sets a new password the dates are filled in: Password expires becomes 60 days after the change, and Password inactive five days after that.
Passwords in scripts
passwd --stdin is a Red Hat addition. chpasswd takes user:password pairs on standard input and works the same way on other distributions:
printf 'dana:Temp#2026\nerin:Temp#2026\n' | sudo chpasswd
Locking
passwd -l and usermod -L put a ! before the hash so no password can match. passwd -S shows the state: PS usable, LK locked, NP no password. Locking the password does not stop key-based SSH logins; to block those too, set a past expiry date (chage -E 0 user) or change the shell to /sbin/nologin.
Going further
Complexity rules (length, character classes) are enforced by pam_pwquality and configured in /etc/security/pwquality.conf, for example minlen = 12. chage -l shows only human-readable dates; the raw numbers (days since 1970-01-01) are in /etc/shadow. faillock shows and resets accounts locked after repeated failed logins.
Practice
0 of 5 done
Do these on your own system. They get harder. Check each result, then tick it off.
- Warm-up
Reset a password and force a change
Create the user
dana(if needed). Set her password toTemp#2026without a prompt and force her to choose a new password at her next login.Check your result
sudo chage -l danashowsLast password change : password must be changed.Hint
passwd -e userexpires the password immediately.chage -d 0 userdoes the same.Solution
sudo useradd dana echo 'Temp#2026' | sudo passwd --stdin dana sudo passwd -e dana sudo chage -l dana - Practice
Apply the policy to one user
For
dana: allow a password change no more than once every 7 days, require a change every 60 days, warn 10 days before expiry, and disable the account 5 days after the password expires. Show the result.Check your result
sudo chage -l danashows minimum 7, maximum 60, warning 10, and aPassword inactivedate five days afterPassword expires.Hint
chage -mminimum,-Mmaximum,-Wwarning,-Iinactive days.Solution
sudo chage -m 7 -M 60 -W 10 -I 5 dana sudo chage -l dana - Practice
Make an account expire on a date
Make
dana's account expire on2027-06-30(not the password), then show how you would read that date back in a single line.Check your result
sudo chage -l dana | grep 'Account expires'printsAccount expires : Jun 30, 2027.Hint
chage -E YYYY-MM-DD.usermod -edoes the same job.Solution
sudo chage -E 2027-06-30 dana sudo chage -l dana | grep 'Account expires' - Practice
Change the defaults for future users
Change the system default so that new users must change their password every 90 days with a minimum of 2 days between changes and a 14-day warning. Create
erinand show she received those values, and show thatdanadid not change.Check your result
sudo chage -l erinshows 2, 90 and 14.dana's values are unchanged from the previous exercise.Hint
Edit
PASS_MAX_DAYS,PASS_MIN_DAYSandPASS_WARN_AGEin/etc/login.defs. These apply only to accounts created afterwards.Solution
sudo sed -i -e 's/^PASS_MAX_DAYS.*/PASS_MAX_DAYS 90/' \ -e 's/^PASS_MIN_DAYS.*/PASS_MIN_DAYS 2/' \ -e 's/^PASS_WARN_AGE.*/PASS_WARN_AGE 14/' /etc/login.defs sudo useradd erin sudo chage -l erin sudo chage -l dana - Challenge
Audit who is locked or expired
Lock
erin's password. Then write one command that prints every account whose password is locked, usingpasswd -S, and showerinin the output. Unlock her afterwards.Check your result
The output includes a line starting
erin LK. Afterpasswd -u erinthe status isPS.Hint
passwd -S userprints a status code:LKlocked,PSusable password,NPnone. Loop over the names fromcut -d: -f1 /etc/passwd.Solution
sudo passwd -l erin for u in $(cut -d: -f1 /etc/passwd); do sudo passwd -S "$u"; done | awk '$2=="LK"' sudo passwd -u erin sudo passwd -S erin