Recently, I found myself trying to understand what was going on in the shadow file. For one thing, the “password” field in Ubuntu Lucid Lynx is much longer than it is in Red Hat Enterprise Linux 5. Then there were the exclamation points in front of some password entries.
Originally, there was no /etc/shadow file – the passwords and salts were contained with other user information in /etc/passwd. The problem was that /etc/passwd was readable by anyone, and that attacks became more common and more powerful. It was necessary to move the password into a separate file that would only be readable by root.
Here is an example of a shadow file line:
Each field is separated by a colon (
:). There are a number of fields:
- User name. This must match up with a user name in /etc/passwd; it is the key.
- Password. This field is a hash of the password (not the actual password itself) combined with an id (specifying which form of encryption was used) and with a salt.
- Last changed date. This is the day that the password was last set (in days since January 1, 1970).
- Minimum days. This is the minimum number of days that a password must be active before a password can be changed again. A user’s password cannot be changed by them until this number of days has elapsed.
- Maximum days. This is the maximum number of days for a password to be valid. Once the maximum number of days has elapsed, the user is forced to change their password.
- Warn days. Before a password expires, warn the user this many days ahead of time.
- Inactive days. Once a password has expired, it will be disabled after this many days.
- Expire date. On this date (in days since January 1, 1970), the account is disabled and the login can no longer be used.
Rather than trying to compute the date from the number of days since 1970, use the chage command:
$ chage -l ddouthitt Last password change : May 25, 2011 Password expires : never Password inactive : never 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
This also explains what each number means, and incorporates any defaults.
The password is more complicated. The actual password is not stored anywhere; the stored value in the /etc/shadow file is a hash generated from the password.
Originally, the password hash was just the hash itself; later, a two-character salt was added at the beginning.
The password hash today comes in three parts, separated by dollar signs ($):
- Id. This identifies the encryption hash method used. A value of 1 denotes MD5; 2 or 2a is Blowfish; 3 is NT Hash; 5 is SHA-256; and 6 is SHA-512.
- Salt. This is used by the encryption algorithms, and could be up to 16 characters.
- Hash. The actual “password” (or hash) is last. MD5 uses 22 characters, SHA-256 uses 43, and SHA-512 uses 86.
Picking apart the example password entry above shows this:
- Id =
- Salt =
- Hash =
Lastly, the password entry could be missing entirely (which means no password) or it could have an invalid entry (locked account).
Traditionally, locking was done with the asterisk (
*) by convention or by the word
LOCKED. However, this has been extended – by convention – to a variety of new suggestions. System logins that never had a password use a double exclamation mark (
!!) and accounts that have been locked have the valid password entry invalidated by a exclamation mark prefix. Using the prefix in this way allows the password to be reinstated as it was.
FreeBSD uses a slightly different setup, with a file called /etc/master.passwd, an extended /etc/passwd file with password aging included, and support for an extended DES format (which starts with an underline). Extended DES is more secure than the original DES, but is no longer used in favor of the new modular format described above. FreeBSD standardizes on MD5 – like Red Hat, and unlike Ubuntu.
By the way – that’s not my real password – so don’t look at it.
5 thoughts on “/etc/shadow format”
It’s worth noting that you can change the hashing method on most distros, including RHEL5, to make it more secure than the default MD5 hash. From RHEL 5.2, you can use authconfig to switch hashing methods, or specify it in your kickstart. I’m pretty sure RHEL6 uses a SHA algorithm by default.
thank you – you explained a lot of aspects that others overlooked. Thanks for making the effort to explain something you already understand to people you don’t know, and doing so in greater detail than others.
I would like to know a lot more about how /etc/shadow is generated when the system is installed. Is it a script that is run or something? Are kernel modules (in Linux) used to do the hashing? Is it standard for example to use 8 characters of salt from the set [./a-zA-Z0-9]? I know Fedora is using SHA512, obvious from $6$, but what about other distros? How to find out? Thanks for writing about the !! entry. I wondered what that would mean. I saw it meant password expired at one site, then here it says that those accounts never had a password. Hmm.
The way to find out a lot of this information is to read the man pages. When you are on the system, don’t just look at passwd(1) – which is the command itself – but look at such man pages as crypt(3). You can find these referenced in the bottom of relevant man pages in a section called “SEE ALSO”.
To access pages in different sections, use a command like
man 3 crypt
The crypt man page explains a lot.
Also, the method of disabling accounts is done by convention only – any characters other than the expected ones placed in the password field will disable the account, as the password becomes invalid. So differing conventions are possible and not abnormal.