forked from lix-project/lix
* Move setuid stuff to libutil.
* Install libexpr header files.
This commit is contained in:
parent
e5a6c09b12
commit
bafc1690fc
|
@ -1,11 +1,12 @@
|
|||
pkglib_LTLIBRARIES = libexpr.la
|
||||
|
||||
libexpr_la_SOURCES = nixexpr.cc nixexpr.hh \
|
||||
eval.cc eval.hh primops.cc \
|
||||
lexer-tab.cc lexer-tab.hh parser-tab.cc parser-tab.hh \
|
||||
get-drvs.cc get-drvs.hh \
|
||||
attr-path.cc attr-path.hh \
|
||||
expr-to-xml.cc expr-to-xml.hh
|
||||
libexpr_la_SOURCES = \
|
||||
nixexpr.cc eval.cc primops.cc lexer-tab.cc parser-tab.cc \
|
||||
get-drvs.cc attr-path.cc expr-to-xml.cc
|
||||
|
||||
pkginclude_HEADERS = \
|
||||
nixexpr.hh eval.hh parser.hh lexer-tab.hh parser-tab.hh \
|
||||
get-drvs.hh attr-path.hh expr-to-xml.hh
|
||||
|
||||
libexpr_la_LIBADD = ../libutil/libutil.la ../libstore/libstore.la \
|
||||
../boost/format/libformat.la
|
||||
|
|
|
@ -207,139 +207,6 @@ static void initAndRun(int argc, char * * argv)
|
|||
}
|
||||
|
||||
|
||||
static bool haveSwitched;
|
||||
static uid_t savedUid, nixUid;
|
||||
static gid_t savedGid, nixGid;
|
||||
|
||||
|
||||
#if HAVE_SETRESUID
|
||||
#define _setuid(uid) setresuid(uid, uid, savedUid)
|
||||
#define _setgid(gid) setresgid(gid, gid, savedGid)
|
||||
#else
|
||||
/* Only works properly when run by root. */
|
||||
#define _setuid(uid) setuid(uid)
|
||||
#define _setgid(gid) setgid(gid)
|
||||
#endif
|
||||
|
||||
|
||||
SwitchToOriginalUser::SwitchToOriginalUser()
|
||||
{
|
||||
#if SETUID_HACK && HAVE_SETRESUID
|
||||
/* Temporarily switch the effective uid/gid back to the saved
|
||||
uid/gid (which is the uid/gid of the user that executed the Nix
|
||||
program; it's *not* the real uid/gid, since we changed that to
|
||||
the Nix user in switchToNixUser()). */
|
||||
if (haveSwitched) {
|
||||
if (setuid(savedUid) == -1)
|
||||
throw SysError(format("temporarily restoring uid to `%1%'") % savedUid);
|
||||
if (setgid(savedGid) == -1)
|
||||
throw SysError(format("temporarily restoring gid to `%1%'") % savedGid);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
SwitchToOriginalUser::~SwitchToOriginalUser()
|
||||
{
|
||||
#if SETUID_HACK && HAVE_SETRESUID
|
||||
/* Switch the effective uid/gid back to the Nix user. */
|
||||
if (haveSwitched) {
|
||||
if (setuid(nixUid) == -1)
|
||||
throw SysError(format("restoring uid to `%1%'") % nixUid);
|
||||
if (setgid(nixGid) == -1)
|
||||
throw SysError(format("restoring gid to `%1%'") % nixGid);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void switchToNixUser()
|
||||
{
|
||||
#if SETUID_HACK
|
||||
|
||||
/* Don't do anything if this is not a setuid binary. */
|
||||
if (getuid() == geteuid() && getgid() == getegid()) return;
|
||||
|
||||
/* Here we set the uid and gid to the Nix user and group,
|
||||
respectively, IF the current (real) user is a member of the Nix
|
||||
group. Otherwise we just drop all privileges. */
|
||||
|
||||
/* Lookup the Nix gid. */
|
||||
struct group * gr = getgrnam(NIX_GROUP);
|
||||
if (!gr) {
|
||||
cerr << format("missing group `%1%'\n") % NIX_GROUP;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Get the supplementary group IDs for the current user. */
|
||||
int maxGids = 512, nrGids;
|
||||
gid_t gids[maxGids];
|
||||
if ((nrGids = getgroups(maxGids, gids)) == -1) {
|
||||
cerr << format("unable to query gids\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* !!! Apparently it is unspecified whether getgroups() includes
|
||||
the effective gid. In that case the following test is always
|
||||
true *if* the program is installed setgid (which we do when we
|
||||
have setresuid()). On Linux this doesn't appear to be the
|
||||
case, but we should switch to the real gid before doing this
|
||||
test, and then switch back to the saved gid. */
|
||||
|
||||
/* Check that the current user is a member of the Nix group. */
|
||||
bool found = false;
|
||||
for (int i = 0; i < nrGids; ++i)
|
||||
if (gids[i] == gr->gr_gid) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
/* Not in the Nix group - drop all root/Nix privileges. */
|
||||
_setgid(getgid());
|
||||
_setuid(getuid());
|
||||
return;
|
||||
}
|
||||
|
||||
savedUid = getuid();
|
||||
savedGid = getgid();
|
||||
|
||||
/* Set the real, effective and saved gids to gr->gr_gid. Also
|
||||
make very sure that this succeeded. We switch the gid first
|
||||
because we cannot do it after we have dropped root uid. */
|
||||
nixGid = gr->gr_gid;
|
||||
if (_setgid(nixGid) != 0 || getgid() != nixGid || getegid() != nixGid) {
|
||||
cerr << format("unable to set gid to `%1%'\n") % NIX_GROUP;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Lookup the Nix uid. */
|
||||
struct passwd * pw = getpwnam(NIX_USER);
|
||||
if (!pw) {
|
||||
cerr << format("missing user `%1%'\n") % NIX_USER;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* This will drop all root privileges, setting the real, effective
|
||||
and saved uids to pw->pw_uid. Also make very sure that this
|
||||
succeeded.*/
|
||||
nixUid = pw->pw_uid;
|
||||
if (_setuid(nixUid) != 0 || getuid() != nixUid || geteuid() != nixUid) {
|
||||
cerr << format("unable to set uid to `%1%'\n") % NIX_USER;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* !!! for setuid operation, we should: 1) wipe the environment;
|
||||
2) verify file descriptors 0, 1, 2; 3) etc.
|
||||
See: http://www.daemon-systems.org/man/setuid.7.html
|
||||
*/
|
||||
|
||||
haveSwitched = true;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -850,4 +850,140 @@ bool string2Int(const string & s, int & n)
|
|||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
static bool haveSwitched;
|
||||
static uid_t savedUid, nixUid;
|
||||
static gid_t savedGid, nixGid;
|
||||
|
||||
|
||||
#if HAVE_SETRESUID
|
||||
#define _setuid(uid) setresuid(uid, uid, savedUid)
|
||||
#define _setgid(gid) setresgid(gid, gid, savedGid)
|
||||
#else
|
||||
/* Only works properly when run by root. */
|
||||
#define _setuid(uid) setuid(uid)
|
||||
#define _setgid(gid) setgid(gid)
|
||||
#endif
|
||||
|
||||
|
||||
SwitchToOriginalUser::SwitchToOriginalUser()
|
||||
{
|
||||
#if SETUID_HACK && HAVE_SETRESUID
|
||||
/* Temporarily switch the effective uid/gid back to the saved
|
||||
uid/gid (which is the uid/gid of the user that executed the Nix
|
||||
program; it's *not* the real uid/gid, since we changed that to
|
||||
the Nix user in switchToNixUser()). */
|
||||
if (haveSwitched) {
|
||||
if (setuid(savedUid) == -1)
|
||||
throw SysError(format("temporarily restoring uid to `%1%'") % savedUid);
|
||||
if (setgid(savedGid) == -1)
|
||||
throw SysError(format("temporarily restoring gid to `%1%'") % savedGid);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
SwitchToOriginalUser::~SwitchToOriginalUser()
|
||||
{
|
||||
#if SETUID_HACK && HAVE_SETRESUID
|
||||
/* Switch the effective uid/gid back to the Nix user. */
|
||||
if (haveSwitched) {
|
||||
if (setuid(nixUid) == -1)
|
||||
throw SysError(format("restoring uid to `%1%'") % nixUid);
|
||||
if (setgid(nixGid) == -1)
|
||||
throw SysError(format("restoring gid to `%1%'") % nixGid);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void switchToNixUser()
|
||||
{
|
||||
#if SETUID_HACK
|
||||
|
||||
/* Don't do anything if this is not a setuid binary. */
|
||||
if (getuid() == geteuid() && getgid() == getegid()) return;
|
||||
|
||||
/* Here we set the uid and gid to the Nix user and group,
|
||||
respectively, IF the current (real) user is a member of the Nix
|
||||
group. Otherwise we just drop all privileges. */
|
||||
|
||||
/* Lookup the Nix gid. */
|
||||
struct group * gr = getgrnam(NIX_GROUP);
|
||||
if (!gr) {
|
||||
cerr << format("missing group `%1%'\n") % NIX_GROUP;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Get the supplementary group IDs for the current user. */
|
||||
int maxGids = 512, nrGids;
|
||||
gid_t gids[maxGids];
|
||||
if ((nrGids = getgroups(maxGids, gids)) == -1) {
|
||||
cerr << format("unable to query gids\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* !!! Apparently it is unspecified whether getgroups() includes
|
||||
the effective gid. In that case the following test is always
|
||||
true *if* the program is installed setgid (which we do when we
|
||||
have setresuid()). On Linux this doesn't appear to be the
|
||||
case, but we should switch to the real gid before doing this
|
||||
test, and then switch back to the saved gid. */
|
||||
|
||||
/* Check that the current user is a member of the Nix group. */
|
||||
bool found = false;
|
||||
for (int i = 0; i < nrGids; ++i)
|
||||
if (gids[i] == gr->gr_gid) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
/* Not in the Nix group - drop all root/Nix privileges. */
|
||||
_setgid(getgid());
|
||||
_setuid(getuid());
|
||||
return;
|
||||
}
|
||||
|
||||
savedUid = getuid();
|
||||
savedGid = getgid();
|
||||
|
||||
/* Set the real, effective and saved gids to gr->gr_gid. Also
|
||||
make very sure that this succeeded. We switch the gid first
|
||||
because we cannot do it after we have dropped root uid. */
|
||||
nixGid = gr->gr_gid;
|
||||
if (_setgid(nixGid) != 0 || getgid() != nixGid || getegid() != nixGid) {
|
||||
cerr << format("unable to set gid to `%1%'\n") % NIX_GROUP;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Lookup the Nix uid. */
|
||||
struct passwd * pw = getpwnam(NIX_USER);
|
||||
if (!pw) {
|
||||
cerr << format("missing user `%1%'\n") % NIX_USER;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* This will drop all root privileges, setting the real, effective
|
||||
and saved uids to pw->pw_uid. Also make very sure that this
|
||||
succeeded.*/
|
||||
nixUid = pw->pw_uid;
|
||||
if (_setuid(nixUid) != 0 || getuid() != nixUid || geteuid() != nixUid) {
|
||||
cerr << format("unable to set uid to `%1%'\n") % NIX_USER;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* !!! for setuid operation, we should: 1) wipe the environment;
|
||||
2) verify file descriptors 0, 1, 2; 3) etc.
|
||||
See: http://www.daemon-systems.org/man/setuid.7.html
|
||||
*/
|
||||
|
||||
haveSwitched = true;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -246,15 +246,15 @@ string int2String(int n);
|
|||
bool string2Int(const string & s, int & n);
|
||||
|
||||
|
||||
/* !!! HACK HACK HACK - this should be in shared.hh, but it's to
|
||||
facilitate a quick hack - will remove this eventually (famous last
|
||||
words). */
|
||||
/* Setuid support. */
|
||||
struct SwitchToOriginalUser
|
||||
{
|
||||
SwitchToOriginalUser();
|
||||
~SwitchToOriginalUser();
|
||||
};
|
||||
|
||||
void switchToNixUser();
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue