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/pwd.db and /etc/spwd.db. Let's take a look at their file types:

file /etc/*pwd.db
/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 cat, 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 s in /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:

name:hash:uid:gid:class:change:expire:gecos:home_dir:shell

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:

dlavigne:pZV8Ju.2sEqsY:1000:1000::0:0:Dru Lavigne:/home/dlavigne:/bin/tcsh

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 pwd_mkdb.

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 chfn or 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 chpass utility:

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:

full_name,office_location,work_phone,home_phone

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:

chpass

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:

login: test

Note that I wasn't prompted for a password, as "test" currently has a blank password. I better change that using the passwd utility:

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.


The source for this article is ONLAMP.com