[svn] commit: r2277 - in /branches/trac180: ChangeLog src/bin/bind10/bind10.py.in src/bin/bind10/tests/args_test.py src/bin/bind10/tests/bind10_test.in

BIND 10 source code commits bind10-changes at lists.isc.org
Fri Jun 25 02:23:26 UTC 2010


Author: shane
Date: Fri Jun 25 02:23:26 2010
New Revision: 2277

Log:
Initial support for setuid. Will be replaced later when the
PriviligedSocketCreator arrives.

See Trac ticket #180 for more details:

    https://bind10.isc.org/ticket/180

Added:
    branches/trac180/src/bin/bind10/tests/args_test.py
Modified:
    branches/trac180/ChangeLog
    branches/trac180/src/bin/bind10/bind10.py.in
    branches/trac180/src/bin/bind10/tests/bind10_test.in

Modified: branches/trac180/ChangeLog
==============================================================================
--- branches/trac180/ChangeLog (original)
+++ branches/trac180/ChangeLog Fri Jun 25 02:23:26 2010
@@ -1,3 +1,8 @@
+  XX.   [func]      shane
+    Added initial support for setuid(). This will be replaced in the
+    future, but for now provides a reasonable starting point.
+    (Trac #180, svn rYYYY)
+
   58.	[bug]		jinmei
 	Worked around an interaction issue between ASIO and standard C++
 	library headers.  Without this ASIO didn't work: sometimes the

Modified: branches/trac180/src/bin/bind10/bind10.py.in
==============================================================================
--- branches/trac180/src/bin/bind10/bind10.py.in (original)
+++ branches/trac180/src/bin/bind10/bind10.py.in Fri Jun 25 02:23:26 2010
@@ -57,6 +57,9 @@
 import select
 import random
 from optparse import OptionParser, OptionValueError
+import io
+import pwd
+import posix
 
 import isc.cc
 
@@ -114,15 +117,21 @@
     dev_null = open(os.devnull, "w")
 
     def __init__(self, name, args, env={}, dev_null_stdout=False,
-                 dev_null_stderr=False):
+                 dev_null_stderr=False, uid=None):
         self.name = name 
         self.args = args
         self.env = env
         self.dev_null_stdout = dev_null_stdout
         self.dev_null_stderr = dev_null_stderr
         self.restart_schedule = RestartSchedule()
+        self.uid = uid
         self._spawn()
 
+    def _setuid(self):
+        if not self.uid is None:
+            sys.stderr.write("setting uid\n")
+            posix.setuid(self.uid)
+            sys.stderr.write("set it\n")
 
     def _spawn(self):
         if self.dev_null_stdout:
@@ -145,7 +154,8 @@
                                         stdout=spawn_stdout,
                                         stderr=spawn_stderr,
                                         close_fds=True,
-                                        env=spawn_env,)
+                                        env=spawn_env,
+                                        preexec_fn=self._setuid)
         self.pid = self.process.pid
         self.restart_schedule.set_run_start_time()
 
@@ -155,7 +165,8 @@
 class BoB:
     """Boss of BIND class."""
     
-    def __init__(self, msgq_socket_file=None, auth_port=5300, verbose=False):
+    def __init__(self, msgq_socket_file=None, auth_port=5300, verbose=False,
+                 setuid=None):
         """Initialize the Boss of BIND. This is a singleton (only one
         can run).
         
@@ -171,6 +182,7 @@
         self.processes = {}
         self.dead_processes = {}
         self.runnable = False
+        self.uid = setuid
 
     def config_handler(self, new_config):
         if self.verbose:
@@ -225,12 +237,13 @@
                 sys.stdout.write("[bind10] Starting b10-msgq\n")
         try:
             c_channel = ProcessInfo("b10-msgq", ["b10-msgq"], c_channel_env,
-                                    True, not self.verbose)
+                                    True, not self.verbose, uid=self.uid)
         except Exception as e:
             return "Unable to start b10-msgq; " + str(e)
         self.processes[c_channel.pid] = c_channel
         if self.verbose:
-            sys.stdout.write("[bind10] Started b10-msgq (PID %d)\n" % c_channel.pid)
+            sys.stdout.write("[bind10] Started b10-msgq (PID %d)\n" % 
+                             c_channel.pid)
 
         # now connect to the c-channel
         cc_connect_start = time.time()
@@ -250,7 +263,7 @@
             sys.stdout.write("[bind10] Starting b10-cfgmgr\n")
         try:
             bind_cfgd = ProcessInfo("b10-cfgmgr", ["b10-cfgmgr"],
-                                    c_channel_env)
+                                    c_channel_env, uid=self.uid)
         except Exception as e:
             c_channel.process.kill()
             return "Unable to start b10-cfgmgr; " + str(e)
@@ -271,23 +284,6 @@
         self.ccs.start()
         if self.verbose:
             sys.stdout.write("[bind10] ccsession started\n")
-
-        # start the xfrout before auth-server, to make sure every xfr-query can
-        # be processed properly.
-        xfrout_args = ['b10-xfrout']
-        if self.verbose:
-            sys.stdout.write("[bind10] Starting b10-xfrout\n")
-            xfrout_args += ['-v']
-        try:
-            xfrout = ProcessInfo("b10-xfrout", xfrout_args, 
-                                 c_channel_env )
-        except Exception as e:
-            c_channel.process.kill()
-            bind_cfgd.process.kill()
-            return "Unable to start b10-xfrout; " + str(e)
-        self.processes[xfrout.pid] = xfrout
-        if self.verbose:
-            sys.stdout.write("[bind10] Started b10-xfrout (PID %d)\n" % xfrout.pid)
 
         # start b10-auth
         # XXX: this must be read from the configuration manager in the future
@@ -307,6 +303,28 @@
         self.processes[auth.pid] = auth
         if self.verbose:
             sys.stdout.write("[bind10] Started b10-auth (PID %d)\n" % auth.pid)
+
+        # everything after the authoritative server can run as non-root
+        if not self.uid is None:
+            posix.setuid(self.uid)
+
+        # start the xfrout before auth-server, to make sure every xfr-query can
+        # be processed properly.
+        xfrout_args = ['b10-xfrout']
+        if self.verbose:
+            sys.stdout.write("[bind10] Starting b10-xfrout\n")
+            xfrout_args += ['-v']
+        try:
+            xfrout = ProcessInfo("b10-xfrout", xfrout_args, 
+                                 c_channel_env )
+        except Exception as e:
+            c_channel.process.kill()
+            bind_cfgd.process.kill()
+            return "Unable to start b10-xfrout; " + str(e)
+        self.processes[xfrout.pid] = xfrout
+        if self.verbose:
+            sys.stdout.write("[bind10] Started b10-xfrout (PID %d)\n" % 
+                             xfrout.pid)
 
         # start b10-xfrin
         xfrin_args = ['b10-xfrin']
@@ -324,7 +342,8 @@
             return "Unable to start b10-xfrin; " + str(e)
         self.processes[xfrind.pid] = xfrind
         if self.verbose:
-            sys.stdout.write("[bind10] Started b10-xfrin (PID %d)\n" % xfrind.pid)
+            sys.stdout.write("[bind10] Started b10-xfrin (PID %d)\n" % 
+                             xfrind.pid)
 
         # start the b10-cmdctl
         # XXX: we hardcode port 8080
@@ -344,7 +363,8 @@
             return "Unable to start b10-cmdctl; " + str(e)
         self.processes[cmd_ctrld.pid] = cmd_ctrld
         if self.verbose:
-            sys.stdout.write("[bind10] Started b10-cmdctl (PID %d)\n" % cmd_ctrld.pid)
+            sys.stdout.write("[bind10] Started b10-cmdctl (PID %d)\n" % 
+                             cmd_ctrld.pid)
 
         self.runnable = True
 
@@ -439,7 +459,8 @@
         next_restart = None
         # if we're shutting down, then don't restart
         if not self.runnable:
-            return next_restart
+#            return next_restart
+            return 0
         # otherwise look through each dead process and try to restart
         still_dead = {}
         now = time.time()
@@ -510,6 +531,10 @@
 def main():
     global options
     global boss_of_bind
+    # Enforce line buffering on stdout, even when not a TTY
+    sys.stdout = io.TextIOWrapper(sys.stdout.detach(), line_buffering=True)
+
+
     # Parse any command-line options.
     parser = OptionParser(version=__version__)
     parser.add_option("-v", "--verbose", dest="verbose", action="store_true",
@@ -520,7 +545,34 @@
     parser.add_option("-m", "--msgq-socket-file", dest="msgq_socket_file",
                       type="string", default=None,
                       help="UNIX domain socket file the b10-msgq daemon will use")
+    parser.add_option("-u", "--user", dest="user",
+                      type="string", default=None,
+                      help="Change user after startup (must run as root)")
     (options, args) = parser.parse_args()
+    if args:
+        parser.print_help()
+        sys.exit(1)
+
+    # Check user ID.
+    setuid = None
+    if options.user:
+        try:
+            pw_ent = pwd.getpwuid(int(options.user))
+            setuid = pw_ent.pw_uid
+        except ValueError:
+            pass
+        except KeyError:
+            pass
+
+        try:
+            pw_ent = pwd.getpwnam(options.user)
+            setuid = pw_ent.pw_uid
+        except KeyError:
+            pass
+
+        if setuid is None:
+            sys.stderr.write("bind10: invalid user: '%s'\n" % options.user)
+            sys.exit(1)
 
     # Announce startup.
     if options.verbose:
@@ -543,11 +595,12 @@
 
     # Go bob!
     boss_of_bind = BoB(options.msgq_socket_file, int(options.auth_port),
-                       options.verbose)
+                       options.verbose, setuid)
     startup_result = boss_of_bind.startup()
     if startup_result:
         sys.stderr.write("[bind10] Error on startup: %s\n" % startup_result)
         sys.exit(1)
+    sys.stdout.write("[bind10] BIND 10 started\n")
 
     # In our main loop, we check for dead processes or messages 
     # on the c-channel.
@@ -584,6 +637,7 @@
     # shutdown
     signal.signal(signal.SIGCHLD, signal.SIG_DFL)
     boss_of_bind.shutdown()
+    sys.exit(0)
 
 if __name__ == "__main__":
     main()

Modified: branches/trac180/src/bin/bind10/tests/bind10_test.in
==============================================================================
--- branches/trac180/src/bin/bind10/tests/bind10_test.in (original)
+++ branches/trac180/src/bin/bind10/tests/bind10_test.in Fri Jun 25 02:23:26 2010
@@ -28,4 +28,5 @@
 
 cd ${BIND10_PATH}/tests
 exec ${PYTHON_EXEC} -O bind10_test.py $*
+exec ${PYTHON_EXEC} -O args_test.py $*
 




More information about the bind10-changes mailing list