Unix: Expiring passwords with chage

Unix sysadmins sometimes use the command chage -d 0 to immediately expire a user's password. While only one of a number of ways that you can use to disable accounts, it's one that's quick (it doesn't require opening the /etc/shadow file in a text editor) and

easily reversible with a similar command.

The chage (think "change age") command manipulates the time between password changes and the date that a password was last changed. It does this, of course, by modifying the fields in the /etc/shadow file that store this information.

The change -d 0 command sets the field that stores when the password was last changed to 0. This essentially says that the password was last changed at the start of the Unix epoch

(Jan 1, 1970).

Here how this works. A line in the shadow file might look like this:

lmoore:$2y$10$Ii.zQijisFXQyjpzMQJFquYCxy6xxGTwLQq3spaFh2Q5qN9sUVUiy:16353:0:90:7:::

Counting the colons, you can see that this format allows for nine separate fields. The last of these is still reserved, so unused. The first is obviously the username and the second the password hash. The remaining fields show the date the password was last changed -- expressed in the number of days since Jan 1, 1970 form.

OK, so the "password last changed" field being set to 16353 might not garner a "Yes, of course" reaction from anyone who doesn't solve quadratic equations in their head, but it's really not all that hard to figure out what this means. Given the commands below, we can see that 16,353 days is at least 44 years and, adding that to 1970, we get ... 2014! And, if we take this a little further, we can see that the date is likely very recent (293 being roughly 10 months). Plus there's undoubtedly a converter online somewhere that would turn this back into a precise date.

$ expr 16353 / 365
44
$ expr 1970 + 44
2014
$ expr 44 \* 365
16060
$ expr 16353 - 16060
293

This shows us that the password was changed fairly recently -- 293 being roughly 10 months -- so October 2014.

Another way to look at this number is to display the current date/time as the number of seconds since Jan 1, 1970.

$ date +%s
1413143716

Then calculate the number of seconds in a day.

$ expr 60 \* 60 \* 24
8640

Then divide today (as calculated above) by the number of seconds in a day, yielding today's date in days.

$ expr `date +%s` / 86400
16355

This show us that the password was changed only two days ago.

Now let's look at the other fields in the shadow file. The 0 represents the number of days that must pass before the password may be changed. In this case, it's 0, so the user can change his password whenever he wants. The 90 represents the number of days after which the password must be changed, so he probably has close to three months before the account is disabled. The 6th field (7) represents the number of days that he will be warned that his password is about to expire.

You can also set the field (the 7th field) that specifies the number of days after password expiration before the password actually expires. The 8th shows the date that the account was actually disabled -- again as the number of days since Jan 1, 1970. If you don't use either of these two fields, the password may expire, but the account will not be disabled.

Now, what if the shadow entry looks like this:

lmoore:$2y$10$E7Dzm.bjbqNzXt5TbBFLueCUJ/IUJlLcPCNqCT.VKrRT1y/.futWq:16353:0:99999:7:::

In this entry, we see that the user changed his password a couple days ago, but we also see that the number of days before it will expire is set to 99999. This seems to be the default, if only on some Linux systems. 99,999 days is a very long time -- more than 273 years. It is the equivalent of "never" as far as Unix password expiration is concerned. Even if we used the chage -d 0 command to indicate that the user hasn't changed his password since Jan 1, 1970, he would still be good to log in with more than 200 years left before his password expires.

The moral of the story is that chage -d 0 can be used to expire a password instantly, but only if passwords are set to expire at some reasonable interval.

The way to ensure that password aging is always used is to set the PASS_MAX_DAYS field in the /etc/login.defs file. In the example below, this field has been set to 90 -- probably a good compromise between passwords being used for too long and changing too frequently for users to remember.

PASS_MAX_DAYS   90
PASS_MIN_DAYS   7
PASS_MIN_LEN    12
PASS_WARN_AGE   7

Password aging is a good thing as it makes it less likely that a forgotten account will be left vulnerable or that your users will use the same password on multiple systems. Setting

This article is published as part of the IDG Contributor Network. Want to Join?

To express your thoughts on Computerworld content, visit Computerworld's Facebook page, LinkedIn page and Twitter stream.
Windows 10 annoyances and solutions
Shop Tech Products at Amazon
Notice to our Readers
We're now using social media to take your comments and feedback. Learn more about this here.