How OpenSSH checks for locked Linux accounts

Last Modified: Tue, 17 Dec 2013 18:12:59 +0000 ; Created: Tue, 17 Dec 2013 17:15:10 +0000

I ran into some interesting behavior with OpenSSH 5.9 on Ubuntu 12.04 (64-bit) LTS. I set up accounts so that only SSH key login is allowed and not password based authentication. I also choose to not allow the user after login to set a password. This is accomplished with the following:

/etc/ssh/sshd_config

PubkeyAuthentication yes

ChallengeResponseAuthentication no
PasswordAuthentication no
UsePAM no

/etc/shadow

username:!*:15974:0:99999:7:::

Notice the !* which indicates that the password login is locked (and the * which means there is no valid password). From the passwd man page you see the "passwd -l" option which is what prefixes or removes the !, but as noted in the man page "Note that this does not disable the account. The user may still be able to login using another authentication token (e.g. an SSH key)."

So I expected to be able to login still, but I kept getting an error in my /var/log/auth.log: "User username not allowed because account is locked". Turns out that in OpenSSH when I set "UsePAM no" that I got the OpenSSH behavior which sees a leading "!" and considers the account locked.

With "UsePAM yes" the "!*" is only seen as a password disabled account and not fully locked so ssh public key login works, and the user's ability to change their password does not.

On a side note to disable an account so it cannot login via password nor ssh key authentication you use:

usermod --expiredate 1970-01-01 username

Note: You sometime see people recommending also doing "passwd -l username", but that is only to disable password based login and not required if you wish to simply disable the entire account.

Depending on your flavor of Unix the behavior of what is in your password entry (usually /etc/shadow sometimes /etc/passwd) for the locked password (or no password or invalid password) varies. Disabling account is best done by using an account expiration (i.e. usermod --expiredate) to ensure no login is possible. Try looking in your system's manual pages for specifics.

The man page for "sshd" also provides this useful info (emphasis added):

Regardless of the authentication type, the account is checked to ensure that it is accessible. An account is not accessible if it is locked, listed in DenyUsers or its group is listed in DenyGroups . The definition of a locked account is system dependant. Some platforms have their own account database (eg AIX) and some modify the passwd field ( "*LK*" on Solaris and UnixWare, "*" on HP-UX, containing "Nologin" on Tru64, a leading "*LOCKED*" on FreeBSD and a leading "!" on most Linuxes). If there is a requirement to disable password authentication for the account while allowing still public-key, then the passwd field should be set to something other than these values (eg "NP" or "*NP*").

I'd point out that using NP or *NP* may not be ideal as according to the passwd(5) man page that is a signal to look in an NIS server for the password. The paragraph above comes from the OpenSSH 5.9p1 version (Debian). The OpenSSH man page does not have this paragraph while the Debian man page does.

References: