Imported Upstream version 2.0
This commit is contained in:
parent
c89ccc3c74
commit
0841b5c7c7
165 changed files with 25440 additions and 4442 deletions
204
gl/idpriv-droptemp.c
Normal file
204
gl/idpriv-droptemp.c
Normal file
|
@ -0,0 +1,204 @@
|
|||
/* Dropping uid/gid privileges of the current process temporarily.
|
||||
Copyright (C) 2009-2013 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "idpriv.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* The privileged uid and gid that the process had earlier. */
|
||||
#if HAVE_GETUID
|
||||
static int saved_uid = -1;
|
||||
#endif
|
||||
#if HAVE_GETGID
|
||||
static int saved_gid = -1;
|
||||
#endif
|
||||
|
||||
int
|
||||
idpriv_temp_drop (void)
|
||||
{
|
||||
#if HAVE_GETEUID && HAVE_GETEGID && (HAVE_SETRESUID || HAVE_SETREUID) && (HAVE_SETRESGID || HAVE_SETREGID)
|
||||
int uid = getuid ();
|
||||
int gid = getgid ();
|
||||
|
||||
/* Find out about the privileged uid and gid at the first call. */
|
||||
if (saved_uid == -1)
|
||||
saved_uid = geteuid ();
|
||||
if (saved_gid == -1)
|
||||
saved_gid = getegid ();
|
||||
|
||||
/* Drop the gid privilege first, because in some cases the gid privilege
|
||||
cannot be dropped after the uid privilege has been dropped. */
|
||||
|
||||
/* This is for executables that have the setgid bit set. */
|
||||
# if HAVE_SETRESGID /* glibc, FreeBSD, OpenBSD, HP-UX */
|
||||
if (setresgid (-1, gid, saved_gid) < 0)
|
||||
return -1;
|
||||
# else /* Mac OS X, NetBSD, AIX, IRIX, Solaris >= 2.5, OSF/1, Cygwin */
|
||||
if (setregid (-1, gid) < 0)
|
||||
return -1;
|
||||
# endif
|
||||
|
||||
/* This is for executables that have the setuid bit set. */
|
||||
# if HAVE_SETRESUID /* glibc, FreeBSD, OpenBSD, HP-UX */
|
||||
/* See <http://www.usenix.org/events/sec02/full_papers/chen/chen.pdf>
|
||||
figure 14. */
|
||||
if (setresuid (-1, uid, saved_uid) < 0)
|
||||
return -1;
|
||||
# else /* Mac OS X, NetBSD, AIX, IRIX, Solaris >= 2.5, OSF/1, Cygwin */
|
||||
if (setreuid (-1, uid) < 0)
|
||||
return -1;
|
||||
# endif
|
||||
|
||||
/* Verify that the privileges have really been dropped.
|
||||
This verification is here for security reasons. Doesn't matter if it
|
||||
takes a couple of system calls.
|
||||
When the verification fails, it indicates that we need to use different
|
||||
API in the code above. Therefore 'abort ()', not 'return -1'. */
|
||||
# if HAVE_GETRESUID /* glibc, FreeBSD, OpenBSD, HP-UX */
|
||||
{
|
||||
uid_t real;
|
||||
uid_t effective;
|
||||
uid_t saved;
|
||||
if (getresuid (&real, &effective, &saved) < 0
|
||||
|| real != uid
|
||||
|| effective != uid
|
||||
|| saved != saved_uid)
|
||||
abort ();
|
||||
}
|
||||
# else
|
||||
# if HAVE_GETEUID
|
||||
if (geteuid () != uid)
|
||||
abort ();
|
||||
# endif
|
||||
if (getuid () != uid)
|
||||
abort ();
|
||||
# endif
|
||||
# if HAVE_GETRESGID /* glibc, FreeBSD, OpenBSD, HP-UX */
|
||||
{
|
||||
uid_t real;
|
||||
uid_t effective;
|
||||
uid_t saved;
|
||||
if (getresgid (&real, &effective, &saved) < 0
|
||||
|| real != gid
|
||||
|| effective != gid
|
||||
|| saved != saved_gid)
|
||||
abort ();
|
||||
}
|
||||
# else
|
||||
# if HAVE_GETEGID
|
||||
if (getegid () != gid)
|
||||
abort ();
|
||||
# endif
|
||||
if (getgid () != gid)
|
||||
abort ();
|
||||
# endif
|
||||
|
||||
return 0;
|
||||
#else
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
idpriv_temp_restore (void)
|
||||
{
|
||||
#if HAVE_GETEUID && HAVE_GETEGID && (HAVE_SETRESUID || HAVE_SETREUID) && (HAVE_SETRESGID || HAVE_SETREGID)
|
||||
int uid = getuid ();
|
||||
int gid = getgid ();
|
||||
|
||||
if (saved_uid == -1 || saved_gid == -1)
|
||||
/* Caller error: idpriv_temp_drop was never invoked. */
|
||||
abort ();
|
||||
|
||||
/* Acquire the gid privilege last, because in some cases the gid privilege
|
||||
cannot be acquired before the uid privilege has been acquired. */
|
||||
|
||||
/* This is for executables that have the setuid bit set. */
|
||||
# if HAVE_SETRESUID /* glibc, FreeBSD, OpenBSD, HP-UX */
|
||||
/* See <http://www.usenix.org/events/sec02/full_papers/chen/chen.pdf>
|
||||
figure 14. */
|
||||
if (setresuid (-1, saved_uid, -1) < 0)
|
||||
return -1;
|
||||
# else /* Mac OS X, NetBSD, AIX, IRIX, Solaris >= 2.5, OSF/1, Cygwin */
|
||||
if (setreuid (-1, saved_uid) < 0)
|
||||
return -1;
|
||||
# endif
|
||||
|
||||
/* This is for executables that have the setgid bit set. */
|
||||
# if HAVE_SETRESGID /* glibc, FreeBSD, OpenBSD, HP-UX */
|
||||
if (setresgid (-1, saved_gid, -1) < 0)
|
||||
return -1;
|
||||
# else /* Mac OS X, NetBSD, AIX, IRIX, Solaris >= 2.5, OSF/1, Cygwin */
|
||||
if (setregid (-1, saved_gid) < 0)
|
||||
return -1;
|
||||
# endif
|
||||
|
||||
/* Verify that the privileges have really been acquired.
|
||||
This verification is here for security reasons. Doesn't matter if it
|
||||
takes a couple of system calls.
|
||||
When the verification fails, it indicates that we need to use different
|
||||
API in the code above. Therefore 'abort ()', not 'return -1'. */
|
||||
# if HAVE_GETRESUID /* glibc, FreeBSD, OpenBSD, HP-UX */
|
||||
{
|
||||
uid_t real;
|
||||
uid_t effective;
|
||||
uid_t saved;
|
||||
if (getresuid (&real, &effective, &saved) < 0
|
||||
|| real != uid
|
||||
|| effective != saved_uid
|
||||
|| saved != saved_uid)
|
||||
abort ();
|
||||
}
|
||||
# else
|
||||
# if HAVE_GETEUID
|
||||
if (geteuid () != saved_uid)
|
||||
abort ();
|
||||
# endif
|
||||
if (getuid () != uid)
|
||||
abort ();
|
||||
# endif
|
||||
# if HAVE_GETRESGID /* glibc, FreeBSD, OpenBSD, HP-UX */
|
||||
{
|
||||
uid_t real;
|
||||
uid_t effective;
|
||||
uid_t saved;
|
||||
if (getresgid (&real, &effective, &saved) < 0
|
||||
|| real != gid
|
||||
|| effective != saved_gid
|
||||
|| saved != saved_gid)
|
||||
abort ();
|
||||
}
|
||||
# else
|
||||
# if HAVE_GETEGID
|
||||
if (getegid () != saved_gid)
|
||||
abort ();
|
||||
# endif
|
||||
if (getgid () != gid)
|
||||
abort ();
|
||||
# endif
|
||||
|
||||
return 0;
|
||||
#else
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
#endif
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue