Introduction

Hello, and welcome back to CS631 "Advanced Programming in the UNIX Environment". We've previously discussed the different UIDs associated with an account; in this video segment we try to answer the awkward question inevitably asked by unix users: "Mommy, where do UIDs come from?"

etc/passwd

As we know, the Unix system uses numeric UIDs to make all access decisions. Computers like numbers, but humans tend to like strings better, so we also have user names. The password database maps these user names to user IDs and thus provides the local accounts on the system. Traditionally, this user database is found in the file /etc/passwd, and it contains the following fields, which map into a 'struct passwd' data structure used by the functions performing the lookups. They are: the username, a simple string; a hashed password, although we will later see that this data nowadays resides in a separate file; the numerical UID the numerical group ID; a comment field, known as the GECOS field, stored as a pw_gecos, where the name GECOS derives from the "General Comprehensive Operating System", a remnant of the early Unix days where compatibility with GECOS machines was desirable. We have an initial working directory and an initial shell.

etc/passwd example

The user database, in good old unix tradition, is a plain text file found under /etc/passwd, with line delimited entries containing colon separated fields. This of course means that none of the fields can contain a colon. Your typical /etc/passwd file will contain entries for the super user - root - a number of service accounts used specifically and entirely for the purposes of privilege separation, and the number of human user accounts. The first field is the username, the second field, as we said, is the hashed password, but as we see here, we primarily find an asterisk in this place. This is because nowadays the hashed password is stored in a separate file. We'll get back to this in our next video segment. Then we have the UID and the group ID followed by the GECOS. In the early days of Unix, the GECOS field was commonly used to include not just the full name of the user, but also their office location and work and home phone numbers, separated via commas within this field. Nowadays, it is mostly used to fill in a full name that some services or tools in the unix system may use. For example, when sending mail the user's full name is filled into the from field from here. Next we have the home directory. This is the directory that the login process uses to set as the current working directory of the user when they log in. And finally, we have the shell, the program that the login program executes on behalf of the user when they log in. Okay, now looking at this password database, we should find a few odd things that we'll have to go over to better understand the format. We said that this file is the user database, defining the local accounts on the system. So we should expect there to be always exactly one username being mapped to one UID. But right here at the beginning we see that we have two accounts with the same UID - and one of them is root, no less! This is no mistake: having multiple accounts with the same UID is rarely desired, but it is not an error in the system. What this means practically is that there are two user names that, when authenticated, will have the effective and real UID of zero. Once logged in, the two accounts are completely indistinguishable from one another, since - remember - the system only looks at the UID, not at the username, to make access decisions. We'll see in a second why we might want to have two accounts with the same id. Let's first look at a few more oddities in this file. We mentioned that we have a password field with a placeholder for the hashed password, but this field can also be empty, which means that this account doesn't have a password! Anybody can log in as this user. Well, this is probably not what you want, but again, the system allows for this to happen because who's the system to tell you whom to grant access to. Next, the login shell can be set to any program, since we have a number of service accounts that we only use for privilege separation - that is, for our process to have a dedicated UID and not have any other privileges - but that we do not ever want to allow to log in interactively, we can set the login shell to /sbin/nologin. /sbin/nologin simply returns false when executed, meaning a user managing to log in as this user will immediately be logged out again. But you can set this shell to any program: our time lord over here, for example, will simply execute the date(1) command when she logs in. Privilege escalation here would require the use of a sonic screwdriver, I suppose. But you can also leave the login shell blank, as shown here. In this case, the system will default to /bin/sh. Your initial working directory is normally set to your home directory, but you can leave that blank, too, in which case the initial current working directory becomes root. The GECOS field allows for the expansion of the ampersand to the capitalized username - we'll see that in action in a minute - as well as to provide for the additional information as previously mentioned. But of course you can also leave that field blank, if you like. Multiple identical group IDs simply means that these users are in the same primary group, which is rather normal, but having multiple entries for the same username is most decidedly not normal. We'll demonstrate why this is a bad idea in a minute as well.

Account weirdnesses

Okay let's illustrate all the different weirdnesses we may encounter in /etc/passwd: first, let's illustrate the use of having a second account with the same UID for root, the toor account, the bourne-again super user. Suppose you're working as root and accidentally managed to corrupt your login shell in some way... Now you have a problem: you can't log in anymore! Now what? Well, with a toor account, you can still log in since the toor account has a different login shell, a statically linked shell from the /rescue set of tools. Once you log in as toor, you are root. Wait... how does that work? Don't you remember? The system only cares about your UID, and toor is UID 0, so as far as the system is concerned, you are the super user. So you can now go ahead and fix your broken shell, after which you can log out and logging in as root will work again. Neat, huh? Note, though, that the use of the toor account is a BSD inherited account; most non-BSD systems do not have this account present or enabled. Okay, next, let's take a look at fred. fred doesn't have a password hash, meaning anybody can become fred without having to provide a password. Probably not what you want, but okay. All right, next we'll check out drwho: remember, the doctor has the date(1) command as her login shell, so when we log in as the doctor, that command is executed, and upon termination of the command we are logged out again and are back being our usual boring self. Here we see the date(1) command being executed as that is the login shell of the doctor. Okay, up next: alice. alice has no login shell, but we can still log in as her. Here we are using the login(1) command to illustrate a different method of logging in as a user. That is what the system does when you log in. We'll come back to this program in a future lecture, though. Anyway, as promised, alice gets /bin/sh as her shell, because it's the default if no shell is specified in /etc/passwd. But remember there was something funky going on with alice? Besides not having a shell? We have two accounts for alice, both with the same home directory. And so here are our files... all are owned by alice, but alice is not allowed to create a file in our own home directory! But we said the Unix system only cares about numeric IDs, so let's take a look at those. Okay, so the directory is owned by UID 1002, but we are UID 1004. Which explains why we can't create a file here. We can't tell the two accounts apart because we are looking at the usernames, but the system checks the ID only. So having two accounts with the same username is probably a bad idea. Okay, now finally let's check out the GECOS field in action: the finger(1) command can be used to find information about the user. As we see here, the ampersand in the GECOS field for root was translated into the upper case name, so we end up with "Charlie Root". Why "Charlie Root"? Good question! I wasn't able to find an authoritative answer ,but rumor has it that the account was indeed named after the baseball player Charlie Root. Unix history folklore is weird. Let's look at the information for user jschauma: note how the finger command was able to parse out the GECOS information from the traditional comma separated values and you see my office location and phone numbers displayed here. By the way, the finger command can also be used over the network to query another system if that system offers the fingerd service. That might look like so. Look at that: I apparently still have my old '.plan' and '.project' files on my system, the ones that I used here at Stevens when I was a System Administrator almost ...20 years ago. Wild! This information is no longer accurate, I'm afraid.

Recap

Okay, that's enough for this short video. Let's recap: the user database, a text-based file named /etc/passwd contains colon-separated fields; most of those fields may be empty. An empty password field means no password - this is probably a bad idea. An empty home directory means you'll be dropped into / when you log in. An empty shell means you get /bin/sh. Some of the fields may be duplicated in the file; this is not always an error. Multiple users sharing the same primary group is completely normal, for example. Multiple user names for the same UID is generally quite rare, but we've seen how it can be useful. Multiple UIDs for the same username, however, is virtually guaranteed to be a mistake and lead to unexpected errors. All right - next time, we'll take a look at the various functions we use to handle these user ID lookups as well as how to get information about groups. Thanks for watching - cheers!