Previously in FreeBSD Basics:
In last week's article, we looked at using the
adduser utility to create user accounts. This week, we'll concentrate on the files that are modified when a user account is created.
When the superuser creates a user account, an entry for that user is added to the password database. Your FreeBSD system actually has four password database files that need to be updated. Let's summarize these files before taking a detailed look at their format. The first file is called
/etc/passwd, and it is an ASCII text file readable by anyone:
file /etc/passwd /etc/passwd: ASCII text ls -l /etc/passwd -rw-r--r-- 1 root wheel 1054 Dec 30 13:00 /etc/passwd
The permissions on this file need to stay the way they are or most of your FreeBSD utilities would stop working. However, it would be a security risk to store passwords in a file readable by anyone; for this reason, an
* is used in the portion of this file where the password would normally be stored.
The second file is the shadow password file, or
/etc/master.passwd. This file contains the encrypted hashes of users. We'll be taking a deeper look at encryption and hashes in future articles; for now, think of a hash as the value that FreeBSD uses to determine if a user's password is valid.
Let's see what type of file this is and who can read it:
file /etc/master.passwd /etc/master.passwd: ASCII text ls -l /etc/master.passwd -rw------- 1 root wheel 1226 Dec 30 13:00 /etc/master.passwd
The shadow password file is still in plain, ASCII text, but it is only readable by root.
The third and fourth password files are called
/etc/spwd.db. Let's take a look at their file types:
/etc/pwd.db: Berkeley DB Hash file (Version 2, Little Endian, Bucket Size 4096, Bucket Shift 12, Directory Size 256, Segment Size 256, Segment Shift 8, Overflow Point 3, Last Freed 2, Max Bucket 7, High Mask 0xf, Low Mask 0x7, Fill Factor 32, Number of Keys 56)
/etc/spwd.db: Berkeley DB Hash file (Version 2, Little Endian, Bucket Size 4096, Bucket Shift 12, Directory Size 256, Segment Size 256, Segment Shift 8, Overflow Point 3, Last Freed 2, Max Bucket 7, High Mask 0xf, Low Mask 0x7, Fill Factor 32, Number of Keys 56)
These definitely aren't ASCII text files, so don't try to open them up with
more, or a text editor. These two files contain the same information as the ASCII text files, but in a database form that improves performance. Since
/etc/pwd.db is the database equivalent of
/etc/passwd, it doesn't contain any hashes. The
/etc/spwd.db represents the shadow, so it is the database equivalent of
etc/master.passwd and does contain the hashes.
Now that we're familiar with the names of the four password files, let's take a look at the type of information they contain. As the superuser, send
/etc/master.passwd to your screen; it should look something like this:
su: Password more /etc/master.passwd # $FreeBSD: src/etc/master.passwd,v 1.25 1999/09/13 17:09:07 peter Exp $ # root:$1$hnH/w50a$tPdv5HZRsDP46FtsW8eXH/:0:0::0:0:Charlie &:/root:/bin/csh toor:*:0:0::0:0:Bourne-again Superuser:/root: daemon:*:1:1::0:0:Owner of many system processes:/root:/sbin/nologin operator:*:2:5::0:0:System &:/:/sbin/nologin bin:*:3:7::0:0:Binaries Commands and Source,,,:/:/sbin/nologin tty:*:4:65533::0:0:Tty Sandbox:/:/sbin/nologin kmem:*:5:65533::0:0:KMem Sandbox:/:/sbin/nologin games:*:7:13::0:0:Games pseudo-user:/usr/games:/sbin/nologin news:*:8:8::0:0:News Subsystem:/:/sbin/nologin man:*:9:9::0:0:Mister Man Pages:/usr/share/man:/sbin/nologin bind:*:53:53::0:0:Bind Sandbox:/:/sbin/nologin uucp:*:66:66::0:0:UUCP pseudo-user:/var/spool/uucppublic:/usr/libexec/uucp/uucico xten:*:67:67::0:0:X-10 daemon:/usr/local/xten:/sbin/nologin pop:*:68:6::0:0:Post Office Owner:/nonexistent:/sbin/nologin nobody:*:65534:65534::0:0:Unprivileged user:/nonexistent:/sbin/nologin genisis:$1$.3tvchjG$C6wtsUV9FcXF4wzBboisJ/:1001:0::0:0:User &:/home/genisis:/bin/csh dlavigne:pZV8Ju.2sEqsY:1000:1000::0:0:Dru Lavigne:/home/dlavigne:/bin/tcsh test::1002:1002::0:0:test:/home/test:/bin/tcsh
Not the most friendly looking file, is it? It'll be a lot easier to read once we understand its format. Each line in the file contains one user's record, and each record consists of 10 fields separated by colons. The fields are always in the following order:
You'll note that my FreeBSD system has 15 system accounts created by the system; the last three accounts (genisis, dlavigne, and test) were created by the superuser.
Let's pick apart the record for the user "dlavigne" that we created last week using the
adduser utility. Its record looks like this:
The first field (
dlavigne) is the username this user uses to log in to the system.
The second field (
pZV8Ju.2sEqsY) is the encrypted hash; fortunately for dlavigne, this is not the password that she types in at login time. There is no way to tell what her actual password is from just reading this file. However, take note of the second field for the "test" user. Since it is blank, this user is not using a password, and I can tell this by just reading this file. Also note that most of the system accounts have an asterisk (
*) in the second field; this means that a regular user won't be able to try to log in using one of these accounts.
The third field (
1000) is the UID (user ID) of the user; this is how FreeBSD differentiates between users, so it must be unique. When we used the
adduser utility, it offered to start creating UIDs at 1000, so all users I've created have a UID of 1000 or greater. Note that the users "root" and "toor" have a UID of 0; this means they have full superuser access to the system.
The fourth field (
1000) is the primary GID (group ID) of the user. By default, when you create a user in FreeBSD, a group of the same name is also created.
The fifth field (blank) is the class of the user. Classes can be used to determine environment settings, session accounting, and resource limits. We'll discuss using classes in a future article. By default, this field is blank.
The sixth field (
0) represents the time until the password needs to be changed. By default this field is set to zero, meaning the user never has to change his password.
The seventh field (
0) represents the time until the user account expires; if a user account expires, that user will no longer be able to log in. By default, this field is set to zero, meaning that the account will never expire.
The eighth field (
Dru Lavigne) contains the user's "gecos" information. This can include the user's full name, office location, work phone number, and home phone number, each separated by commas. The origin of the term "gecos" is interesting; when Unix was first being developed at Bell Labs, the main computer ran the General Electric Computer Operating System (gecos), and the information regarding the location of the users using this computer was placed in the "gecos" field of the password file.
The ninth field (
/home/dlavigne) is the user's home directory. This is where they will be placed when they log in.
The tenth field (
/bin/tcsh) is the path to the user's shell. Remember from last week that the default shell is the Bourne shell, but we changed it to the tcsh shell when we ran the
adduser utility. If we had kept the default, this field would be empty.
Let's quickly compare the
/etc/master.passwd file to the
/etc/passwd file. I don't need to be the superuser to read this file, so I'll exit out of the superuser account first:
exit more /etc/passwd # $FreeBSD: src/etc/master.passwd,v 1.25 1999/09/13 17:09:07 peter Exp $ # root:*:0:0:Charlie &:/root:/bin/csh toor:*:0:0:Bourne-again Superuser:/root: daemon:*:1:1:Owner of many system processes:/root:/sbin/nologin operator:*:2:5:System &:/:/sbin/nologin bin:*:3:7:Binaries Commands and Source,,,:/:/sbin/nologin tty:*:4:65533:Tty Sandbox:/:/sbin/nologin kmem:*:5:65533:KMem Sandbox:/:/sbin/nologin games:*:7:13:Games pseudo-user:/usr/games:/sbin/nologin news:*:8:8:News Subsystem:/:/sbin/nologin man:*:9:9:Mister Man Pages:/usr/share/man:/sbin/nologin bind:*:53:53:Bind Sandbox:/:/sbin/nologin uucp:*:66:66:UUCP pseudo-user:/var/spool/uucppublic:/usr/libexec/uucp/uucico xten:*:67:67:X-10 daemon:/usr/local/xten:/sbin/nologin pop:*:68:6:Post Office Owner:/nonexistent:/sbin/nologin nobody:*:65534:65534:Unprivileged user:/nonexistent:/sbin/nologin genisis:*:1001:0:User &:/home/genisis:/bin/csh dlavigne:*:1000:1000:Dru Lavigne:/home/dlavigne:/bin/tcsh test:*:1002:1002:test:/home/test:/bin/tcsh
Note that it is similar to the shadow password file except that all of the password fields contain an * instead of the user's hash. Also, the fields that were blank or had a value of 0 have been omitted in this file.
You may have noticed that when we did the long listing for the password files using the
ls -l command, only root had permission to write to the password files. It is important to note that root does not edit these files by opening them directly into a text editor. It is critical that a change made to one password file is sent to the other password files when that change is made; this is the job of the system utility called
pwd_mkdb. If root needs to change a password file, he needs to use a utility which will send its changes to
An example of a utility used for this purpose is
vipw. The command
vipw opens up the entire password file in the editor defined by the environment variable
EDITOR, which is usually
vi, hence the name "vipw." If for some reason your default editor is not vi, you should probably avoid using the
vipw utility or change
EDITOR back to
vi. Other editors use word-wrap, which can wreak havoc with system files such as your password file; this is not a good thing.
To use this utility, you need to be comfortable using the
vi editor and know what each of the ten fields represents and what values are acceptable in each field. For these reasons, only the superuser is allowed to use this utility.
Another utility that can be used to edit the password files is
chpass, which is also called
chsh. These utilities can be used by any user to change some of their own values in the password file. I'll log in as the user "dlavigne" and run the
login: dlavigne Password: chpass #Changing user database information for dlavigne. Shell: /bin/tcsh Full Name: Dru Lavigne Office Location: Office Phone: Home Phone: Other information: ~ /etc/pw.m32496: unmodified: line 1
Notice that a regular user is limited to changing only their own default shell and gecos information fields. I'll add an office phone number and see what happens. Since I'm in the
vi editor, I'll arrow over to the correct spot in the file, press the ESC key followed by an
a to enter append mode, and type in the phone number 123-4567. I'll then press ESC again, followed by
:wq to save my changes and quit the
vi editor. The following will be displayed on my screen:
chpass: updating the database... chpass: done
If I then become the superuser and look for the relevant entry in
/etc/passwd, I should be able to see the change:
su: Password: more /etc/passwd <snip> dlavigne:*:1000:1000:Dru Lavigne,,123-4567:/home/dlavigne:/bin/tcsh
Notice the addition of the two commas in the gecos field to indicate what values you are reading. They will always be in this order:
so I know that 123-4567 is the work phone number of the user Dru Lavigne.
Now, I'll run the
chpass utility as the superuser. If I give a username as an argument to this command, I can edit the entries that pertain to that user. Let's see what the superuser can do to the entries for the user "dlavigne":
chpass dlavigne #Changing user database information for dlavigne. Login: dlavigne Password: pZV8Ju.2sEqsY Uid [#]: 1000 Gid [# or name]: 1000 Change [month day year]: Expire [month day year]: Class: Home directory: /home/dlavigne Shell: /bin/tcsh Full Name: Dru Lavigne Office Location: Office Phone: 123-4567 Home Phone: Other information: ~ /etc/pw.B32584: unmodified: line 1
You should be able to recognize all of the ten fields for this user. The superuser account can modify the record for any user using the
chpass command followed by the username. If the superuser just types:
he will be able to modify the record for the root user account. The
chpass utility does have a few switches the superuser can use to modify a particular field in a user's record; see
man 1 chpass for details.
The utility that is used to safely change a user's password in all of the password database files is the
passwd utility. I'll log in as the "test" user and then create a password for this user:
Note that I wasn't prompted for a password, as "test" currently has a blank password. I better change that using the
passwd Changing local password for test. New password: Retype new password: passwd: updating the database... passwd: done
Normally, when a user changes their password, they are prompted for the old password; this prevents other users from changing a user's password for them. Let's run the
passwd utility again as the test user:
passwd Changing local password for test. Old password: New password: Retype new password: passwd: updating the database... passwd: done
What if a user forgets their password? All is not lost, as the superuser can change a user's password for them; when the superuser changes a user's password, she will not be prompted for the user's old password:
su: Password: passwd test Changing local password for test. New password: Retype new password: passwd: updating the database... passwd: done
Note that the superuser uses the username as an argument to the
passwd utility; if there is no username, the password for the root account will be changed.
The last utility I want to look at that changes the password files is the
rmuser utility. This utility is used to remove user accounts and anything associated with that user; therefore, it can only be run as the superuser. Let's remove that test account:
rmuser Enter login name for user to remove: test Matching password entry: test:$1$P6kMmPWG$rZiu/HfaIPVwJC6hdOImc/:1002:1002::0:0:test:/home/test:/bin/tcsh Is this the entry you wish to remove? y Remove user's home directory (/home/test)? y Killed process(es) belonging to test. Updating password file, updating databases, done. Updating group file: (removing group test -- personal group is empty) done. Removing user's home directory (/home/test): done. Removing user's incoming mail file /var/mail/test: done. Removing files belonging to test from /tmp: done. Removing files belonging to test from /var/tmp: done. Removing files belonging to test from /var/tmp/vi.recover: done.
This is a pretty effective utility; not only did it remove the user from the password files, it also removed the user's home directory, mail file, and any files belonging to the user in the temporary directories. You should also note that before I deleted the test user, their password field was no longer empty; it looked like the
passwd utility had been successful in updating the password database.
In today's article we took a good look at the password files but skirted around the issue of passwords. Next week, I want to look at creating a password policy for your FreeBSD system.
Dru Lavigne is a network and systems administrator, IT instructor, author and international speaker. She has over a decade of experience administering and teaching Netware, Microsoft, Cisco, Checkpoint, SCO, Solaris, Linux, and BSD systems. A prolific author, she pens the popular FreeBSD Basics column for O'Reilly and is author of BSD Hacks and The Best of FreeBSD Basics.
Read more FreeBSD Basics columns.
Discuss this article in the Operating Systems Forum.
Return to the BSD DevCenter.
Copyright © 2009 O'Reilly Media, Inc.