Disabling Linux user accounts – passwd and chage

Nov 28, 2010 • alan


On internet-facing machines, I like to disable the root password so that you can only log in as root using an SSH key.  This is done by setting the seemingly-scary option PermitRootLogin without-password in /etc/ssh/sshd_config .  This option means that you can ONLY use a key to log in as root… a password will never be accepted, and so you can not guess it by trial-and-error.

While I am at it, I go ahead and disable the root password completely.  That’ll be one less thing for me to remember, and one less thing to keep secret.

First, be sure that you have at least one “sudoer” user, or at least one SSH key in ~root/.ssh/authorized_keys . Otherwise, you’ll realize in an “ignisecond” that you’ve just locked yourself out.

Then, use the passwd command to “lock” the account.

$ passwd -l root

This command will put a ! character in the password field of the /etc/shadow file so that no password hash will ever match the string in the shadow file.

But on SOME SYSTEMS, it also does a second thing — it may change the account expiration date to January 2, 1970. This will prevent SSH access, even with a key.

While researching this article, I had this “world-shifting-under-me” feeling, as I distinctly remember having to work around this issue. However, on every system I tried, I could not reproduce the expiration-date-changing behavior. Then I found that it was an issue that flip-flopped in the Debian community between 2006 and 2008. In 2006, they made the passwd -l command lock the password and also expire the user account. But in 2008, they decided that the change affected too many people, where most had grown accustomed to the passwd command affecting the password only, and not touching the account expiration date.

If you want to change the account’s expiration date, you should use the chage command.

$ chage -E -1 root  # never expire
$ chage -E 1 root  # expire on Jan 2, 1970
$ chage -E 0 root  # not recommended, undefined behavior
$ chage -E 2010-12-25  # expire on a specific date

So here I was, all set to share a nugget of wisdom with the world, and instead, it ends up being a trip down memory lane. However, in the process, I learned a couple of things.

A very safe way to disable a user account’s password, while keeping the account open to SSH access is like this: passwd -l user && chage -E -1 user . The chage part is unnecessary on modern systems, but it does not hurt anything.

A quick way to check on whether a password is locked, or a user account is expired, is to use passwd -S user, like this.

$ passwd -S user
user P 09/11/2007 0 99999 7 -1

This says that user‘s password is set (P), it was changed way back 2007, there is no minimum age (restriction on how often they can change their password), there’s a very long maximum age (time when they are forced to change their password), the warning period is one week, and the account is not inactive/expired.

So there you go, two for one, a Linux tip and a history lesson!