Arch Linux PAM Expiry Semantics and OpenSSH Public-Key Authentication: Which Account Checks Apply?
0 reputation · 20 Mar 2022, 13:43 UTC
0 reputation · 20 Mar 2022, 13:43 UTC
Arch Linux delegates local authentication to PAM, where pam_unix reads /etc/shadow. Two shadow fields matter here: password expiry, configured with chage -M, which forces a change at next authentication, and account expiration, set with chage -E, which denies access after the given date. OpenSSH can run with UsePAM yes, yet public-key authentication does not necessarily traverse the same PAM stack as a password login.
The integration question is which expiry semantics survive when a user authenticates with an SSH key instead of a password. Whether the PAM account module runs for pubkey sessions, and therefore whether account expiration is honored, depends on the joint configuration of /etc/pam.d/sshd and sshd_config. Because Arch is a rolling release, these defaults can shift between upgrades, so the behavior should be re-verified rather than assumed.
Specific questions: Does sshd invoke the PAM account phase for publickey-only authentication when UsePAM yes is set? If not, which shadow field, password expiry or account expiry, still blocks a key-based login? And which sshd_config directives determine that outcome?
35275 reputation · 20 Mar 2022, 21:15 UTC
With UsePAM yes, sshd runs the PAM account phase for every successful login, including publickey-only authentication. Consequently, account expiration (chage -E, the 8th field of /etc/shadow) does block a key-based login, because pam_unix.so in the account stack of /etc/pam.d/sshd checks it. Password expiry (chage -M) does not block a key login, because the forced password change is triggered in the PAM auth phase, which pubkey authentication bypasses.
PAM splits work into four phases: auth, account, password, and session. The two expiry mechanisms live in different phases:
chage -M, -W, -I) is enforced when pam_unix authenticates a password. An expired password triggers the chauthtok flow—a forced change at next password login. A publickey login skips auth entirely, so an expired password is irrelevant to it.chage -E) is a validity check on the account itself, evaluated in the account phase. sshd calls pam_acct_mgmt() after any successful authentication method when PAM is enabled, so an expired account is refused regardless of how the user proved their identity.UsePAM yes in sshd_config — the master switch. Without it, sshd falls back to internal checks, which may honor account expiry but bypass your PAM policy entirely.account lines in /etc/pam.d/sshd — on Arch these typically pull in system-auth, which contains account required pam_unix.so. If an administrator removed this stack, expiry checks disappear.PasswordAuthentication no and PubkeyAuthentication yes only choose the auth method; they do not change whether the account phase runs.Arch defaults can shift across openssh/pambase upgrades, so test rather than assume:
# pick a test user, then:
sudo chage -E 1 testuser # expire the account
ssh -i ~/.ssh/id_ed25519 testuser@host # expect: account expired
sudo chage -E -1 testuser # clear expiry, login should work
sudo chage -M 0 testuser # force password change; key login should succeed
journalctl -u sshd -e # look for pam_unix(sshd:account) messagesAlso confirm the stack: grep -E '^(account|auth)' /etc/pam.d/sshd /etc/pam.d/system-auth.
The behavior above reflects long-standing OpenSSH/PAM semantics, but two local factors can change it: a customized /etc/pam.d/sshd missing the account stack, and PAM configurations that skip checks for system-UID ranges. If your test shows an expired account still logging in with a key, verify whether the account phase actually contains pam_unix.so.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.