📄 library_25.html
字号:
the number of group IDs in the array <VAR>groups</VAR>.<P>This function returns <CODE>0</CODE> if successful and <CODE>-1</CODE> on error.The following <CODE>errno</CODE> error conditions are defined for thisfunction:<P><DL COMPACT><DT><CODE>EPERM</CODE><DD>The calling process is not privileged.</DL><P><A NAME="IDX1810"></A><U>Function:</U> int <B>initgroups</B> <I>(const char *<VAR>user</VAR>, gid_t <VAR>gid</VAR>)</I><P>The <CODE>initgroups</CODE> function effectively calls <CODE>setgroups</CODE> toset the process's supplementary group IDs to be the normal default forthe user name <VAR>user</VAR>. The group ID <VAR>gid</VAR> is also included.<P><H2><A NAME="SEC437" HREF="library_toc.html#SEC437" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_toc.html#SEC437">Enabling and Disabling Setuid Access</A></H2><P>A typical setuid program does not need its special access all of thetime. It's a good idea to turn off this access when it isn't needed,so it can't possibly give unintended access.<P>If the system supports the saved user ID feature, you can accomplishthis with <CODE>setuid</CODE>. When the game program starts, its real user IDis <CODE>jdoe</CODE>, its effective user ID is <CODE>games</CODE>, and its saveduser ID is also <CODE>games</CODE>. The program should record both user IDvalues once at the beginning, like this:<P><PRE>user_user_id = getuid ();game_user_id = geteuid ();</PRE><P>Then it can turn off game file access with <P><PRE>setuid (user_user_id);</PRE><P>and turn it on with <P><PRE>setuid (game_user_id);</PRE><P>Throughout this process, the real user ID remains <CODE>jdoe</CODE> and thesaved user ID remains <CODE>games</CODE>, so the program can always set itseffective user ID to either one.<P>On other systems that don't support the saved user ID feature, you canturn setuid access on and off by using <CODE>setreuid</CODE> to swap the realand effective user IDs of the process, as follows:<P><PRE>setreuid (geteuid (), getuid ());</PRE><P>This special case is always allowed--it cannot fail.<P>Why does this have the effect of toggling the setuid access? Suppose agame program has just started, and its real user ID is <CODE>jdoe</CODE> whileits effective user ID is <CODE>games</CODE>. In this state, the game canwrite the scores file. If it swaps the two uids, the real becomes<CODE>games</CODE> and the effective becomes <CODE>jdoe</CODE>; now the program hasonly <CODE>jdoe</CODE> access. Another swap brings <CODE>games</CODE> back tothe effective user ID and restores access to the scores file.<P>In order to handle both kinds of systems, test for the saved user IDfeature with a preprocessor conditional, like this:<P><PRE>#ifdef _POSIX_SAVED_IDS setuid (user_user_id);#else setreuid (geteuid (), getuid ());#endif</PRE><P><H2><A NAME="SEC438" HREF="library_toc.html#SEC438" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_toc.html#SEC438">Setuid Program Example</A></H2><P>Here's an example showing how to set up a program that changes itseffective user ID.<P>This is part of a game program called <CODE>caber-toss</CODE> thatmanipulates a file <TT>`scores'</TT> that should be writable only by the gameprogram itself. The program assumes that its executablefile will be installed with the set-user-ID bit set and owned by thesame user as the <TT>`scores'</TT> file. Typically, a systemadministrator will set up an account like <CODE>games</CODE> for this purpose.<P>The executable file is given mode <CODE>4755</CODE>, so that doing an <SAMP>`ls -l'</SAMP> on it produces output like:<P><PRE>-rwsr-xr-x 1 games 184422 Jul 30 15:17 caber-toss</PRE><P>The set-user-ID bit shows up in the file modes as the <SAMP>`s'</SAMP>.<P>The scores file is given mode <CODE>644</CODE>, and doing an <SAMP>`ls -l'</SAMP> onit shows:<P><PRE>-rw-r--r-- 1 games 0 Jul 31 15:33 scores</PRE><P>Here are the parts of the program that show how to set up the changeduser ID. This program is conditionalized so that it makes use of thesaved IDs feature if it is supported, and otherwise uses <CODE>setreuid</CODE>to swap the effective and real user IDs.<P><PRE>#include <stdio.h>#include <sys/types.h>#include <unistd.h>#include <stdlib.h>/* Save the effective and real UIDs. */static uid_t euid, ruid;/* Restore the effective UID to its original value. */voiddo_setuid (void){ int status;#ifdef _POSIX_SAVED_IDS status = setuid (euid);#else status = setreuid (ruid, euid);#endif if (status < 0) { fprintf (stderr, "Couldn't set uid.\n"); exit (status); }}/* Set the effective UID to the real UID. */voidundo_setuid (void){ int status;#ifdef _POSIX_SAVED_IDS status = setuid (ruid);#else status = setreuid (euid, ruid);#endif if (status < 0) { fprintf (stderr, "Couldn't set uid.\n"); exit (status); }}/* Main program. */intmain (void){ /* Save the real and effective user IDs. */ ruid = getuid (); euid = geteuid (); undo_setuid (); /* Do the game and record the score. */ ...}</PRE><P>Notice how the first thing the <CODE>main</CODE> function does is to set theeffective user ID back to the real user ID. This is so that any otherfile accesses that are performed while the user is playing the game usethe real user ID for determining permissions. Only when the programneeds to open the scores file does it switch back to the originaleffective user ID, like this:<P><PRE>/* Record the score. */intrecord_score (int score){ FILE *stream; char *myname; /* Open the scores file. */ do_setuid (); stream = fopen (SCORES_FILE, "a"); undo_setuid (); /* Write the score to the file. */ if (stream) { myname = cuserid (NULL); if (score < 0) fprintf (stream, "%10s: Couldn't lift the caber.\n", myname); else fprintf (stream, "%10s: %d feet.\n", myname, score); fclose (stream); return 0; } else return -1;}</PRE><P><H2><A NAME="SEC439" HREF="library_toc.html#SEC439" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_toc.html#SEC439">Tips for Writing Setuid Programs</A></H2><P>It is easy for setuid programs to give the user access that isn't intended--in fact, if you want to avoid this, you need to be careful.Here are some guidelines for preventing unintended access andminimizing its consequences when it does occur:<P><UL><LI>Don't have <CODE>setuid</CODE> programs with privileged user IDs such as<CODE>root</CODE> unless it is absolutely necessary. If the resource isspecific to your particular program, it's better to define a new,nonprivileged user ID or group ID just to manage that resource.<P><LI>Be cautious about using the <CODE>system</CODE> and <CODE>exec</CODE> functions incombination with changing the effective user ID. Don't let users ofyour program execute arbitrary programs under a changed user ID.Executing a shell is especially bad news. Less obviously, the<CODE>execlp</CODE> and <CODE>execvp</CODE> functions are a potential risk (sincethe program they execute depends on the user's <CODE>PATH</CODE> environmentvariable).<P>If you must <CODE>exec</CODE> another program under a changed ID, specify anabsolute file name (see section <A HREF="library_10.html#SEC114" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_10.html#SEC114">File Name Resolution</A>) for the executable,and make sure that the protections on that executable and <EM>all</EM>containing directories are such that ordinary users cannot replace itwith some other program.<P><LI>Only use the user ID controlling the resource in the part of the programthat actually uses that resource. When you're finished with it, restorethe effective user ID back to the actual user's user ID.See section <A HREF="library_25.html#SEC437" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_25.html#SEC437">Enabling and Disabling Setuid Access</A>.<P><LI>If the <CODE>setuid</CODE> part of your program needs to access other filesbesides the controlled resource, it should verify that the real userwould ordinarily have permission to access those files. You can use the<CODE>access</CODE> function (see section <A HREF="library_13.html#SEC206" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_13.html#SEC206">How Your Access to a File is Decided</A>) to check this; ituses the real user and group IDs, rather than the effective IDs.</UL><P><A NAME="IDX1811"></A><A NAME="IDX1812"></A><H2><A NAME="SEC440" HREF="library_toc.html#SEC440" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_toc.html#SEC440">Identifying Who Logged In</A></H2><P>You can use the functions listed in this section to determine the loginname of the user who is running a process, and the name of the user whologged in the current session. See also the function <CODE>getuid</CODE> andfriends (see section <A HREF="library_25.html#SEC434" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_25.html#SEC434">Reading the Persona of a Process</A>).<P>The <CODE>getlogin</CODE> function is declared in <TT>`unistd.h'</TT>, while<CODE>cuserid</CODE> and <CODE>L_cuserid</CODE> are declared in <TT>`stdio.h'</TT>.<A NAME="IDX1814"></A><A NAME="IDX1813"></A><P><A NAME="IDX1815"></A><U>Function:</U> char * <B>getlogin</B> <I>(void)</I><P>The <CODE>getlogin</CODE> function returns a pointer to a string containing thename of the user logged in on the controlling terminal of the process,or a null pointer if this information cannot be determined. The stringis statically allocated and might be overwritten on subsequent calls tothis function or to <CODE>cuserid</CODE>.<P><A NAME="IDX1816"></A><U>Function:</U> char * <B>cuserid</B> <I>(char *<VAR>string</VAR>)</I><P>The <CODE>cuserid</CODE> function returns a pointer to a string containing auser name associated with the effective ID of the process. If<VAR>string</VAR> is not a null pointer, it should be an array that can holdat least <CODE>L_cuserid</CODE> characters; the string is returned in thisarray. Otherwise, a pointer to a string in a static area is returned.This string is statically allocated and might be overwritten onsubsequent calls to this function or to <CODE>getlogin</CODE>.<P><A NAME="IDX1817"></A><U>Macro:</U> int <B>L_cuserid</B><P>An integer constant that indicates how long an array you might need tostore a user name.<P>These functions let your program identify positively the user who isrunning or the user who logged in this session. (These can differ whensetuid programs are involved; See section <A HREF="library_25.html#SEC431" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_25.html#SEC431">The Persona of a Process</A>.) The user cannotdo anything to fool these functions.<P>For most purposes, it is more useful to use the environment variable<CODE>LOGNAME</CODE> to find out who the user is. This is more flexibleprecisely because the user can set <CODE>LOGNAME</CODE> arbitrarily.See section <A HREF="library_22.html#SEC394" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_22.html#SEC394">Standard Environment Variables</A>.<P><A NAME="IDX1818"></A><A NAME="IDX1819"></A><A NAME="IDX1820"></A><H2><A NAME="SEC441" HREF="library_toc.html#SEC441" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_toc.html#SEC441">User Database</A></H2><P>This section describes all about now to search and scan the database of
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -