Most mature operating systems -- IBM's MVS, DEC's VMS,
and HP's 
MPE, for example -- provide a number of privileges,
many of which 
are limited in scope, that can be assigned one at a
time to users 
on the system. On UNIX, however, you either have super-user
privileges 
or not -- all or nothing. Generally, the super-user
privileges 
are given to one user, root. This means root has to
be available for 
any of a number of tasks, including lp administration,
mounting/unmounting 
disks, changing network configuration, adding users,
shutting down 
a system, and running backups.
Working around this inconvenience can cause a number
of security issues 
for a system. If you give root's password to everyone,
you violate 
basic password security and lose the ability to find
out who performed 
a command as root. Being able to log on as root from
anywhere is always 
a bad idea and allowing several people to do this is
worse, since 
it greatly increases the likelihood that a root terminal
session will 
be left unattended. Anyone with physical access to a
terminal left 
in such a state has root access. It only takes minutes
to extend privileges 
or subvert the system.
Under certain circumstances, however, it's useful to
be able to delegate 
some privileges. It may be that a networking staff,
rather than the 
system administrator, is responsible for the networking.
Operators 
may need to back up files. Perhaps a manager has a team
of support 
personnel and does not want the root password to be
that widely known.
This last was the case for a recent customer of mine.
The organization 
had about 500 workstations that were supported by a
staff of 20. All 
these systems had the same root password, which was
changed weekly. 
The major concern was keeping track of what had been
done on each 
of the systems by any of the support personnel. To this
end, the root 
log-on was only used when mandatory and was restricted
to the system 
consoles. In place of the root log-on, they used a program
called 
sudo (super-user do), which allows them to execute commands
with super-user privileges and logs this activity.
sudo is a set-user-id program that runs as root and
allows 
authorized users to execute commands for which they
are approved. 
sudo was originally written by Cliff Spencer of SUNY-Buffalo
and was 
published in Evi Nemeth's UNIX System Administration
Handbook. 
It was originally written to run under BSD UNIX.
The original sudo left a number of things undone. These
included 
being able to shell out of programs like vi, using root's
path, 
having to fully qualify the commands to be executed,
having to specify 
all the commands that can be executed and not being
able to specify 
commands that cannot be executed, and being able to
specify "all" 
commands, thereby allowing a user free range. A user
could also sudo 
a shell and thereby circumvent the logging mechanism.
The original sudo used root's complete environment,
including 
root's shell and path. I added the putenv commands to
set the 
shell to /bin/false and assigned a path for commands
that can 
be run by sudo. Reassigning the shell variable keeps
programs 
like vi from being able to spawn a subshell. Assigning
a path 
limits the scope of the commands that can be executed
with sudo. 
It also eliminates the need to fully qualify path names
for commands. 
I added a "not" option to the configuration
file to allow 
you to configure someone to run all commands except
those listed. 
Granting some super-user privileges to ordinary users
and depending 
on their log-in passwords for security is likely to
cause security 
problems. If a user who has sudo privileges has a poor
password, 
or shares the password, or has it stolen, then the super-user
privileges 
granted to that user have also been compromised. There
are a number 
of things that you can do to limit this risk:
Monitor the log files to see what the users are doing.
Some commands should not be given out to sudo users.
For example, 
certain commands circumvent the logging procedure. These
are commands 
that spawn an interactive shell or replace the sudo
process with another 
process. These include sh, ksh, csh, rsh 
(restricted shell), and exec. Other commands increase
the 
risk to other systems, particularly in a Trusted Computer
Base. These 
are rlogin and remsh (remote shell, rsh on some 
systems). These programs allow you to log-on to another
computer without 
requiring a password. Still other commands, such as
chmod and 
chown, can be used to coerce additional permissions
and can 
be used to make set-uid shells that can be executed
outside of sudo.
Security Measures
A number of steps should be taken to ensure that you
are using sudo 
securely. This section describes those steps.
The locations of the configuration file, log file, and
time directory 
should be known only to the security manager. Any user
who knows where 
these files are located can manipulate them to add users
or commands 
to the configuration file, or to add commands in the
secure path to 
be executed via sudo, or to alter the logfile. One way
to obscure 
the location of these files is to put them in a hidden
directory, 
that is, a directory whose name starts with a period,
with no read 
or write permission for anyone and root ownership. A
directory name 
that cannot be typed would actually be better. Only
commands that 
are to be executed would be placed in this directory,
and permissions 
for these commands would be execute only, no read or
write permissions.
The source code should not be left online and the binary
file should 
be marked as execute only, with no read or write permissions
for anyone. 
Failure to observe these guidelines would allow someone
to locate 
the path to the configuration and log files and time
directories.
How sudo Works
sudo first validates its configuration. It checks that
it is 
owned by root and has the set-UID bit set. It checks
the configuration 
file to validate that it is not writeable or readable
by anyone other 
than root (the configuration file contains the list
of authorized 
users and the commands that they can execute). sudo
next validates 
the user, by scanning through the configuration file
to find the user's 
log-on name, and the command that was entered, by scanning
the list 
of commands that are valid for that user. It then prompts
the user 
for a password and matches the input password against
the user's log-on 
password. Only when all of these tests have been passed
will it execute 
the command. This command, however, must be in a path
that is defined 
in the sudo source as a secure path. If there is a configuration
problem or if a user is not authorized or tries to execute
a command 
for which he has no permission, sudo sends mail to the
security 
manager describing the problem. sudo also logs all executions,
whether they are successful or not.
Configurable Parameters
There are a number of locally configurable parameters
at the beginning 
of the sudo source code. The following are the default
values:
#define SECURE_PATH "/bin:/usr/bin:/etc"
#define USERFILE    "/usr/local/adm/sudoers"
#define LOGFILE     "/usr/local/adm/sudolog"
#define TIME         5 /* minutes */
#define TIMEDIR     "/usr/local/adm/sudocheck/"
#define SUDO_COP    "root@localhost"
SECURE_PATH is a path statement that defines the 
directories that contain the programs that can be executed
by sudo. 
Appropriate permissions need to be maintained for the
directories 
in this path and the programs in these directories.
Periodic checksumming 
of these directories would be a good idea.
USERFILE is the configuration file that contains the
users 
and the commands that can be executed. The format of
this file is 
user log-on name, followed by a white-space-separated
list of commands. 
You can use "not" to indicate all but the
listed commands. 
You can use "all" to indicate all commands
in the secure path.
LOGFILE is the location of the log file that sudo creates
to log information about commands that were executed
or attempted. 
This file must not be readable or writeable by anyone
but root.
TIME and TIMEDIR allow a user to enter a number of sudo
commands without re-entering his or her password if
the TIME 
has not expired. This is managed by making timestamp
files in the 
TIMEDIR directory. Setting TIME to 0 disables 
this option. This directory also needs appropriate permissions.
SUDO_COP is the mail address of the security manager,
where 
information about violations is to be sent. The mail
address must 
be in a format understood by the mail system running
on the node where 
sudo is installed.
Configuration File
The configuration file consists of the user's log-on
name followed 
by the commands that the user can execute, or the word
"not" 
followed by the commands that this user cannot execute,
or the word 
"all," indicating that this user can execute
all commands. 
The following lines represent three users: the user
"operator," 
who can execute the du and dump commands; the user "nice_guy,"
who can execute all sudo commands, and the user "buster,"
who cannot execute the command sh.
operator	du dump
nice_guy	all
buster	not sh
Only commands that are in the secure path can be executed
with sudo.
Log File
The log file contains the date and time that sudo was
executed, 
whether it was successful or not, who executed sudo,
and the 
command line used with the sudo command. Here is an
excerpt 
of a sudo log file:
Mon Aug 15  9:25:42 : SUCCESS buster    vi /etc/hosts
Mon Aug 15 11:30:05 : FAIL    operator  lpshut
Tue Aug 16 22:02:46 : SUCCESS buster    mv rouge/bin
Thu Aug 18  8:05:21 : FAIL    hacker    vi /etc/passwd
Fri Aug 19 16:54:02 : SUCCESS nice_guy  shutdown -h
Using sudo
Using sudo is generally very straightforward. You invoke
the 
sudo command, followed by the command and parameters
that you 
wish to execute with super-user privileges. For example,
to edit the 
password file you would type:
sudo vi /etc/passwd
Some situations are not so obvious. If you are pipelining
commands, you have to invoke sudo for each command in
the pipe 
that requires super-user privileges. For example, if
you wish to find 
all the files on the system and create a cpio archive
on a 
tape drive that has write permissions only for root,
you would use 
the following command:
sudo find / -print | sudo cpio -o >/dev/rmt
You can combine remote execution with sudo to 
execute commands on remote systems that support sudo.
For example, 
if you wish to print all the failed log-in attempts
of a remote system 
on a local printer, you would use:
remsh remotehost sudo who </etc/btmp | lp
The lp command does not have to be invoked with 
sudo since the output from the who command is available 
across the pipe without privileges.
Enhancements
It would be convenient to have the ability to enable
a group of users 
for a list of commands. You could accomplish this by
adding a group 
command to the command file, followed by a list of the
users who are 
members of the group.
I have also had requests to add a node name to the log
file for systems 
that share file systems. With the current configurations,
it is impossible 
to tell on which node the sudo command was executed.
The only 
change required would be a simple change to the logging
routine, but 
I contend that if the nodes share a file system, then
a security problem 
on one is a security problem on all.
Conclusion
Some vendors are starting to address the issue of granularity
of control 
in UNIX, but currently their efforts are very limited
and vendor specific. 
Until standards for subdividing and assigning privileges
are more 
widespread, sudo, which is easily portable, can be a
useful 
tool if appropriate security precautions are taken.
It allows system 
administrators to delegate tasks while maintaining system
security 
across UNIX systems from many vendors. 
About the Author
Don Pipkin has been a Hewlett-Packard technical consultant
for nine years, focused on UNIX. He specializes in system
security 
and networking Client/Server technologies. He has a
BS in Computer 
Science from the College of Engineering at the University
of Tulsa. 
Don can be reached at Hewlett-Packard, 6655 S. Lewis
#105, Tulsa, 
OK 74136, or at pipkin@hptulsa.ssr.hp.com.