/etc/passwd, /etc/shadow, and Password AgingOne of the first things to do when troubleshooting a login failure is to confirm that the account exists. The finger command shows user information, but because /etc/passwd has read permissions for all, we prefer just to grep for the user name. $ grep bob /etc/passwd bob:x:515:515::/home/bob:/bin/bash We are only confirming that there is an /etc/passwd line for this user to prove that the account hasn't been removed. /etc/passwd and /etc/shadowAccount information is stored in two files: /etc/passwd and /etc/shadow. All users can view the /etc/passwd file: $ ls -l /etc/passwd -rw-r--r-- 1 root root 2423 Jan 21 11:17 /etc/passwd The /etc/passwd file has seven fields, as shown in Table 14-1.
The /etc/passwd file is completely explained in the passwd(5) man page. We are interested in the password field for the purposes of this chapter. The password field does not contain the encrypted password. It should have an "x" instead. The password field did contain the password when UNIX was first released. As computers became more powerful, though, viewable encrypted passwords left systems vulnerable to brute force attacks. Thus, the password was moved to a new file that can only be read by root. This file is /etc/shadow. In Linux, the /etc/shadow file is delivered in the shadow-utils package. $ ls -l /etc/shadow -r-------- 1 root root 1974 Jan 22 13:30 /etc/shadow Let's look at the /etc/shadow entry for an account. The grep command is an easy way to view /etc/shadow. $ grep bob /etc/shadow grep: /etc/shadow: Permission denied Right. We must switch to root. #grep bob /etc/shadow bob:$1$lIDEzDIs$mVFLa6ZVsSolJS8yPc3/o.:12800:0:99999:7::: The /etc/shadow file contains password aging information as well as the password. The fields separated by ":" are explained in Table 14-2.
The /etc/shadow date fields are in days since January 1st, 1970. The password expiration date is the result of adding the date the password was last changed field and the maximum age of password field. See the shadow(5) man page for more details. chage, passwd, and usermodThe chage, passwd, and usermod commands can be used to modify password aging parameters. The usermod command duplicates some but not all the password aging features of chage. The chage -l username syntax is a good way to view the password aging settings for accounts. The following example shows the default password aging information for an account: #chage -l bob Minimum: 0 field 4 /etc/shadow Maximum: 99999 field 5 /etc/shadow Warning: 7 field 6 /etc/shadow Inactive: -1 field 7 /etc/shadow Last Change: Jan 17, 2005 field 3 /etc/shadow Password Expires: Never field 3 + field 5 Password Inactive: Never field 3 + field 5 + field 7 Account Expires: Never field 8 /etc/shadow Let's look at the password aging example. A user tries to log in on January 19, 2005 using ssh, but the term window is disconnected immediately after entering the password: login as: dbadmin3 Sent username "dbadmin3" TIS authentication refused. lori@sawnee.somecomp.com's password: The login attempt doesn't identify the problem. The chage -l username command shows that the account expired yesterday, preventing logins. #chage -l dbadmin3 Minimum: 0 Maximum: 99999 Warning: 7 Inactive: -1 Last Change: Jan 17, 2005 Password Expires: Never Password Inactive: Never Account Expires: Jan 18, 2005 The Password Inactive and Account Expires dates prevent a user from logging in. When the Password Expires date is reached, the user should be forced to change his or her password during login. However, ssh will just fail the login attempt. Table 14-3 shows the more useful chage syntaxes.
Here is an example showing a change to the maximum password lifetime. Password lifetime is field 5 of /etc/shadow. #grep dbadmin /etc/shadow dbadmin:$1$TuCLLDqz$Fc1YnK309QXT6TJMOagdZ.:12841:0:99999:7::: We can use grep to see this information, but chage is nicer. #chage -l dbadmin Minimum: 0 Maximum: 99999 Warning: 7 Inactive: -1 Last Change: Feb 27, 2005 Password Expires: Never Password Inactive: Never Account Expires: Never Now let's set the maximum password lifetime using chage. #chage -M 30 dbadmin We can use grep to see that the password aging field is now 30. #grep dbadmin /etc/shadow dbadmin:$1$TuCLLDqz$Fc1YnK309QXT6TJMOagdZ.:12841:0:30:7::: Once again, chage -l username offers nicer output. # chage -l dbadmin Minimum: 0 Maximum: 30 Warning: 7 Inactive: -1 Last Change: Feb 27, 2005 Password Expires: Mar 29, 2005 Password Inactive: Never Account Expires: Never A -1 for either a date or days field clears the field from /etc/shadow. Here is an example demonstrating how to reset the Account Expires date, which is field 8. Once again, we look at the password aging information with both grep and chage so that we can clearly see which field is being changed. #grep lori /etc/shadow lori:$1$cQG1pnOz$UHRmboguvqvOyJv5wAbTr/:12805:0:30:7::12847: chage -l lori Minimum: 0 Maximum: 30 Warning: 7 Inactive: -1 Last Change: Jan 22, 2005 Password Expires: Feb 21, 2005 Password Inactive: Never Account Expires: Mar 05, 2005 Here chage is used to clear the account expiration date. #chage -E -1 lori #chage -l lori Minimum: 0 Maximum: 30 Warning: 7 Inactive: -1 Last Change: Jan 22, 2005 Password Expires: Feb 21, 2005 Password Inactive: Never Account Expires: Never Field 8 is empty. #grep lori /etc/shadow lori:$1$cQG1pnOz$UHRmboguvqvOyJv5wAbTr/:12805:0:30:7::: The usermod command can set the account expiration date and the number of days after the password expires when the account is locked. The syntax is shown for each in Table 14-4.
The following example is similar to the previous chage example. This time, usermod is used to change the account expiration date, which is field 8 in /etc/shadow. #grep dbadmin /etc/shadow dbadmin:$1$TuCLLDqz$Fc1YnK309QXT6TJMOagdZ.:12841:0:30:7::: chage -l dbadmin Minimum: 0 Maximum: 30 Warning: 7 Inactive: -1 Last Change: Feb 27, 2005 Password Expires: Mar 29, 2005 Password Inactive: Never Account Expires: Never #usermod -e 2006-01-03 dbadmin #grep dbadmin /etc/shadow dbadmin:$1$TuCLLDqz$Fc1YnK309QXT6TJMOagdZ.:12841:0:30:7::13151: #chage -l dbadmin Minimum: 0 Maximum: 30 Warning: 7 Inactive: -1 Last Change: Feb 27, 2005 Password Expires: Mar 29, 2005 Password Inactive: Never Account Expires: Jan 03, 2006 Let's remove the Account Expires date: #chage -E -1 dbadmin #grep dbadmin /etc/shadow dbadmin:$1$TuCLLDqz$Fc1YnK309QXT6TJMOagdZ.:12841:0:30:7::: #chage -l dbadmin Minimum: 0 Maximum: 30 Warning: 7 Inactive: -1 Last Change: Feb 27, 2005 Password Expires: Mar 29, 2005 Password Inactive: Never Account Expires: Never The passwd command can change the password aging fields too. The passwd aging options are shown in Table 14-5.
The usermod and passwd commands can also disable an account. The different syntaxes are shown in Table 14-6.
A ! in the password field of /etc/shadow indicates a locked account. Notice the change in the password field after usermod is used to lock an account. #grep dbadmin /etc/shadow dbadmin:$1$TuCLLDqz$Fc1YnK309QXT6TJMOagdZ.:12841:0:30:7::: #usermod -L dbadmin grep dbadmin /etc/shadow dbadmin:!$1$TuCLLDqz$Fc1YnK309QXT6TJMOagdZ.:12841:0:30:7::: The chage -l output doesn't indicate that the account is locked. #chage -l dbadmin Minimum: 0 Maximum: 30 Warning: 7 Inactive: -1 Last Change: Feb 27, 2005 Password Expires: Mar 29, 2005 Password Inactive: Never Account Expires: Never The account can be unlocked with usermod -U, passwd -u, or by changing the password with the passwd command as root. Why can't the user change the password, assuming he or she is already logged in? Because the user is prompted for the current password before being granted the authority to change the password. The user doesn't know the password anymore because a ! character was added when the account was locked. Root isn't required to enter the current password, which enables the root user to unlock the account with passwd. The following is an example of a locked account being unlocked with passwd. #grep dbadmin /etc/shadow dbadmin:!$1$8nF5XmBG$Pckwi8Chld..JgP5Zmc4i0:12841:0:30:7::: #passwd -u dbadmin Unlocking password for user dbadmin. passwd: Success. #grep dbadmin /etc/shadow dbadmin:$1$8nF5XmBG$Pckwi8Chld..JgP5Zmc4i0:12841:0:30:7::: /etc/passwd and /etc/shadow CorruptionThe passwd and shadow files can be corrupted in numerous ways: /etc/shadow might have been restored while /etc/passwd was not, incorrect file permissions could cause problems, and so on. Let's look at what happens if someone edits /etc/shadow to clear password aging information while a user attempts to change his password. Look at Dave's /etc/shadow line: dave:$1$dkdAH.dQ$DU1t04WOFGjF4BGymI/ll0:12802:0:2:7::: The system administrator is using vi to edit /etc/shadow. Before the system administrator saves the file, Dave changes his password successfully by using the passwd command. /etc/shadow shows the change to the password field: dave:$1$VGCA.Vk8$9u2b8W5eCWjtOdt6ipOlD0:12804:0:2:7::: Now the system administrator saves /etc/shadow. When the administrator tries to save the file, he sees: WARNING: The file has been changed since reading it!!! Do you really want to write to it (y/n)? Hopefully, the system administrator replies n and tries again. If not, Dave loses his password change. Look at what happens to Dave's password. It changes back to the previous value: #grep dave /etc/shadow dave:$1$dkdAH.dQ$DU1t04WOFGjF4BGymI/ll0:12802:0:2:7::: Be careful when making changes to /etc/passwd or /etc/shadow. Always try to use a command to make changes instead of editing the file. pwckLinux provides the pwck command to look for /etc/passwd and /etc/shadow problems. This command validates field entries and looks for duplicate lines. No output from pwck means it didn't identify any problems. It will not find all problems, so you might need to inspect the passwd and shadow files line by line to confirm the lines are correct. The following error is caused by user rob not having an entry in /etc/shadow. The pwck command didn't catch it. passwd rob Changing password for user rob. passwd: Authentication token manipulation error |