
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