2 of 4

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.

  • passwd
  • chage
  • passwd --stdin
  • chpasswd
  • /etc/login.defs
  • /etc/security/pwquality.conf

35 min5 exercises

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.

Fieldchage optionMeaning
Minimum days-mDays that must pass before the password can be changed again
Maximum days-MDays after which the password must be changed
Warning days-WDays before expiry the user is warned at login
Inactive days-IDays after expiry before the account is locked
Expire date-EThe date the account stops working, regardless of password
Last change-dDate 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.

  1. Warm-up

    Reset a password and force a change

    Create the user dana (if needed). Set her password to Temp#2026 without a prompt and force her to choose a new password at her next login.

    Check your result

    sudo chage -l dana shows Last password change : password must be changed.

    Hint

    passwd -e user expires the password immediately. chage -d 0 user does the same.

    Solution
    sudo useradd dana
    echo 'Temp#2026' | sudo passwd --stdin dana
    sudo passwd -e dana
    sudo chage -l dana
  2. 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 dana shows minimum 7, maximum 60, warning 10, and a Password inactive date five days after Password expires.

    Hint

    chage -m minimum, -M maximum, -W warning, -I inactive days.

    Solution
    sudo chage -m 7 -M 60 -W 10 -I 5 dana
    sudo chage -l dana
  3. Practice

    Make an account expire on a date

    Make dana's account expire on 2027-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' prints Account expires : Jun 30, 2027.

    Hint

    chage -E YYYY-MM-DD. usermod -e does the same job.

    Solution
    sudo chage -E 2027-06-30 dana
    sudo chage -l dana | grep 'Account expires'
  4. 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 erin and show she received those values, and show that dana did not change.

    Check your result

    sudo chage -l erin shows 2, 90 and 14. dana's values are unchanged from the previous exercise.

    Hint

    Edit PASS_MAX_DAYS, PASS_MIN_DAYS and PASS_WARN_AGE in /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
  5. Challenge

    Audit who is locked or expired

    Lock erin's password. Then write one command that prints every account whose password is locked, using passwd -S, and show erin in the output. Unlock her afterwards.

    Check your result

    The output includes a line starting erin LK. After passwd -u erin the status is PS.

    Hint

    passwd -S user prints a status code: LK locked, PS usable password, NP none. Loop over the names from cut -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