about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2006-11-29T21·06+0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2006-11-29T21·06+0000
commit71e867c5f5ee2c188244da33366e506935abffb7 (patch)
tree9ebf9f95e1af9f70f368a721ad1fb43493a75be2
parentc6a97e3b74289fdc8e57189212a0db3d0e6896e0 (diff)
* Remove --enable-setuid, --with-nix-user and --with-nix-group.
  Rather, setuid support is now always compiled in (at least on
  platforms that have the setresuid system call, e.g., Linux and
  FreeBSD), but it must enabled by chowning/chmodding the Nix
  binaries.

-rw-r--r--Makefile.am10
-rw-r--r--configure.ac22
-rw-r--r--src/Makefile.am11
-rw-r--r--src/libutil/util.cc71
4 files changed, 53 insertions, 61 deletions
diff --git a/Makefile.am b/Makefile.am
index 5734cbd79d..911f308013 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -20,10 +20,11 @@ install-data-local: init-state
 	fi
 
 if INIT_STATE
-if SETUID_HACK
-INIT_FLAGS = -g @NIX_GROUP@ -o @NIX_USER@
-GROUP_WRITABLE = -m 775
-endif
+
+# For setuid operation, you can enable the following:
+# INIT_FLAGS = -g @NIX_GROUP@ -o @NIX_USER@
+# GROUP_WRITABLE = -m 775
+
 init-state:
 	$(INSTALL) $(INIT_FLAGS) -d $(DESTDIR)$(localstatedir)/nix
 	$(INSTALL) $(INIT_FLAGS) -d $(DESTDIR)$(localstatedir)/nix/db
@@ -40,6 +41,7 @@ init-state:
 	$(INSTALL) $(INIT_FLAGS) -m 1777 -d $(DESTDIR)$(prefix)/store
 	$(INSTALL) $(INIT_FLAGS) $(GROUP_WRITABLE) -d $(DESTDIR)$(localstatedir)/nix/manifests
 #	$(bindir)/nix-store --init
+
 else
 init-state:
 endif
diff --git a/configure.ac b/configure.ac
index 37ebe06b5c..b5c0e61b59 100644
--- a/configure.ac
+++ b/configure.ac
@@ -237,33 +237,13 @@ AM_CONDITIONAL(INIT_STATE, test "$init_state" = "yes")
 
 
 # Setuid installations.
-AC_ARG_ENABLE(setuid, AC_HELP_STRING([--enable-setuid],
-  [install Nix setuid]),
-  setuid_hack=$enableval, setuid_hack=no)
-AM_CONDITIONAL(SETUID_HACK, test "$setuid_hack" = "yes")
-if test "$setuid_hack" = "yes"; then
-    AC_DEFINE(SETUID_HACK, 1, [whether to install Nix setuid])
-fi
-
 AC_CHECK_FUNC(setresuid, [HAVE_SETRESUID=1], [HAVE_SETRESUID=])
 AM_CONDITIONAL(HAVE_SETRESUID, test "$HAVE_SETRESUID" = "1")
 if test "$HAVE_SETRESUID" = "1"; then
     AC_DEFINE(HAVE_SETRESUID, 1, [whether we have setresuid()])
 fi
 
-AC_ARG_WITH(nix-user, AC_HELP_STRING([--with-nix-user=USER],
-  [user for Nix setuid binaries]),
-  NIX_USER=$withval, NIX_USER=nix)
-AC_SUBST(NIX_USER)
-AC_DEFINE_UNQUOTED(NIX_USER, ["$NIX_USER"], [Nix user])
-                                                      
-AC_ARG_WITH(nix-group, AC_HELP_STRING([--with-nix-group=USER],
-  [group for Nix setuid binaries]),
-  NIX_GROUP=$withval, NIX_GROUP=nix)
-AC_SUBST(NIX_GROUP)
-AC_DEFINE_UNQUOTED(NIX_GROUP, ["$NIX_GROUP"], [Nix group])
-
-                                                                                                            
+
 # This is needed if ATerm, Berkeley DB or bzip2 are static libraries,
 # and the Nix libraries are dynamic.
 if test "$(uname)" = "Darwin"; then
diff --git a/src/Makefile.am b/src/Makefile.am
index 1cdbc558ae..2bf789fd3b 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -3,13 +3,4 @@ SUBDIRS = bin2c boost libutil libstore libmain nix-store nix-hash \
 
 EXTRA_DIST = aterm-helper.pl
 
-SETUID_PROGS = nix-store nix-instantiate nix-env
-install-exec-hook:
-if SETUID_HACK
-if HAVE_SETRESUID
-	cd $(DESTDIR)$(bindir) && chown @NIX_USER@ $(SETUID_PROGS) \
-	  && chgrp @NIX_GROUP@ $(SETUID_PROGS) && chmod ug+s $(SETUID_PROGS)
-else
-	cd $(DESTDIR)$(bindir) && chown root $(SETUID_PROGS) && chmod u+s $(SETUID_PROGS)
-endif
-endif
+#SETUID_PROGS = nix-store nix-instantiate nix-env
diff --git a/src/libutil/util.cc b/src/libutil/util.cc
index f80fb7dbf7..8bd15a9aef 100644
--- a/src/libutil/util.cc
+++ b/src/libutil/util.cc
@@ -911,7 +911,7 @@ static gid_t savedGid, nixGid;
 
 SwitchToOriginalUser::SwitchToOriginalUser()
 {
-#if SETUID_HACK && HAVE_SETRESUID
+#if 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
@@ -928,7 +928,7 @@ SwitchToOriginalUser::SwitchToOriginalUser()
 
 SwitchToOriginalUser::~SwitchToOriginalUser()
 {
-#if SETUID_HACK && HAVE_SETRESUID
+#if HAVE_SETRESUID
     /* Switch the effective uid/gid back to the Nix user. */
     if (haveSwitched) {
         if (setuid(nixUid) == -1)
@@ -942,21 +942,43 @@ SwitchToOriginalUser::~SwitchToOriginalUser()
 
 void switchToNixUser()
 {
-#if SETUID_HACK
+    fprintf(stderr, "real = %d/%d, effective = %d/%d\n",
+        getuid(), geteuid(), getgid(), getegid());
+
+    /* Note: we require setresuid for now since I don't want to think
+       to deeply about whether this works on systems that don't have
+       setresuid.  It's already hard enough. */
+      
+#if HAVE_SETRESUID
+
+    /* Setuid Nix operation works as follows:
 
+       - The Nix binaries are owned by a Nix user and group, e.g.,
+         nix.nix, and must setuid and setgid, e.g.,
+
+         rwsrwsr-x nix.nix
+
+       - Users (say alice.users) are only allowed to run (most) Nix
+         operations if they are in the Nix group.  If they aren't,
+         some read-only operations (like nix-env -qa) may still work.
+         
+       - We run mostly under the Nix user/group, but we switch back to
+         the calling user/group for some work, like reading Nix
+         expressions.
+
+    */
+    
+    
     /* 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) {
-        std::cerr << format("missing group `%1%'\n") % NIX_GROUP;
-        exit(1);
-    }
+       group.  (The Nix group is the group of the current executable,
+       i.e., the current effective gid.)  Otherwise we just drop all
+       privileges. */
+
+    nixGid = geteuid();
 
     /* Get the supplementary group IDs for the current user. */
     int maxGids = 512, nrGids;
@@ -976,7 +998,7 @@ void switchToNixUser()
     /* 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) {
+        if (gids[i] == nixGid) {
             found = true;
             break;
         }
@@ -988,31 +1010,29 @@ void switchToNixUser()
         return;
     }
 
+    /* Save the uid/gid of the caller so the we can switch back to
+       that uid/gid for temporary work, like accessing files, in
+       SwitchToOriginaluser. */
     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;
+    /* Set the real and effective gids to nixGid.  Also make very sure
+       that this succeeded.  We switch the gid first because we cannot
+       do it after we have dropped root uid. */
     if (_setgid(nixGid) != 0 || getgid() != nixGid || getegid() != nixGid) {
-        std::cerr << format("unable to set gid to `%1%'\n") % NIX_GROUP;
+        std::cerr << format("unable to set gid to `%1%'\n") % nixGid;
         exit(1);
     }
 
-    /* Lookup the Nix uid. */
-    struct passwd * pw = getpwnam(NIX_USER);
-    if (!pw) {
-        std::cerr << format("missing user `%1%'\n") % NIX_USER;
-        exit(1);
-    }
+    /* The Nix uid is the effective uid of the owner of the current
+       executable, i.e., the current effective uid. */
+    nixUid = geteuid();
 
     /* 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) {
-        std::cerr << format("unable to set uid to `%1%'\n") % NIX_USER;
+        std::cerr << format("unable to set uid to `%1%'\n") % nixUid;
         exit(1);
     }
 
@@ -1022,7 +1042,6 @@ void switchToNixUser()
     */
 
     haveSwitched = true;
-    
 #endif
 }