Earlier on the list we mentioned using sudo(8) in preference to su(1), since sudo(8) doesn't compromise the superuser password. I've dashed off a small tutorial (attached) for your consideration. Cheers!
<?xml version="1.0"?> <!-- $Id: --> <!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" [ <!ENTITY % FEDORA-ENTITIES-EN SYSTEM "../common/fedora-entities-en.xml"> %FEDORA-ENTITIES-EN; <!ENTITY BOOKID "sudo-tutorial-0.1 (2005-04-03)"> <!-- change version of manual and date here --> <!ENTITY LEGALNOTICE SYSTEM "../common/legalnotice-en.xml"> <!ENTITY PROGRAM "sudo(8)"> ]> <article id="sudo-tutorial" lang="en"> <articleinfo> <title>A &PROGRAM; Tutorial</title> <subtitle>Not a pseudo-tutorial!</subtitle> <copyright> <year>2005</year> <holder>Tommy Reynolds <Tommy.Reynolds@xxxxxxxxxxxxx></holder> </copyright> <authorgroup> <author> <surname>Reynolds</surname> <firstname>Tommy</firstname> <email>Tommy.Reynolds@xxxxxxxxxxxxx</email> </author> </authorgroup> &LEGALNOTICE; </articleinfo> <section id="intro"> <title>Introduction</title> <para> The security of a Linux system depends largely on the enforcement of <firstterm>file access permissions</firstterm>. Access to a file is granted or withheld by comparing the identity of the user making the request against permissions associated with the file itself. Most of the configuration files, and many system administration activities, must be accessed by the privileged system user, commonly known as the <firstterm>superuser</firstterm> or the <firstterm>root</firstterm> account, and are not available to ordinary users. </para> <para> In this tutorial, we examine a technique for safely granting trusted users access to these programs and files that would normally be denied. The system administrator can keep the root password concealed, yet still allow selected users to obtain privileged access. Everybody wins with this approach. </para> <para> Although <application>sudo(8)</application><footnote> <para> When writing about programs or system configuration files, it is customary to indicate which section of the on-line manual pages contain its documentation. For example, section one (1) documents applications; section two (2) documents system calls, section three (3) a library function and so on. Sometimes the same name may be both a system call and a library function, knowing the manual page section is important. Compare the results of "<userinput>man 2 exit</userinput>" with "<userinput>man 3 exit</userinput>". </para> </footnote> offers robust control for a networked environment, we shall consider only local use in this tutorial. For more information, consult <ulink url="http://www.sudo.ws/sudo"><filename>http://www.sudo.ws/sudo</filename> </ulink>, the official web site. </para> </section> <section id="credentials"> <title>How Linux Controls Access</title> <para> To better understand the benefit that <application>sudo(8)</application> brings, let us review how Linux provides access security to the system resources. If you like, skip this section but come back if you need. </para> <para> Linux is a multiuser system. There is more to this than simply having a <application>login(1)</application> program: every time a system resource is accessed, care must be taken to ensure that the user attempting the access is permitted to do so. </para> <para> For this reason, Linux assigns each login user a set of <firstterm>credentials</firstterm>. Each user has a unique <firstterm>user-id</firstterm>, or <abbrev>UID</abbrev>, and also has a <firstterm>group-id</firstterm>, or <abbrev>GID</abbrev> which need not be unique. This <abbrev>uid</abbrev>:<abbrev>gid</abbrev> pair form an important component of that user's credentials. </para> <section id="credentials-obtaining"> <title>Who Are You?</title> <para> Before you get access to a Linux system, you must prove your identity. While the system administrator decides the security policy for the machine, usually one or more password challenges must be answered. After all, if you really are user <userinput>joesixpack</userinput>, then you should know the answer to a question that only <userinput>joesixpack</userinput> would know: what is the password? </para> <para> This process of proving your identity to the system is known as <firstterm>authentication</firstterm>. Many schemes are available to the system administrator, but once the system authenticates your login request, the kernel has enough information to determine what programs you can run or what files you can access<footnote> <para> Actually, there is more to the authentication process than just a password challenge. The sysadmin can impose restrictions such as limiting the time of day when a given user may login, or requiring that a user make the login attempt from a specific location. </para> </footnote>. </para> <para> After a successfully authentication the system uses your uid and gid to control your access to system resources. </para> </section> <section id="credentials-perms"> <title>File Access Permissions</title> <para> Every system resource, whether an application program, directory, or file, has a unique name: its <firstterm>filename</firstterm>. You can think of a filename has a unique identifier for that system resource. The part of Linux that manages these named system resources is known as the <firstterm>file system</firstterm>. </para> <para> In addition to the file content itself, the file system keeps extra information about every file: its size; disk block locations; and modification and access timestamps. You can see most of this "meta-data" using the <application>ls(1)</application> program: </para> <example id="credentials-perms-ls"> <title>Using ls(1) to examine file permissions</title> <screen width="60">$ ls -l /bin/mail -rwxr-xr-x 1 root mail 73588 Apr 4 07:03 /bin/mail</screen> </example> <para> We are most interested in two groups of information about the file: its ownership and its access permissions. </para> <para> When a user creates a file, the user credentials are attached to the file, giving that user <emphasis>ownership</emphasis> of that file<footnote> <para> The <application>chown(1)</application> program allows the ownership credentials to be changed, but that is another HOWTO. </para> </footnote>. In our example, <filename>/bin/mail</filename> is owned by user <userinput>root</userinput> and group <userinput>mail</userinput>. </para> <para> The created file also gets a set of file access permissions that describe who may access that file and what kind of access they can get. There are exactly three types of access: read, write, or execute ‐ usually abbreviated as <abbrev>rwx</abbrev>. Permissions for a file which could be read, but neither written nor executed, would be written as <abbrev>r--</abbrev>. Remember, the notation is positional and order matters. </para> <para> Files actually have three sets of permissions: one set for the file owner, one set for members of the owner's group; and one set for everyone else; again order matters, the owner permissions are first, followed by the group and then the world permissions. In the next section, we shall see how Linux puts all this together. </para> </section> <section id="credentials-method"> <title>May I Access This File, Please?</title> <para> Before any file is accessed, and this includes running an application program, the file system must validate the attempt. There is a very simple, but very powerful, method used to determine whether access should be granted or denied. This algorithm is shown below: </para> <example id="credentials-method-howto"> <title>Determining File Access</title> <programlisting width="60">if( u.uid == f.uid ) { rwx = perms.owner; } else if( u.gid == f.gid ) { rwx = perms.group; } else { rwx = perms.world; } if( !accessok( access_wanted, rwx ) ) { errno = EPERM; return( -1 ); } do_access();</programlisting> </example> <para> Assuming the following definitions: </para> <glosslist> <glossentry> <glossterm>u</glossterm> <glossdef> <para> Represents the user credentials containing both the <abbrev>uid</abbrev> and <abbrev>gid</abbrev>. </para> </glossdef> </glossentry> <glossentry> <glossterm>f</glossterm> <glossdef> <para> Represents the file ownership credentials, as shown by the <command>ls -l</command> command. Contains both the <abbrev>uid</abbrev> and <abbrev>gid</abbrev> values identifying the owner of the file. </para> </glossdef> </glossentry> <glossentry> <glossterm>perms</glossterm> <glossdef><para> The file access permissions for the file, including all three sets of permissions: owner, group and world. </para></glossdef> </glossentry> </glosslist> <para> The key point here is that, although there are three sets of file access permissions associated with the file, exactly <emphasis>one</emphasis> set is used to arbitrate the file access. Emphatically, the sets are <emphasis>not</emphasis> tried in sequence until the access is granted or we run out of sets: you get one and only one try at accessing the file. </para> <para> If you are the owner of the file, the system uses the file owner permissions. If you are not the owner, but a member of the same group as the file, the system uses the group permissions. If you are neither of these, the system checks against the world permissions. </para> </section> </section> <section id="bad-karma"> <title>What Not To Do</title> <para> As desirable as enforcing file access permissions are on a Linux system, there are valid reasons for needing to bypass the checking. Several users run the same program to generate project files that must be accessible to all; a printer queue is hung and the sysadmin has given a local user authority to restart the printer daemon; an ordinary user wants to mount an NFS hierarchy from a file server; a mail delivery program must be able to write into mail files writable only by the mail recipient; and finally, a local user is empowered to perform designated sysadmin functions but the real sysadmin does not want to grant blanket permission to alter everything on the system. </para> <para> Below we will look at common methods of working around the Linux file access permissions scheme and point out some short-comings of each technique. All these methods "work", in the sense that they function correctly but incur unnecessary security risks. In the next section, we show how <application>sudo(8)</application> controls most of these risks. </para> <section id="bad-karma-su"> <title>Perhaps You Have Heard Of The su(1) Application?</title> <para> One technique, used since <trademark>UNIX</trademark> systems began, is for the user to temporarily assume the privileges of the superuser account. The <application>su(1)</application> changes the identification for the current user by <emphasis>s</emphasis>ubstituting <emphasis>u</emphasis>ser credentials. </para> <example> <title>Traditional Approach Using su(1)</title> <screen width="60">$ id uid=500(reynolds) gid=500(reynolds) groups=500(reynolds) $ su -c id Password: uid=0(root) gid=0(root) groups=0(root),1(bin)...</screen> </example> <para> There are some problems with this approach: </para> <itemizedlist> <listitem> <para> The superuser password is compromised. </para> <para> Once anyone other than the system administrator knows the superuser password, everyone will know it. He that wishes to keep a secret must keep it a secret that he has a secret to keep. Promises not to tell are not sufficient security. </para> </listitem> <listitem> <para> There is no audit trail. </para> <para> With a superuser shell, a user can do anything that the root account can do. We must trust<footnote> <para> In security parlance, "to trust" is identical to "be at risk from". </para> </footnote>the user to access only the files and programs they claimed to need. </para> </listitem> </itemizedlist> </section> <section id="bad-karma-suid"> <title>Please, No Setuid Shell Scripts</title> <para> Another technology, used by the <application>su(1)</application> program, takes advantage of a neat feature. </para> <para> Normally, the files accessible to an application or shell depend on who is executing that program. Recall those <emphasis>credentials</emphasis> mentioned earlier? An application executes using the credentials of the user who runs the program. </para> <para> Stop, wait, there's more! </para> <para> Files have access permissions but since a program is stored in a file, the program has file access permissions, too. </para> <para> By setting a special flag, called the <firstterm>set user id bit</firstterm> or <function>setuid(2)</function>, we can cause the system to check "credentials" made from the program file access permissions, instead of using the credentials for the user running the application<footnote> <para> The commands: </para> <screen width="60"># chown root:root /bin/foo # chmod 06555 /bin/foo</screen> <para> would give whomever runs <filename>/bin/foo</filename> the same privileges that the superuser account would have while running the same application. </para> </footnote>. </para> <para> This ability to use the credentials of an application, instead of those of the user, can be a great boon to multiuser applications such as databases or email delivery agents. The feature has its proper use on a Linux system. </para> <para> As useful as it is, one must resist the temptation to make a shell program, such as <filename>/bin/bash</filename>, or a shell script, such as <filename>/usr/local/bin/run_as_root</filename>, be set user ID to root. </para> <para> If this were to be done, then <emphasis>any</emphasis> user running that script or application would be able to access any file that the root account could access. </para> <para> Again, the objections to this method a similar to those we mentioned for the <application>su(1)</application> program: no control, and no traceability. </para> </section> </section> <section id="at-last"> <title>A Safer Alternative: sudo(8)</title> <para> The <application>sudo(8)</application> program solves the dilemma of how to allow ordinary users access to certain privileged system resources yet still keep the superuser password secret. </para> <para> Before granting privileges to a user, the <application>sudo(8)</application> program checks the configuration file <filename>/etc/sudoers</filename> and: </para> <itemizedlist> <listitem> <para> Grants privileges to the user without requiring any password at all. </para> </listitem> <listitem> <para> Grants privileges to the user if, and only if, the user supplies the correct password to prove their identity. Note that this is the password for the user account, <emphasis>not</emphasis> the superuser password. </para> </listitem> <listitem> <para> Deny the access and notify the system administrator of the failed attempt via an email sent to the root account. </para> </listitem> <listitem><para> Log the command, its arguments, and timestamp into the <filename>/var/log/secure</filename> file. </para></listitem> </itemizedlist> <para> <application>Sudo(8)</application> keeps a log of all activity in the <filename>/var/log/secure</filename> file. Thus, there is an audit trail recording everything done in the name of the system administrator. </para> <section id="at-last-setup"> <title>Controlling Access To sudo(8)</title> <para> The <filename>/etc/sudoers</filename> file configures the programs that users can access using <application>sudo(8)</application>, along with whether or not a password will be needed. </para> <para> The system administrator adds users to this file using the <filename>/usr/sbin/visudo</filename> command. Each non-comment line in the file has two parts: </para> <orderedlist> <listitem> <para> A username ("reynolds"), or a group name ("%wheel").</para> </listitem> <listitem> <para> A list of machine names where a program may be run, or the keyword <literal>ALL</literal>. Following an equal sign (<literal>=</literal>), a list of user identities the command may be run as, enclosed in round brackets (parenthesis); the wildcard <literal>ALL</literal> may also appear. Finally, a list of applications which may be run as the named users; the keyword <literal>ALL</literal> is a wildcard. </para> </listitem> </orderedlist> <para> The following examples should help make this clear: </para> <example> <title>/etc/sudoers Examples</title> <variablelist> <varlistentry> <term> <computeroutput>reynolds ALL=(ALL) ALL</computeroutput> </term> <listitem> <para> User reynolds can execute any command as any user, but must know the password to the reynolds account. </para> </listitem> </varlistentry> <varlistentry> <term> <computeroutput>reynolds ALL=(root) shutdown</computeroutput> </term> <listitem> <para> User reynolds can execute only command <application>shutdown</application>, but must know the password to the reynolds account. </para> </listitem> </varlistentry> <varlistentry> <term> <computeroutput>reynolds ALL=(root) NOPASSWD: /usr/bin/id</computeroutput> </term> <listitem> <para> User reynolds can execute only the application <filename>/usr/bin/id</filename>; no password will be needed. </para> </listitem> </varlistentry> </variablelist> </example> </section> <section id="at-last-using"> <title>Using sudo(8)</title> <para> Once the system administrator has entered the necessary setup into the <filename>/etc/sudoers</filename> file, users can safely access privileged system resources and activities like this: </para> <screen width="60">$ sudo reboot Password:</screen> <para> No awkward quoting on the command line, just prefix the command you want with the word <userinput>sudo</userinput>. If you want to run the command as a user other than <userinput>root</userinput>, just add the <option>-u </option><replaceable>username</replaceable> switch: </para> <screen width="60">$ sudo -u reynolds id</screen> <para> There will be a log entry written to the <filename>/var/log/secure</filename> file to show who did the deed. </para> <para> Of course, the sysadmin may have configured <application>sudo(8)</application> not to request a password. In this case, the command is immediately executed although the audit trail entry will still be written. </para> </section> </section> <section id="summary"> <title>And, In Conclusion</title> <para> The <application>sudo(8)</application> program provides a safe, controlled facility that allows a user to run a defined set of programs using the credentials of a defined set of users. The superuser password need never be publicised or compromised, since <application>sudo(8)</application> is controlled from a configuration file crafted by the system administrator. </para> <para> All commands run by <application>sudo(8)</application> are logged to the <filename>/var/log/secure</filename> file, while access violations are reported via email. Traceability results. </para> <para> From a user perspective, <application>sudo(8)</application> is easy to use: simply prefix the desired command line with the word <wordasword>sudo</wordasword>, press return, and possibly enter a password (but <emphasis>not</emphasis> the superuser password). </para> <para> End Of Document </para> </section> </article>
Attachment:
pgpJT7GIQAvGb.pgp
Description: PGP signature