⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 library_25.html

📁 Glibc的中文手册
💻 HTML
📖 第 1 页 / 共 3 页
字号:
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 this
function:
<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> to
set the process's supplementary group IDs to be the normal default for
the 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 the
time.  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 accomplish
this with <CODE>setuid</CODE>.  When the game program starts, its real user ID
is <CODE>jdoe</CODE>, its effective user ID is <CODE>games</CODE>, and its saved
user ID is also <CODE>games</CODE>.  The program should record both user ID
values 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 the
saved user ID remains <CODE>games</CODE>, so the program can always set its
effective user ID to either one.
<P>
On other systems that don't support the saved user ID feature, you can
turn setuid access on and off by using <CODE>setreuid</CODE> to swap the real
and 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 a
game program has just started, and its real user ID is <CODE>jdoe</CODE> while
its effective user ID is <CODE>games</CODE>.  In this state, the game can
write 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 has
only <CODE>jdoe</CODE> access.  Another swap brings <CODE>games</CODE> back to
the effective user ID and restores access to the scores file.
<P>
In order to handle both kinds of systems, test for the saved user ID
feature 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 its
effective user ID.
<P>
This is part of a game program called <CODE>caber-toss</CODE> that
manipulates a file <TT>`scores'</TT> that should be writable only by the game
program itself.  The program assumes that its executable
file will be installed with the set-user-ID bit set and owned by the
same user as the <TT>`scores'</TT> file.  Typically, a system
administrator 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> on
it 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 changed
user ID.  This program is conditionalized so that it makes use of the
saved IDs feature if it is supported, and otherwise uses <CODE>setreuid</CODE>
to swap the effective and real user IDs.
<P>
<PRE>
#include &#60;stdio.h&#62;
#include &#60;sys/types.h&#62;
#include &#60;unistd.h&#62;
#include &#60;stdlib.h&#62;


/* Save the effective and real UIDs. */

static uid_t euid, ruid;


/* Restore the effective UID to its original value. */

void
do_setuid (void)
{
  int status;

#ifdef _POSIX_SAVED_IDS
  status = setuid (euid);
#else
  status = setreuid (ruid, euid);
#endif
  if (status &#60; 0) {
    fprintf (stderr, "Couldn't set uid.\n");
    exit (status);
    }
}


/* Set the effective UID to the real UID. */

void
undo_setuid (void)
{
  int status;

#ifdef _POSIX_SAVED_IDS
  status = setuid (ruid);
#else
  status = setreuid (euid, ruid);
#endif
  if (status &#60; 0) {
    fprintf (stderr, "Couldn't set uid.\n");
    exit (status);
    }
}

/* Main program. */

int
main (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 the
effective user ID back to the real user ID.  This is so that any other
file accesses that are performed while the user is playing the game use
the real user ID for determining permissions.  Only when the program
needs to open the scores file does it switch back to the original
effective user ID, like this:
<P>
<PRE>
/* Record the score. */

int
record_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 &#60; 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 and
minimizing 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 is
specific 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 in
combination with changing the effective user ID.  Don't let users of
your 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 (since
the program they execute depends on the user's <CODE>PATH</CODE> environment
variable).
<P>
If you must <CODE>exec</CODE> another program under a changed ID, specify an
absolute 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 it
with some other program.
<P>
<LI>
Only use the user ID controlling the resource in the part of the program
that actually uses that resource.  When you're finished with it, restore
the 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 files
besides the controlled resource, it should verify that the real user
would 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; it
uses 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 login
name of the user who is running a process, and the name of the user who
logged in the current session.  See also the function <CODE>getuid</CODE> and
friends (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 the
name of the user logged in on the controlling terminal of the process,
or a null pointer if this information cannot be determined.  The string
is statically allocated and might be overwritten on subsequent calls to
this 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 a
user 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 hold
at least <CODE>L_cuserid</CODE> characters; the string is returned in this
array.  Otherwise, a pointer to a string in a static area is returned.
This string is statically allocated and might be overwritten on
subsequent 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 to
store a user name.
<P>
These functions let your program identify positively the user who is
running or the user who logged in this session.  (These can differ when
setuid 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 cannot
do 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 flexible
precisely 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 + -