Log message for revision 126699:
  Fixed:
  
  The change in 2.0.6 to set a user's supplemental groups broke common
  configurations in which the effective user was set via ``su`` or
  ``sudo -u`` prior to invoking zdaemon.
  
  Now, zdaemon doesn't set groups or the effective user if the
  effective user is already set to the configured user.
  

Changed:
  U   zdaemon/trunk/CHANGES.txt
  U   zdaemon/trunk/src/zdaemon/tests/testuser.py
  U   zdaemon/trunk/src/zdaemon/zdctl.py
  U   zdaemon/trunk/src/zdaemon/zdoptions.py

-=-
Modified: zdaemon/trunk/CHANGES.txt
===================================================================
--- zdaemon/trunk/CHANGES.txt   2012-06-08 17:20:55 UTC (rev 126698)
+++ zdaemon/trunk/CHANGES.txt   2012-06-08 17:52:02 UTC (rev 126699)
@@ -1,10 +1,22 @@
-===========
- Change log
-===========
+==========
+Change log
+==========
 
-3.0.0 (unreleased)
+3.0.1 (2012-06-08)
 ==================
 
+- Fixed:
+
+  The change in 2.0.6 to set a user's supplemental groups broke common
+  configurations in which the effective user was set via ``su`` or
+  ``sudo -u`` prior to invoking zdaemon.
+
+  Now, zdaemon doesn't set groups or the effective user if the
+  effective user is already set to the configured user.
+
+3.0.0 (2012-06-08)
+==================
+
 - Added an option, ``start-test-program`` to supply a test command to
   test whether the program managed by zdaemon is up and operational,
   rather than just running.  When starting a program, the start

Modified: zdaemon/trunk/src/zdaemon/tests/testuser.py
===================================================================
--- zdaemon/trunk/src/zdaemon/tests/testuser.py 2012-06-08 17:20:55 UTC (rev 
126698)
+++ zdaemon/trunk/src/zdaemon/tests/testuser.py 2012-06-08 17:52:02 UTC (rev 
126699)
@@ -96,10 +96,36 @@
 
     """
 
+def test_do_nothing_if_effective_user_is_configured_user():
+    """
+
+    >>> write('conf',
+    ... '''
+    ... <runner>
+    ...   program sleep 9
+    ...   user zope
+    ... </runner>
+    ... ''')
+
+    >>> with mock.patch('os.geteuid') as geteuid:
+    ...     geteuid.return_value = 99
+    ...     zdaemon.zdctl.main(['-C', 'conf', 'status'])
+    ...     os.geteuid.assert_called_with()
+    daemon manager not running
+
+    >>> import pwd, os, grp
+    >>> pwd.getpwnam.assert_called_with('zope')
+    >>> _ = grp.getgrall.assert_not_called()
+    >>> _ = os.setuid.assert_not_called()
+    >>> _ = os.setgid.assert_not_called()
+    >>> _ = os.setgroups.assert_not_called()
+
+    """
+
 def setUp(test):
     setupstack.setUpDirectory(test)
     getpwname = setupstack.context_manager(test, mock.patch('pwd.getpwnam'))
-    getpwname.return_value = O(pw_gid=5, pw_uid=99)
+    getpwname.return_value = O(pw_gid=5, pw_uid=99, pw_name='zope')
     setupstack.context_manager(test, mock.patch('os.geteuid')).return_value = 0
     setupstack.context_manager(test, mock.patch('grp.getgrall'))
     setupstack.context_manager(test, mock.patch('os.setgroups'))

Modified: zdaemon/trunk/src/zdaemon/zdctl.py
===================================================================
--- zdaemon/trunk/src/zdaemon/zdctl.py  2012-06-08 17:20:55 UTC (rev 126698)
+++ zdaemon/trunk/src/zdaemon/zdctl.py  2012-06-08 17:52:02 UTC (rev 126699)
@@ -166,15 +166,43 @@
             os.chown(directory, self.options.uid, self.options.gid)
 
     def set_uid(self):
-        if self.options.uid is None:
+        user = self.options.user
+        if user is None:
             return
-        uid = os.geteuid()
-        if uid != 0 and uid != self.options.uid:
-            self.options.usage("only root can use -u USER to change users")
-        os.setgid(self.options.gid)
-        os.setgroups(self.options.groups)
-        os.setuid(self.options.uid)
 
+        import pwd
+        try:
+            uid = int(user)
+        except ValueError:
+            try:
+                pwrec = pwd.getpwnam(user)
+            except KeyError:
+                self.options.usage("username %r not found" % user)
+            uid = pwrec.pw_uid
+        else:
+            try:
+                pwrec = pwd.getpwuid(uid)
+            except KeyError:
+                self.options.usage("uid %r not found" % user)
+
+        # See if we're already that user:
+        euid = os.geteuid()
+        if euid != 0:
+            if euid != uid:
+                self.options.usage("only root can use -u USER to change users")
+            return
+
+        # OK, we have to set user and groups:
+        os.setgid(pwrec.pw_gid)
+
+        import grp
+        user = pwrec.pw_name
+        os.setgroups(
+            sorted(g.gr_gid for g in grp.getgrall() # sort for tests
+                   if user in g.gr_mem)
+            )
+        os.setuid(uid)
+
     def emptyline(self):
         # We don't want a blank line to repeat the last command.
         # Showing status is a nice alternative.

Modified: zdaemon/trunk/src/zdaemon/zdoptions.py
===================================================================
--- zdaemon/trunk/src/zdaemon/zdoptions.py      2012-06-08 17:20:55 UTC (rev 
126698)
+++ zdaemon/trunk/src/zdaemon/zdoptions.py      2012-06-08 17:52:02 UTC (rev 
126699)
@@ -375,31 +375,7 @@
         self.add("directory", "runner.directory", "z:", "directory=",
                  existing_parent_directory)
 
-    def realize(self, *args, **kwds):
-        ZDOptions.realize(self, *args, **kwds)
 
-        # Additional checking of user option; set uid and gid
-        if self.user is not None:
-            import pwd, grp
-            try:
-                uid = int(self.user)
-            except ValueError:
-                try:
-                    pwrec = pwd.getpwnam(self.user)
-                except KeyError:
-                    self.usage("username %r not found" % self.user)
-                uid = pwrec.pw_uid
-            else:
-                try:
-                    pwrec = pwd.getpwuid(uid)
-                except KeyError:
-                    self.usage("uid %r not found" % self.user)
-            self.uid = uid
-            self.gid = pwrec.pw_gid
-            self.groups = sorted(g.gr_gid for g in grp.getgrall()
-                                 if self.user in g.gr_mem)
-
-
 # ZConfig datatype
 
 def list_of_ints(arg):

_______________________________________________
Zope-Checkins maillist  -  Zope-Checkins@zope.org
https://mail.zope.org/mailman/listinfo/zope-checkins

Reply via email to