(linenum→info "unix/slp.c:2238")

glibc/2.7/manual/users.texi

    1: @node Users and Groups, System Management, Name Service Switch, Top
    2: @c %MENU% How users are identified and classified
    3: @chapter Users and Groups
    4: 
    5: Every user who can log in on the system is identified by a unique number
    6: called the @dfn{user ID}.  Each process has an effective user ID which
    7: says which user's access permissions it has.
    8: 
    9: Users are classified into @dfn{groups} for access control purposes.  Each
   10: process has one or more @dfn{group ID values} which say which groups the
   11: process can use for access to files.
   12: 
   13: The effective user and group IDs of a process collectively form its
   14: @dfn{persona}.  This determines which files the process can access.
   15: Normally, a process inherits its persona from the parent process, but
   16: under special circumstances a process can change its persona and thus
   17: change its access permissions.
   18: 
   19: Each file in the system also has a user ID and a group ID.  Access
   20: control works by comparing the user and group IDs of the file with those
   21: of the running process.
   22: 
   23: The system keeps a database of all the registered users, and another
   24: database of all the defined groups.  There are library functions you
   25: can use to examine these databases.
   26: 
   27: @menu
   28: * User and Group IDs::          Each user has a unique numeric ID;
   29:                                  likewise for groups.
   30: * Process Persona::             The user IDs and group IDs of a process.
   31: * Why Change Persona::          Why a program might need to change
   32:                                  its user and/or group IDs.
   33: * How Change Persona::          Changing the user and group IDs.
   34: * Reading Persona::             How to examine the user and group IDs.
   35: 
   36: * Setting User ID::             Functions for setting the user ID.
   37: * Setting Groups::              Functions for setting the group IDs.
   38: 
   39: * Enable/Disable Setuid::       Turning setuid access on and off.
   40: * Setuid Program Example::      The pertinent parts of one sample program.
   41: * Tips for Setuid::             How to avoid granting unlimited access.
   42: 
   43: * Who Logged In::               Getting the name of the user who logged in,
   44:                                  or of the real user ID of the current process.
   45: 
   46: * User Accounting Database::    Keeping information about users and various
   47:                                  actions in databases.
   48: 
   49: * User Database::               Functions and data structures for
   50:                                  accessing the user database.
   51: * Group Database::              Functions and data structures for
   52:                                  accessing the group database.
   53: * Database Example::            Example program showing the use of database
   54:                                  inquiry functions.
   55: * Netgroup Database::           Functions for accessing the netgroup database.
   56: @end menu
   57: 
   58: @node User and Group IDs
   59: @section User and Group IDs
   60: 
   61: @cindex login name
   62: @cindex user name
   63: @cindex user ID
   64: Each user account on a computer system is identified by a @dfn{user
   65: name} (or @dfn{login name}) and @dfn{user ID}.  Normally, each user name
   66: has a unique user ID, but it is possible for several login names to have
   67: the same user ID.  The user names and corresponding user IDs are stored
   68: in a data base which you can access as described in @ref{User Database}.
   69: 
   70: @cindex group name
   71: @cindex group ID
   72: Users are classified in @dfn{groups}.  Each user name belongs to one
   73: @dfn{default group} and may also belong to any number of
   74: @dfn{supplementary groups}. Users who are members of the same group can
   75: share resources (such as files) that are not accessible to users who are
   76: not a member of that group.  Each group has a @dfn{group name} and
   77: @dfn{group ID}.  @xref{Group Database}, for how to find information
   78: about a group ID or group name.
   79: 
   80: @node Process Persona
   81: @section The Persona of a Process
   82: @cindex persona
   83: @cindex effective user ID
   84: @cindex effective group ID
   85: @cindex supplementary group IDs
   86: 
   87: @c When Hurd is more widely used, explain multiple effective user IDs
   88: @c here. -zw
   89: At any time, each process has an @dfn{effective user ID}, a @dfn{effective
   90: group ID}, and a set of @dfn{supplementary group IDs}.  These IDs
   91: determine the privileges of the process.  They are collectively
   92: called the @dfn{persona} of the process, because they determine ``who it
   93: is'' for purposes of access control.
   94: 
   95: Your login shell starts out with a persona which consists of your user
   96: ID, your default group ID, and your supplementary group IDs (if you are
   97: in more than one group).  In normal circumstances, all your other processes
   98: inherit these values.
   99: 
  100: @cindex real user ID
  101: @cindex real group ID
  102: A process also has a @dfn{real user ID} which identifies the user who
  103: created the process, and a @dfn{real group ID} which identifies that
  104: user's default group.  These values do not play a role in access
  105: control, so we do not consider them part of the persona.  But they are
  106: also important.
  107: 
  108: Both the real and effective user ID can be changed during the lifetime
  109: of a process.  @xref{Why Change Persona}.
  110: 
  111: For details on how a process's effective user ID and group IDs affect
  112: its permission to access files, see @ref{Access Permission}.
  113: 
  114: The effective user ID of a process also controls permissions for sending
  115: signals using the @code{kill} function.  @xref{Signaling Another
  116: Process}.
  117: 
  118: Finally, there are many operations which can only be performed by a
  119: process whose effective user ID is zero.  A process with this user ID is
  120: a @dfn{privileged process}.  Commonly the user name @code{root} is
  121: associated with user ID 0, but there may be other user names with this
  122: ID.
  123: @c !!! should mention POSIX capabilities here.
  124: 
  125: @node Why Change Persona
  126: @section Why Change the Persona of a Process?
  127: 
  128: The most obvious situation where it is necessary for a process to change
  129: its user and/or group IDs is the @code{login} program.  When
  130: @code{login} starts running, its user ID is @code{root}.  Its job is to
  131: start a shell whose user and group IDs are those of the user who is
  132: logging in.  (To accomplish this fully, @code{login} must set the real
  133: user and group IDs as well as its persona.  But this is a special case.)
  134: 
  135: The more common case of changing persona is when an ordinary user
  136: program needs access to a resource that wouldn't ordinarily be
  137: accessible to the user actually running it.
  138: 
  139: For example, you may have a file that is controlled by your program but
  140: that shouldn't be read or modified directly by other users, either
  141: because it implements some kind of locking protocol, or because you want
  142: to preserve the integrity or privacy of the information it contains.
  143: This kind of restricted access can be implemented by having the program
  144: change its effective user or group ID to match that of the resource.
  145: 
  146: Thus, imagine a game program that saves scores in a file.  The game
  147: program itself needs to be able to update this file no matter who is
  148: running it, but if users can write the file without going through the
  149: game, they can give themselves any scores they like.  Some people
  150: consider this undesirable, or even reprehensible.  It can be prevented
  151: by creating a new user ID and login name (say, @code{games}) to own the
  152: scores file, and make the file writable only by this user.  Then, when
  153: the game program wants to update this file, it can change its effective
  154: user ID to be that for @code{games}.  In effect, the program must
  155: adopt the persona of @code{games} so it can write the scores file.
  156: 
  157: @node How Change Persona
  158: @section How an Application Can Change Persona
  159: @cindex @code{setuid} programs
  160: @cindex saved set-user-ID
  161: @cindex saved set-group-ID
  162: @cindex @code{_POSIX_SAVED_IDS}
  163: 
  164: The ability to change the persona of a process can be a source of
  165: unintentional privacy violations, or even intentional abuse.  Because of
  166: the potential for problems, changing persona is restricted to special
  167: circumstances.
  168: 
  169: You can't arbitrarily set your user ID or group ID to anything you want;
  170: only privileged processes can do that.  Instead, the normal way for a
  171: program to change its persona is that it has been set up in advance to
  172: change to a particular user or group.  This is the function of the setuid
  173: and setgid bits of a file's access mode.  @xref{Permission Bits}.
  174: 
  175: When the setuid bit of an executable file is on, executing that file
  176: gives the process a third user ID: the @dfn{file user ID}.  This ID is
  177: set to the owner ID of the file.  The system then changes the effective
  178: user ID to the file user ID.  The real user ID remains as it was.
  179: Likewise, if the setgid bit is on, the process is given a @dfn{file
  180: group ID} equal to the group ID of the file, and its effective group ID
  181: is changed to the file group ID.
  182: 
  183: If a process has a file ID (user or group), then it can at any time
  184: change its effective ID to its real ID and back to its file ID.
  185: Programs use this feature to relinquish their special privileges except
  186: when they actually need them.  This makes it less likely that they can
  187: be tricked into doing something inappropriate with their privileges.
  188: 
  189: @strong{Portability Note:} Older systems do not have file IDs.
  190: To determine if a system has this feature, you can test the compiler
  191: define @code{_POSIX_SAVED_IDS}.  (In the POSIX standard, file IDs are
  192: known as saved IDs.)
  193: 
  194: @xref{File Attributes}, for a more general discussion of file modes and
  195: accessibility.
  196: 
  197: @node Reading Persona
  198: @section Reading the Persona of a Process
  199: 
  200: Here are detailed descriptions of the functions for reading the user and
  201: group IDs of a process, both real and effective.  To use these
  202: facilities, you must include the header files @file{sys/types.h} and
  203: @file{unistd.h}.
  204: @pindex unistd.h
  205: @pindex sys/types.h
  206: 
  207: @comment sys/types.h
  208: @comment POSIX.1
  209: @deftp {Data Type} uid_t
  210: This is an integer data type used to represent user IDs.  In the GNU
  211: library, this is an alias for @code{unsigned int}.
  212: @end deftp
  213: 
  214: @comment sys/types.h
  215: @comment POSIX.1
  216: @deftp {Data Type} gid_t
  217: This is an integer data type used to represent group IDs.  In the GNU
  218: library, this is an alias for @code{unsigned int}.
  219: @end deftp
  220: 
  221: @comment unistd.h
  222: @comment POSIX.1
  223: @deftypefun uid_t getuid (void)
  224: The @code{getuid} function returns the real user ID of the process.
  225: @end deftypefun
  226: 
  227: @comment unistd.h
  228: @comment POSIX.1
  229: @deftypefun gid_t getgid (void)
  230: The @code{getgid} function returns the real group ID of the process.
  231: @end deftypefun
  232: 
  233: @comment unistd.h
  234: @comment POSIX.1
  235: @deftypefun uid_t geteuid (void)
  236: The @code{geteuid} function returns the effective user ID of the process.
  237: @end deftypefun
  238: 
  239: @comment unistd.h
  240: @comment POSIX.1
  241: @deftypefun gid_t getegid (void)
  242: The @code{getegid} function returns the effective group ID of the process.
  243: @end deftypefun
  244: 
  245: @comment unistd.h
  246: @comment POSIX.1
  247: @deftypefun int getgroups (int @var{count}, gid_t *@var{groups})
  248: The @code{getgroups} function is used to inquire about the supplementary
  249: group IDs of the process.  Up to @var{count} of these group IDs are
  250: stored in the array @var{groups}; the return value from the function is
  251: the number of group IDs actually stored.  If @var{count} is smaller than
  252: the total number of supplementary group IDs, then @code{getgroups}
  253: returns a value of @code{-1} and @code{errno} is set to @code{EINVAL}.
  254: 
  255: If @var{count} is zero, then @code{getgroups} just returns the total
  256: number of supplementary group IDs.  On systems that do not support
  257: supplementary groups, this will always be zero.
  258: 
  259: Here's how to use @code{getgroups} to read all the supplementary group
  260: IDs:
  261: 
  262: @smallexample
  263: @group
  264: gid_t *
  265: read_all_groups (void)
  266: @{
  267:   int ngroups = getgroups (0, NULL);
  268:   gid_t *groups
  269:     = (gid_t *) xmalloc (ngroups * sizeof (gid_t));
  270:   int val = getgroups (ngroups, groups);
  271:   if (val < 0)
  272:     @{
  273:       free (groups);
  274:       return NULL;
  275:     @}
  276:   return groups;
  277: @}
  278: @end group
  279: @end smallexample
  280: @end deftypefun
  281: 
  282: @node Setting User ID
  283: @section Setting the User ID
  284: 
  285: This section describes the functions for altering the user ID (real
  286: and/or effective) of a process.  To use these facilities, you must
  287: include the header files @file{sys/types.h} and @file{unistd.h}.
  288: @pindex unistd.h
  289: @pindex sys/types.h
  290: 
  291: @comment unistd.h
  292: @comment POSIX.1
  293: @deftypefun int seteuid (uid_t @var{neweuid})
  294: This function sets the effective user ID of a process to @var{newuid},
  295: provided that the process is allowed to change its effective user ID.  A
  296: privileged process (effective user ID zero) can change its effective
  297: user ID to any legal value.  An unprivileged process with a file user ID
  298: can change its effective user ID to its real user ID or to its file user
  299: ID.  Otherwise, a process may not change its effective user ID at all.
  300: 
  301: The @code{seteuid} function returns a value of @code{0} to indicate
  302: successful completion, and a value of @code{-1} to indicate an error.
  303: The following @code{errno} error conditions are defined for this
  304: function:
  305: 
  306: @table @code
  307: @item EINVAL
  308: The value of the @var{newuid} argument is invalid.
  309: 
  310: @item EPERM
  311: The process may not change to the specified ID.
  312: @end table
  313: 
  314: Older systems (those without the @code{_POSIX_SAVED_IDS} feature) do not
  315: have this function.
  316: @end deftypefun
  317: 
  318: @comment unistd.h
  319: @comment POSIX.1
  320: @deftypefun int setuid (uid_t @var{newuid})
  321: If the calling process is privileged, this function sets both the real
  322: and effective user ID of the process to @var{newuid}.  It also deletes
  323: the file user ID of the process, if any.  @var{newuid} may be any
  324: legal value.  (Once this has been done, there is no way to recover the
  325: old effective user ID.)
  326: 
  327: If the process is not privileged, and the system supports the
  328: @code{_POSIX_SAVED_IDS} feature, then this function behaves like
  329: @code{seteuid}.
  330: 
  331: The return values and error conditions are the same as for @code{seteuid}.
  332: @end deftypefun
  333: 
  334: @comment unistd.h
  335: @comment BSD
  336: @deftypefun int setreuid (uid_t @var{ruid}, uid_t @var{euid})
  337: This function sets the real user ID of the process to @var{ruid} and the
  338: effective user ID to @var{euid}.  If @var{ruid} is @code{-1}, it means
  339: not to change the real user ID; likewise if @var{euid} is @code{-1}, it
  340: means not to change the effective user ID.
  341: 
  342: The @code{setreuid} function exists for compatibility with 4.3 BSD Unix,
  343: which does not support file IDs.  You can use this function to swap the
  344: effective and real user IDs of the process.  (Privileged processes are
  345: not limited to this particular usage.)  If file IDs are supported, you
  346: should use that feature instead of this function.  @xref{Enable/Disable
  347: Setuid}.
  348: 
  349: The return value is @code{0} on success and @code{-1} on failure.
  350: The following @code{errno} error conditions are defined for this
  351: function:
  352: 
  353: @table @code
  354: @item EPERM
  355: The process does not have the appropriate privileges; you do not
  356: have permission to change to the specified ID.
  357: @end table
  358: @end deftypefun
  359: 
  360: @node Setting Groups
  361: @section Setting the Group IDs
  362: 
  363: This section describes the functions for altering the group IDs (real
  364: and effective) of a process.  To use these facilities, you must include
  365: the header files @file{sys/types.h} and @file{unistd.h}.
  366: @pindex unistd.h
  367: @pindex sys/types.h
  368: 
  369: @comment unistd.h
  370: @comment POSIX.1
  371: @deftypefun int setegid (gid_t @var{newgid})
  372: This function sets the effective group ID of the process to
  373: @var{newgid}, provided that the process is allowed to change its group
  374: ID.  Just as with @code{seteuid}, if the process is privileged it may
  375: change its effective group ID to any value; if it isn't, but it has a
  376: file group ID, then it may change to its real group ID or file group ID;
  377: otherwise it may not change its effective group ID.
  378: 
  379: Note that a process is only privileged if its effective @emph{user} ID
  380: is zero.  The effective group ID only affects access permissions.
  381: 
  382: The return values and error conditions for @code{setegid} are the same
  383: as those for @code{seteuid}.
  384: 
  385: This function is only present if @code{_POSIX_SAVED_IDS} is defined.
  386: @end deftypefun
  387: 
  388: @comment unistd.h
  389: @comment POSIX.1
  390: @deftypefun int setgid (gid_t @var{newgid})
  391: This function sets both the real and effective group ID of the process
  392: to @var{newgid}, provided that the process is privileged.  It also
  393: deletes the file group ID, if any.
  394: 
  395: If the process is not privileged, then @code{setgid} behaves like
  396: @code{setegid}.
  397: 
  398: The return values and error conditions for @code{setgid} are the same
  399: as those for @code{seteuid}.
  400: @end deftypefun
  401: 
  402: @comment unistd.h
  403: @comment BSD
  404: @deftypefun int setregid (gid_t @var{rgid}, gid_t @var{egid})
  405: This function sets the real group ID of the process to @var{rgid} and
  406: the effective group ID to @var{egid}.  If @var{rgid} is @code{-1}, it
  407: means not to change the real group ID; likewise if @var{egid} is
  408: @code{-1}, it means not to change the effective group ID.
  409: 
  410: The @code{setregid} function is provided for compatibility with 4.3 BSD
  411: Unix, which does not support file IDs.  You can use this function to
  412: swap the effective and real group IDs of the process.  (Privileged
  413: processes are not limited to this usage.)  If file IDs are supported,
  414: you should use that feature instead of using this function.
  415: @xref{Enable/Disable Setuid}.
  416: 
  417: The return values and error conditions for @code{setregid} are the same
  418: as those for @code{setreuid}.
  419: @end deftypefun
  420: 
  421: @code{setuid} and @code{setgid} behave differently depending on whether
  422: the effective user ID at the time is zero.  If it is not zero, they
  423: behave like @code{seteuid} and @code{setegid}.  If it is, they change
  424: both effective and real IDs and delete the file ID.  To avoid confusion,
  425: we recommend you always use @code{seteuid} and @code{setegid} except
  426: when you know the effective user ID is zero and your intent is to change
  427: the persona permanently.  This case is rare---most of the programs that
  428: need it, such as @code{login} and @code{su}, have already been written.
  429: 
  430: Note that if your program is setuid to some user other than @code{root},
  431: there is no way to drop privileges permanently.
  432: 
  433: The system also lets privileged processes change their supplementary
  434: group IDs.  To use @code{setgroups} or @code{initgroups}, your programs
  435: should include the header file @file{grp.h}.
  436: @pindex grp.h
  437: 
  438: @comment grp.h
  439: @comment BSD
  440: @deftypefun int setgroups (size_t @var{count}, gid_t *@var{groups})
  441: This function sets the process's supplementary group IDs.  It can only
  442: be called from privileged processes.  The @var{count} argument specifies
  443: the number of group IDs in the array @var{groups}.
  444: 
  445: This function returns @code{0} if successful and @code{-1} on error.
  446: The following @code{errno} error conditions are defined for this
  447: function:
  448: 
  449: @table @code
  450: @item EPERM
  451: The calling process is not privileged.
  452: @end table
  453: @end deftypefun
  454: 
  455: @comment grp.h
  456: @comment BSD
  457: @deftypefun int initgroups (const char *@var{user}, gid_t @var{group})
  458: The @code{initgroups} function sets the process's supplementary group
  459: IDs to be the normal default for the user name @var{user}.  The group
  460: @var{group} is automatically included.
  461: 
  462: This function works by scanning the group database for all the groups
  463: @var{user} belongs to.  It then calls @code{setgroups} with the list it
  464: has constructed.
  465: 
  466: The return values and error conditions are the same as for
  467: @code{setgroups}.
  468: @end deftypefun
  469: 
  470: If you are interested in the groups a particular user belongs to, but do
  471: not want to change the process's supplementary group IDs, you can use
  472: @code{getgrouplist}.  To use @code{getgrouplist}, your programs should
  473: include the header file @file{grp.h}.
  474: @pindex grp.h
  475: 
  476: @comment grp.h
  477: @comment BSD
  478: @deftypefun int getgrouplist (const char *@var{user}, gid_t @var{group}, gid_t *@var{groups}, int *@var{ngroups})
  479: The @code{getgrouplist} function scans the group database for all the
  480: groups @var{user} belongs to.  Up to *@var{ngroups} group IDs
  481: corresponding to these groups are stored in the array @var{groups}; the
  482: return value from the function is the number of group IDs actually
  483: stored.  If *@var{ngroups} is smaller than the total number of groups
  484: found, then @code{getgrouplist} returns a value of @code{-1} and stores
  485: the actual number of groups in *@var{ngroups}.  The group @var{group} is
  486: automatically included in the list of groups returned by
  487: @code{getgrouplist}.
  488: 
  489: Here's how to use @code{getgrouplist} to read all supplementary groups
  490: for @var{user}:
  491: 
  492: @smallexample
  493: @group
  494: gid_t *
  495: supplementary_groups (char *user)
  496: @{
  497:   int ngroups = 16;
  498:   gid_t *groups
  499:     = (gid_t *) xmalloc (ngroups * sizeof (gid_t));
  500:   struct passwd *pw = getpwnam (user);
  501: 
  502:   if (pw == NULL)
  503:     return NULL;
  504: 
  505:   if (getgrouplist (pw->pw_name, pw->pw_gid, groups, &ngroups) < 0)
  506:     @{
  507:       groups = xrealloc (ngroups * sizeof (gid_t));
  508:       getgrouplist (pw->pw_name, pw->pw_gid, groups, &ngroups);
  509:     @}
  510:   return groups;
  511: @}
  512: @end group
  513: @end smallexample
  514: @end deftypefun
  515: 
  516: @node Enable/Disable Setuid
  517: @section Enabling and Disabling Setuid Access
  518: 
  519: A typical setuid program does not need its special access all of the
  520: time.  It's a good idea to turn off this access when it isn't needed,
  521: so it can't possibly give unintended access.
  522: 
  523: If the system supports the @code{_POSIX_SAVED_IDS} feature, you can
  524: accomplish this with @code{seteuid}.  When the game program starts, its
  525: real user ID is @code{jdoe}, its effective user ID is @code{games}, and
  526: its saved user ID is also @code{games}.  The program should record both
  527: user ID values once at the beginning, like this:
  528: 
  529: @smallexample
  530: user_user_id = getuid ();
  531: game_user_id = geteuid ();
  532: @end smallexample
  533: 
  534: Then it can turn off game file access with
  535: 
  536: @smallexample
  537: seteuid (user_user_id);
  538: @end smallexample
  539: 
  540: @noindent
  541: and turn it on with
  542: 
  543: @smallexample
  544: seteuid (game_user_id);
  545: @end smallexample
  546: 
  547: @noindent
  548: Throughout this process, the real user ID remains @code{jdoe} and the
  549: file user ID remains @code{games}, so the program can always set its
  550: effective user ID to either one.
  551: 
  552: On other systems that don't support file user IDs, you can
  553: turn setuid access on and off by using @code{setreuid} to swap the real
  554: and effective user IDs of the process, as follows:
  555: 
  556: @smallexample
  557: setreuid (geteuid (), getuid ());
  558: @end smallexample
  559: 
  560: @noindent
  561: This special case is always allowed---it cannot fail.
  562: 
  563: Why does this have the effect of toggling the setuid access?  Suppose a
  564: game program has just started, and its real user ID is @code{jdoe} while
  565: its effective user ID is @code{games}.  In this state, the game can
  566: write the scores file.  If it swaps the two uids, the real becomes
  567: @code{games} and the effective becomes @code{jdoe}; now the program has
  568: only @code{jdoe} access.  Another swap brings @code{games} back to
  569: the effective user ID and restores access to the scores file.
  570: 
  571: In order to handle both kinds of systems, test for the saved user ID
  572: feature with a preprocessor conditional, like this:
  573: 
  574: @smallexample
  575: #ifdef _POSIX_SAVED_IDS
  576:   seteuid (user_user_id);
  577: #else
  578:   setreuid (geteuid (), getuid ());
  579: #endif
  580: @end smallexample
  581: 
  582: @node Setuid Program Example
  583: @section Setuid Program Example
  584: 
  585: Here's an example showing how to set up a program that changes its
  586: effective user ID.
  587: 
  588: This is part of a game program called @code{caber-toss} that manipulates
  589: a file @file{scores} that should be writable only by the game program
  590: itself.  The program assumes that its executable file will be installed
  591: with the setuid bit set and owned by the same user as the @file{scores}
  592: file.  Typically, a system administrator will set up an account like
  593: @code{games} for this purpose.
  594: 
  595: The executable file is given mode @code{4755}, so that doing an
  596: @samp{ls -l} on it produces output like:
  597: 
  598: @smallexample
  599: -rwsr-xr-x   1 games    184422 Jul 30 15:17 caber-toss
  600: @end smallexample
  601: 
  602: @noindent
  603: The setuid bit shows up in the file modes as the @samp{s}.
  604: 
  605: The scores file is given mode @code{644}, and doing an @samp{ls -l} on
  606: it shows:
  607: 
  608: @smallexample
  609: -rw-r--r--  1 games           0 Jul 31 15:33 scores
  610: @end smallexample
  611: 
  612: Here are the parts of the program that show how to set up the changed
  613: user ID.  This program is conditionalized so that it makes use of the
  614: file IDs feature if it is supported, and otherwise uses @code{setreuid}
  615: to swap the effective and real user IDs.
  616: 
  617: @smallexample
  618: #include <stdio.h>
  619: #include <sys/types.h>
  620: #include <unistd.h>
  621: #include <stdlib.h>
  622: 
  623: 
  624: /* @r{Remember the effective and real UIDs.} */
  625: 
  626: static uid_t euid, ruid;
  627: 
  628: 
  629: /* @r{Restore the effective UID to its original value.} */
  630: 
  631: void
  632: do_setuid (void)
  633: @{
  634:   int status;
  635: 
  636: #ifdef _POSIX_SAVED_IDS
  637:   status = seteuid (euid);
  638: #else
  639:   status = setreuid (ruid, euid);
  640: #endif
  641:   if (status < 0) @{
  642:     fprintf (stderr, "Couldn't set uid.\n");
  643:     exit (status);
  644:     @}
  645: @}
  646: 
  647: 
  648: @group
  649: /* @r{Set the effective UID to the real UID.} */
  650: 
  651: void
  652: undo_setuid (void)
  653: @{
  654:   int status;
  655: 
  656: #ifdef _POSIX_SAVED_IDS
  657:   status = seteuid (ruid);
  658: #else
  659:   status = setreuid (euid, ruid);
  660: #endif
  661:   if (status < 0) @{
  662:     fprintf (stderr, "Couldn't set uid.\n");
  663:     exit (status);
  664:     @}
  665: @}
  666: @end group
  667: 
  668: /* @r{Main program.} */
  669: 
  670: int
  671: main (void)
  672: @{
  673:   /* @r{Remember the real and effective user IDs.}  */
  674:   ruid = getuid ();
  675:   euid = geteuid ();
  676:   undo_setuid ();
  677: 
  678:   /* @r{Do the game and record the score.}  */
  679:   @dots{}
  680: @}
  681: @end smallexample
  682: 
  683: Notice how the first thing the @code{main} function does is to set the
  684: effective user ID back to the real user ID.  This is so that any other
  685: file accesses that are performed while the user is playing the game use
  686: the real user ID for determining permissions.  Only when the program
  687: needs to open the scores file does it switch back to the file user ID,
  688: like this:
  689: 
  690: @smallexample
  691: /* @r{Record the score.} */
  692: 
  693: int
  694: record_score (int score)
  695: @{
  696:   FILE *stream;
  697:   char *myname;
  698: 
  699:   /* @r{Open the scores file.} */
  700:   do_setuid ();
  701:   stream = fopen (SCORES_FILE, "a");
  702:   undo_setuid ();
  703: 
  704: @group
  705:   /* @r{Write the score to the file.} */
  706:   if (stream)
  707:     @{
  708:       myname = cuserid (NULL);
  709:       if (score < 0)
  710:         fprintf (stream, "%10s: Couldn't lift the caber.\n", myname);
  711:       else
  712:         fprintf (stream, "%10s: %d feet.\n", myname, score);
  713:       fclose (stream);
  714:       return 0;
  715:     @}
  716:   else
  717:     return -1;
  718: @}
  719: @end group
  720: @end smallexample
  721: 
  722: @node Tips for Setuid
  723: @section Tips for Writing Setuid Programs
  724: 
  725: It is easy for setuid programs to give the user access that isn't
  726: intended---in fact, if you want to avoid this, you need to be careful.
  727: Here are some guidelines for preventing unintended access and
  728: minimizing its consequences when it does occur:
  729: 
  730: @itemize @bullet
  731: @item
  732: Don't have @code{setuid} programs with privileged user IDs such as
  733: @code{root} unless it is absolutely necessary.  If the resource is
  734: specific to your particular program, it's better to define a new,
  735: nonprivileged user ID or group ID just to manage that resource.
  736: It's better if you can write your program to use a special group than a
  737: special user.
  738: 
  739: @item
  740: Be cautious about using the @code{exec} functions in combination with
  741: changing the effective user ID.  Don't let users of your program execute
  742: arbitrary programs under a changed user ID.  Executing a shell is
  743: especially bad news. Less obviously, the @code{execlp} and @code{execvp}
  744: functions are a potential risk (since the program they execute depends
  745: on the user's @code{PATH} environment variable).
  746: 
  747: If you must @code{exec} another program under a changed ID, specify an
  748: absolute file name (@pxref{File Name Resolution}) for the executable,
  749: and make sure that the protections on that executable and @emph{all}
  750: containing directories are such that ordinary users cannot replace it
  751: with some other program.
  752: 
  753: You should also check the arguments passed to the program to make sure
  754: they do not have unexpected effects.  Likewise, you should examine the
  755: environment variables.  Decide which arguments and variables are safe,
  756: and reject all others.
  757: 
  758: You should never use @code{system} in a privileged program, because it
  759: invokes a shell.
  760: 
  761: @item
  762: Only use the user ID controlling the resource in the part of the program
  763: that actually uses that resource.  When you're finished with it, restore
  764: the effective user ID back to the actual user's user ID.
  765: @xref{Enable/Disable Setuid}.
  766: 
  767: @item
  768: If the @code{setuid} part of your program needs to access other files
  769: besides the controlled resource, it should verify that the real user
  770: would ordinarily have permission to access those files.  You can use the
  771: @code{access} function (@pxref{Access Permission}) to check this; it