ONLamp.com    
 Published on ONLamp.com (http://www.onlamp.com/)
 See this if you're having trouble printing code examples


FreeBSD Basics

An Introduction to Unix Permissions -- Part Two

09/13/2000

In last week's article, we looked at the three base permissions and the three specialty permissions. This week, we'll be using chmod to change permissions. You might want to reread last week's article, as we'll be implementing the concepts it introduced.

But first, never, ever, ever change the default permissions on the files and directories that came with your FreeBSD system. The creators of FreeBSD understand permissions; unless you are a systems administrator or a security engineer with a good reason to change these defaults, please leave well enough alone.

Instead, we'll be creating test directories and test files to practice with. Once you're comfortable with setting permissions, you'll be able to create your own directories and set their permissions according to your needs.

Let's start by taking a look at the chmod command. There are two modes of operation for chmod: absolute mode (which uses numbers) and symbolic mode (which uses letters).

In absolute mode, chmod uses four numbers to represent the following four sets of permissions:

Instead of using the letters r, w, x, s, or t, it uses the numbers 4, 2, and 1 in this order:

421 421 421 421

In the first set of numbers, 4 = SUID, 2 = SGID, and 1 = directory sticky bit. In the next three sets of numbers, 4 = read, 2 = write, and 1 = execute; again the order is owner, group, and everyone else. If a permission is to be denied, a 0 is used, not the - symbol.

So, if I wanted to to set the SUID bit on a file, give its owner full access, and give the primary group and everyone else read and execute access, I would want permissions like this:

400 421 401 401

To set this using chmod, I must first total each set of permissions like so:

400 = 4+0+0 = 4
421 = 4+2+1 = 7
401 = 4+0+1 = 5
401 = 4+0+1 = 5

so I can tell chmod this:

chmod 4755 name_of_file

Let's try this and see if it works. As a regular user, cd into your home directory and create a test file. In this example, I am logged in as the user genisis; if I type cd without any arguments, I will be taken to genisis' home directory.

cd
touch test
ls -la test

-rw-r--r--  1 genisis  wheel  0 Aug 19 11:27 test
chmod 4755 test
ls -la test

-rwsr-xr-x  1 genisis  wheel  0 Aug 19 11:27 test

Note that whoever creates a file becomes the owner of the file; the primary group of the file will be the primary group of the owner of the file. This is important as only the owner of the file (and root) can change the permissions of a file.

Now, how would you use chmod to change the file back to its original permissions? Let's see if we can do the math and get it to work. Our original permissions looked like this:

-rw-r--r--  1 genisis  wheel  0 Aug 19 11:27 test
There isn't an s, S, t, or T in the original permissions, so the first set will be 0 + 0 + 0 = 0.

The owner has rw which is 4 + 2 + 0 = 6.

The group has r which is 4 + 0 + 0 = 4.

Everyone else has r which is 4 + 0 + 0 = 4.

So let's see if the following works:

chmod 644 test
ls -la test
-rw-r--r--  1 genisis  wheel  0 Aug 19 11:27 test

Note that the following command would yield the same result:

chmod 0644 test

However, you can omit the 0 if it represents the specialty permissions.

Now let's try chmod in symbolic mode. The syntax for symbolic mode is a bit longer:

chmod who operator permission filename

where who can be:

and operator can be:

and the permissions can be r, w, x, s, t, and X. Note that there is no capital S; if you want to keep the execute bit when you set the SUID or SGID bits, use both s and x. If you want to set the SUID bit, use s with a who of u; to set the SGID bit, use s with a who of g. To set the sticky bit, use t with a who of o.

Let's try our original example in symbolic mode. We started with:

-rw-r--r--  1 genisis  wheel  0 Aug 19 11:27 test

and want to end up with:

-rwsr-xr-x  1 genisis  wheel  0 Aug 19 11:27 test

so let's try this:

chmod a+sx test
ls -la test

-rwsr-sr-x  1 genisis  wheel  0 Aug 19 13:05 test

Close, but no cigar. Since we specified a who of a (or everyone), we set both the SUID and SGID bits. Let's try again:

rm test
touch test
chmod u+s go+x test

chmod: go+x: No such file or directory

We got a syntax error on that command because chmod expects the who, operator, and permissions to be a string of characters without any spaces. Whatever follows the space is interpreted as the name of the file whose permissions are being set. Let's try again:

chmod u+s,go+x test
ls -la test

-rwSr-xr-x  1 genisis  wheel  0 Aug 19 13:16 test

Almost there; we seem to have set the SUID bit and given everyone except the owner execute permission. One more try:

rm test
touch test
chmod u+sx,go+x test
ls -la test

-rwsr-xr-x  1 genisis  wheel  0 Aug 19 13:22 test

Success. You can see that it is a good idea to always doublecheck your permissions using ls -la after using the chmod command to make sure you actually set the permissions you intended.

Remember from last week that what a user can do with a file depends on both the file's permissions and the directory's permissions. Let's make a test directory in our home directory to store some test files:

cd
mkdir testdir
cd testdir
touch testfile
ls -la

total 2
drwxr-xr-x   2 genisis  wheel   512 Aug 20 10:24 .
drwxr-xr-x  14 genisis  wheel  1024 Aug 20 10:23 ..
-rw-r--r--   1 genisis  wheel     0 Aug 20 10:24 testfile

Note the interesting behaviour with the times. The parent directory was last modified when testdir was created, as its name had to be added to the parent directory's list. (Remember from last week that a directory is simply a file containing a list of the directory's contents). Similarly, the testdir directory was modified the same time that the testfile was created, as it also had to be added to its directory list.

