The root password can be a cause of contention in any organization . Many system administrators hate giving it out, even to people who are responsible for maintaining part of the system. If this sort of system administrator doesn't know how to properly manage things, this reluctance can keep people from being able to do their jobs. Many other system administrators hand out root to dang near anyone who wants to use it, and then complain when the system becomes unstable.
by Michael W. Lucas
Using GroupsUnix has powerful facilities for removing the need to use the root password. In the next few articles, we're going to consider minimizing use of the root password.
One common situation is where a junior administrator is responsible for a particular portion of the system. i.e DNS administrators;
these people don't ever install software, recompile the kernel, or do other low-level system tasks. They just answer email, update the zone files on the nameservers, and reload
New junior administrators frequently seem to think that they need root to do this sort of work. With proper use of groups, and a bit of scheduling, you don't need to hand out root at all! Here, we're going to implement group-based security for managing DNS files. The same techniques can be applied to almost any other section of the system.
Unix classifies users into groups, each group consisting of people who perform similar administrative functions. You can have a group called
Web, which includes the people who edit Web pages, and a group called
dnsthat includes the people who manage your nameserver. Depending on your operating system, you might already have groups with similar names.
For example, NetBSD and OpenBSD both include a user and a groupThese predefined users and groups are generally used by programs on the system. Web servers generally run as the
named, while FreeBSD has a user and group called
bind, all for use by the nameserver.
wwwuser, for example.
For our purposes, we'll want to define a separate group for users who need access to files used by these programs. We don't need a matching user account, however. Group information is in
/etc/group. Each line in
/etc/groupcontains four colon-delimited fields.
- The first is the group name. Group names are fairly arbitrary: you could give your DNS managers the group name "losers" if you wished. It's a good idea, however, to choose group names that give you some idea of what they're for; while you might remember that the group xyzzy manages your email system today, will you remember it six months from now? Choose group names that mean something.
- The second field contains the group's encrypted password. Group passwords encouraged poor security practices, so most modern Unixes don't support them. As with many other things in Unix, however, this field has always been there and so we're stuck with it. Rather than leave this field blank, we use an asterisk (*) as a placeholder.
- The third field holds the group's unique numeric ID (GID). Many of FreeBSD's internal programs use this GID, rather than names, to identify groups.
/etc/groupsis sorted in order by GID.
- Last is a list of all the users in that group. To add a user to a group, simply add the username to this list, separated from other names with commas.
dnsgroup we're creating, which are closely related to another group in the system, I'll frequently pick a GID that's off by one from its related group.
For example, on FreeBSD the bind user has a GID of 53 (from the network port number nameservers use). Our new
dnsgroup will have a GID of 54. I want to add the local users "chris", "phil", and "michael" to this group, so our new entry will look like this.
/etc/group, it's a good idea to make sure you haven't made a mistake. FreeBSD includes
chkgrp(8), which checks the syntax of the groups file; if it runs silently, you haven't shot yourself in the foot.
Now that you have a group, you can use it to assign ownership of files. Every file is owned by both a user and a group. You can see the existing ownership of a file with
ls -l. Many new system administrators pay close attention to the owner, and to the word permissions, but gloss over the group permissions.
# ls -l total 29 -rw------- 1 root wheel 27136 Sep 14 09:36 file1 -rwxrwxr-- 1 root wheel 1188 Sep 14 09:35 file2
file1can only be read or written to by root.
file2can be read by root or any member of the group wheel. If you're in the wheel group, you don't need to become root to edit or read
file2file; you can just open your text editor and go!
To change a group owner on a file, use
# chgrp groupname filename
Now, in BSD
wheelis a system group.
Wheelis the group of users who may use the root password. You don't want to go generically making files writable by
wheel; this would strongly violate the principle of least privilege.
bindis a group used by the nameserver program. You don't want the nameserver program to be able to write DNS zone files; if someone compromises the nameserver, then the nameserver would be able to write files directly to the disk. This would be bad. But consider the following permissions scheme on the zone file for blackhelicopters.org:
This file is owned by me, as the senior administrator, but it's writeable by anyone in the
-rw-rw-r-- 1 mwlucas dns 486 Jun 7 10:14 blackhelicopters.org.db
dnsgroup. (You could also set up a particular user to own these files.) Anyone in the
dnsgroup can read and write to this file, without using the root password. Finally, this file can be read by the nameserver.
The only thing the DNS administrators need the root password for now is to restart the nameserver. This is easily dealt with by setting up a cron job to reload the nameserver. These administrators still might want to reload the nameserver manually on occasion, however. We'll look at allowing them to do so without using the root password in the next article....
While proper implementation of groups can help reduce the need for the root password, at times, users must absolutely run commands as another user (usually root). As the system administrator, you're stuck between deciding to hand out the root password or doing everything for your users.
sudoprovides a third way, one that can help solve this dilemma. It's a tricky program, however, and needs some care in implementation.
sudois integrated into OpenBSD, and is an add-on package for just about every other Unix-like operating system out there.
sudois a setuid root wrapper that implements fine-grained access control for commands that need to be run as root. It takes the command you want to run and compares it to its internal list of permissions. If
sudo's permissions allow that particular user to run that command,
sudoruns that command for you, with its privileges. As root can run commands as any user,
sudocan execute commands as any arbitrary system user.
With proper setup, the system administrator can allow any user to run any command as any other user.
We're going to do a basic
sudois a very powerful tool, and can be configured to allow or deny almost any set of commands. As a result of this flexibility, the documentation tends to scare off new users.
sudosetup that will cover almost all uses, but you should be aware that many more combinations are possible, and are documented in
Other than the obvious fine-grained access control
sudoprovides, there are a few other benefits to using
- One of the biggest advantages is the command logging. Every
sudocommand is logged, making it very easy to track who made what changes.
- And once you have
sudoconfigured correctly, you can change the root password and not give it to anyone. Nobody should need the root password if they have the correct
sudopermissions, after all! Reducing the number of people who have the root password can help improve security.
- Finally, a single
sudoconfiguration file can be used on all of these systems, vastly easing administrator overhead.
sudois that users and junior administrators don't like it. If people have traditionally had root access on a system, they will perceive that they're losing something when you implement
The key to overcoming this is to make sure that people have the ability to do their jobs. If users think that they need the root password to perform other tasks, then your need to settle just who is responsible for what. These users may have been taking extra duties upon themselves, rather than troubling you with jobs that you should do.
sudosetup can create security holes. A thoughtless configuration will create holes in the system that a clever user can use to actually become root. This problem is best dealt with by a combination of careful configuration and administrative policy.
sudohas three pieces.
- The first is the actual
sudo(8)command, the setuid root wrapper that users will actually use.
- There's also
sudo's configuration file,
/etc/sudoers. This file is
sudo's permissions table, saying who may run what commands as which user, and is fully documented in
- Finally, the
visudo(8)command allows administrators to edit the
sudoersfile without risking locking themselves out of the system.
sudoers file, and
If the syntax in yourMuch like
sudoersfile is incorrect,
sudowill not run. If you're relying on
sudoto provide access to the
sudoersfile, and you corrupt the
sudoersfile, you can lock yourself out of root-level activities on the system and be unable to correct your error. This is bad.
visudo(8)provides some protection against this sort of error.
visudo(8)locks the file so only one person can edit the configuration file at a time. It then opens the
sudoconfiguration file in an editor (
vi(1)by default, but it respects the
When you exit the editor,
visudoparses the file and confirms that there are no
sudosyntax errors (This is not a guarantee that the configuration will do what you want, merely a confirmation that the file is actually a valid).
visudo(8)will accept a configuration file that says "nobody may do anything via
sudo" if the rules are properly formatted.
visudofinds an error when you exit the editor, it will print out the line number and ask you what you want to do:
# visudo >>> sudoers file: syntax error, line 44 <<< What now?
Here, we've made an error on line 44. You have three choices:
- edit the file again,
- quit without saving any of the changes you made, or
visudoto write the
sudoersfile you created.
visudowill send you back to the editor. You can go to the line it complained about, and try to find your error.
If you enter x,
visudowill quit and revert the configuration file to what it was before you started editing. Your changes will be lost, but that may be all right. It's better to have the old, working configuration, than have a new, non-functional configuration.
Entering Q forces
visudoto accept the file, syntax error and all. If your configuration file has an error,
sudowill not run. Essentially, you're telling
sudountil such time as you log in as root to fix the problem. This is almost certainly not what you want to do!
sudowho may run which commands as which users. OpenBSD stores the
/etc/sudoers, FreeBSD stores it as
Never edit this file directly, even if you think you know exactly what change you want to make; always use
sudopermissions syntax can be confusing until you understand it. Getting everything correct can be difficult the first time. Once you understand how
sudosets things up, however, it's very quick and easy.
The various sample
sudoersfiles you'll find on the Internet frequently look quite complicated and difficult to understand, as they demonstrate all the nifty things you can do with
sudo. The basic syntax is very simple. Each rule entry in
sudoershas the following format:
username host = command
usernameis the username of the user who may execute the command.
hostis the hostname of the system where this rule applies.
commandfield lists the commands this rule applies to. You must have a full path to each command name, or
sudowill not recognize it! (You wouldn't want people to be able to adjust their
$PATHvariable to access renamed versions of commands, now would you?)
sudois designed so you can use one
sudoersfile on all of your systems. This space allows you to set per-host rules.
sudodefaults to not allowing anything to happen. To let a user run a command, you must create a rule that gives that user permission on that host to run that command. If any of the three fields don't match, the user cannot run the command.
You can use the
ALLkeyword in any of these fields to match all possible options. For example, suppose I trust user "chris" to run absolutely any command as root, on any system:
Giving a junior system administrator total control of one of my systems isn't very likely. As senior system administrator, I should know what commands Chris needs to run to do his job. Suppose Chris is in charge of the nameserver portion of this system. We control actual editing of the zone files with group permissions, but that won't help when the nameserver must be started, reloaded, or stopped. Here, I'll give him permission to run just the name daemon controller program,
chris ALL = ALL
If I'm sharing this file across several machines, it's quite probable that many of those machines are not even running a nameserver program. Here, I'll restrict which machine Chris may run this program on to the server called "
chris ALL = /usr/sbin/ndc
On the other hand, Chris is the administrator of the email server "
chris dns1 = /usr/sbin/ndc
sudoersfile on both the systems.
You can specify multiple entries in a single field by separating them with commas. Here, I'd like Chris to be able to mount floppy disks with
chris dns1 = /usr/sbin/ndc
chris mail = ALL
mount(8), as well as control the nameserver.
You can tell
chris dns1 = /usr/sbin/ndc, /bin/mount
sudoersthat a user can run commands as a particular user, instead of root, by putting the username in parenthesis before a command. For example, suppose we have our nameserver set to run as the user "
named" and all commands to control the server must be run as that user:
Every entry in
chris dns1 = (named) /usr/sbin/ndc
/etc/sudoersmust be on a single line. This can make the lines very long. If you have a long list of alias members or rules, you can skip to another line by using the
\character at the end of each incomplete line.
Now that you understand how
chris server1 = /sbin/fdisk,/sbin/fsck,/sbin/kldload,\
sudopermissions are set, let's look at how to actually use
visudo, and give your account privileges to run any command. (If you've installed
sudocorrectly you already have root, so this won't be a security issue.)
The first time you run
sudowill prompt you for a password.
Enter the password for your own account, not the root password.If you give an incorrect password,
sudowill insult your typing abilities, mental facilities, or ancestry, and let you try again. After three incorrect passwords,
sudogives up on you. You'll have to re-enter the command you want to run.
Once you enter a correct password,This makes work easier when you're issuing a series of commands under
sudorecords the time. If you run
sudoagain within five minutes, it won't ask you for a password. After you don't use
sudofor five minutes, however, you must re-authenticate.
sudo, but times things out quickly in case you walk away from the computer.
When you're a regular user on a system with
sudo, one thing you'll probably want to know is what commands the system administrator has permitted you to run.
-lflag will tell you this.
If you had tighter restrictions, they would be displayed.
# sudo -l Password: User mwlucas may run the following commands on this host: (root) ALL
To run commands via
sudo, just put the word "
sudo" before the command you actually want to run. For example, here's how we would become root using
# sudo su Password: #
sudoto become root simply allows the senior system administrator keep the root password a closely-held secret.
This isn't entirely useful, as with unrestrictedStill, it's a start towards keeping the system more secure, and towards implementing
sudoaccess junior administrators can change the root password.
sudofor all commands.
You can run more complicated commands under
sudo, with all of their regular arguments. For example,
tail -fis excellent to view the end of a log file, and to have new log entries appear on the end of the screen. Some log files are only visible to root, or should be -- for example, the log that contains
sudouse information. You might want to view these logs without bothering to become root.
# sudo tail -f /var/log/authlog openbsd/usr/src/usr.bin/sudo;sudo tail -f /var/log/secure Jul 29 13:24:19 openbsd sudo: mwlucas : TTY=ttyp0 ; PWD=/home/mwlucas ; USER=root ; COMMAND=list Jul 29 13:30:03 openbsd sudo: mwlucas : TTY=ttyp0 ; PWD=/home/mwlucas ; USER=root ; COMMAND=/usr/bin/tail -f /var/log/authlog ...
You can choose to run commands as a user other than root, if you have the appropriate permissions. For example, suppose we have our database application where commands must be run as the database user. You tell
sudoto run as a particular user by using the
-uflag and a username. For example, the operator user has the privileges necessary to run
dumpand back up the system.
# sudo -u operator dump /dev/sd0s1
All this tracking and accountability is nice, but where does it account to?
sudomessages are logged. Each log message contains a timestamp, the name of the user, the directory where
sudowas run, and the command that was run.
Jul 29 11:21:02 openbsd sudo: chris : TTY=ttyp0 ; PWD=/home/chris ; USER=root ; COMMAND=/sbin/mount /dev/fd0 /mnt
In the worst case, you can backtrack exactly what happened when something breaks. For example, if one of my systems doesn't reboot correctly because
/etc/rc.confis missing or corrupt, I can check the
sudologs to who touched it.
Jul 29 11:34:56 openbsd sudo: chris : TTY=ttyp0 ; PWD=/home/chris ; USER=root ; COMMAND=/bin/rm /etc/rc.conf
If everyone had been using
su, or even using "
sudo su" instead of
sudoto run each individual command, I would have had no clue as to why the system broke. With
sudologs, once I get this computer up and running again I know who to blame. This alone makes