Now, I want you to logout and login as a different user (other than root). Looking at the permissions for the testdir directory, will that user be able to cd into that directory, use the ls command, read a file, change a file, create a file, or remove a file? As you try this exercise, remind yourself which permission is allowing or preventing that user from doing something in the testdir directory. I'll login as the user biko:

exit
login: biko
Password:
cd ~genisis/testdir

Note the shortcut to return to genisis' home directory. Looks like the execute permission for everyone on testdir allowed biko to cd into it.

ls -la

total 2
drwxr-xr-x   2 genisis  wheel   512 Aug 20 10:24 .
drwxr-xr-x  14 genisis  wheel  1024 Aug 20 10:23 ..
-rw-r--r--   1 genisis  wheel     0 Aug 20 10:24 testfile

Looks like the read permission for everyone on the testdir directory allowed biko to list its contents.

more testfile

Looks like the read for everyone on the testfile allowed its contents to be read. Even though the file was empty, biko did not receive an error message.

touch myfile
touch: myfile: Permission denied

Looks like biko doesn't have write permission to this directory, so he won't be creating any files in it.

rm testfile
override rw-r--r--  genisis/wheel for testfile? y
rm: testfile: Permission denied

Again, lack of write permission will prevent biko from removing files from this directory.

mv testfile ~
mv: rename testfile to /home/biko/testfile: Permission denied

This is a move operation; biko would need write permission on the testdir directory for this to work.

cp testfile ~

This copy operation was successful as biko does have write permission on his home directory.

ls -la >> testfile
testfile: Permission denied.

Here I was trying to append the results of ls -la to the end of the testfile. If biko had write permission, he would be able to do this.

Now, how would we give biko permission to create files in this directory but not delete any files which were created by genisis? See if you can come up with a solution in both absolute and symbolic mode before testing your theory. Note, you have a choice of giving permission to the primary group, to everyone else, or to both. You'll have to log in as the original user who made the testdir directory in order to change its permissions. And don't forget to change your directory's sticky bit.

Now is a good time to mention groups, as group membership is an important consideration when setting permissions. To see what groups you belong to, simply type:

groups

To see what groups anyone else belongs to, add their login name to the end of the groups command like so:

groups genisis
wheel
groups biko
biko

Here I have two users who don't live in the same group. If I wanted them to share a directory, I could set permissions on everyone, but this would also give permissions to everyone else. Alternately, I could make them members of the same group and set permissions for the group. With this method, I may also have to change the primary group of the file using the chown command. Let's create a group called projects and add these two users to it. Become root, as only root can make new users or groups. We'll use the pw command to create the group; first, we'll type pw to get the syntax:

pw
usage:pw [user|group|lock|unlock] [add|del|mod|show|next] [help|switches/values]

Then we'll add a group with the fairly straightforward syntax:

pw group add projects

Then we'll verify that it worked like so:

grep projects /etc/group
projects:*:1006:

Our new group is showing up in the /etc/group database with a group ID of 1006. Now, I'll want to add the users genisis and biko to the group like so:

pw groupmod projects -M genisis,biko
grep projects /etc/group

projects:*:1006:genisis,biko

Everything looks good; one last test to verify:

groups genisis
wheel projects

groups biko
biko projects

Note that you can belong to more than one group at a time in FreeBSD. Now all we have to do is change the primary group of the testdir directory so we can give permissions to just genisis and biko. The user genisis can do this, as she owns the directory, so we'll exit out of the root account and log back in as genisis. Then:

cd
chown :projects testdir

Note that the chown command requires a full colon (:) to indicate you want to change the primary group, not the owner of the file or directory.

Now, let's see if the change was successful:

ls -la testdir

total 2
drwxr-xr-x   2 genisis  projects   512 Aug 20 10:24 .
drwxr-xr-x  14 genisis  wheel    1024 Aug 20 11:45 ..
-rw-r--r--   1 genisis  wheel       0 Aug 20 10:24 testfile

We can now set permissions for the projects group, and it will only affect the users genisis and biko.

I'd like to end this article with some common permissions to set on directories that you create.

If you create a directory that will contain private data that you only want yourself to access, set its permissions to 700. Users will be able to see the directory, but they won't be able to cd into it, list its contents, or modify any of the files in it. Keep in mind that root is not subject to permissions, so nothing is really hidden from the root account.

If you wish to have a directory inaccessible to a group of users, set its permissions to 707 or 705. This works, as FreeBSD stops reading permissions when it finds a match. This means that FreeBSD first checks to see if you are the owner of the file; if you are, you are subject to the owner's permissions. If you are not the owner, it then checks to see if you belong to the primary group of the file; if you do, you are subject to that group's permissions. If you don't, you are subject to the permissions of everyone else.

If you want a group to be able to write files, but only delete their own files, set the directory's permissions to 1775.

Practice reading directory listings to determine what you can and can't do with a file. When you see a listing, think which chmod command would have set that permission. Before you know it, you'll be able to look at a listing and know how to change its permissions so your users can do what you want them to do.

Next week, we'll do some customizing of the user environment by learning how to change our shell prompt.

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.