def exchange_ping(self): try: # exchange "ready" messages reply = self.send_recv((Message.PING.value, )) success = reply[0] == Message.PONG except Exception as e: LOG.exception( _LE('Error while sending initial PING to privsep: %s'), e) success = False if not success: msg = _('Privsep daemon failed to start') LOG.critical(msg) raise FailedToDropPrivileges(msg)
def exchange_ping(self): try: # exchange "ready" messages reply = self.send_recv((Message.PING.value,)) success = reply[0] == Message.PONG except Exception as e: LOG.exception( _LE('Error while sending initial PING to privsep: %s'), e) success = False if not success: msg = _('Privsep daemon failed to start') LOG.critical(msg) raise FailedToDropPrivileges(msg)
def helper_main(): """Start privileged process, serving requests over a Unix socket.""" cfg.CONF.register_cli_opts([ cfg.StrOpt('privsep_context', required=True), cfg.StrOpt('privsep_sock_path', required=True), ]) logging.register_options(cfg.CONF) cfg.CONF(args=sys.argv[1:], project='privsep') logging.setup(cfg.CONF, 'privsep') # We always log to stderr. Replace the root logger we just set up. replace_logging(pylogging.StreamHandler(sys.stderr)) LOG.info(_LI('privsep daemon starting')) context = importutils.import_class(cfg.CONF.privsep_context) from oslo_privsep import priv_context # Avoid circular import if not isinstance(context, priv_context.PrivContext): LOG.fatal( _LE('--privsep_context must be the (python) name of a ' 'PrivContext object')) sock = socket.socket(socket.AF_UNIX) sock.connect(cfg.CONF.privsep_sock_path) set_cloexec(sock) channel = comm.ServerChannel(sock) # Channel is set up, so fork off daemon "in the background" and exit if os.fork() != 0: # parent return # child # Note we don't move into a new process group/session like a # regular daemon might, since we _want_ to remain associated with # the originating (unprivileged) process. try: Daemon(channel, context).run() except Exception as e: LOG.exception(e) sys.exit(str(e)) LOG.debug('privsep daemon exiting') sys.exit(0)
def helper_main(): """Start privileged process, serving requests over a Unix socket.""" cfg.CONF.register_cli_opts([ cfg.StrOpt('privsep_context', required=True), cfg.StrOpt('privsep_sock_path', required=True), ]) logging.register_options(cfg.CONF) cfg.CONF(args=sys.argv[1:], project='privsep') logging.setup(cfg.CONF, 'privsep') # We always log to stderr. Replace the root logger we just set up. replace_logging(pylogging.StreamHandler(sys.stderr)) LOG.info(_LI('privsep daemon starting')) context = importutils.import_class(cfg.CONF.privsep_context) from oslo_privsep import priv_context # Avoid circular import if not isinstance(context, priv_context.PrivContext): LOG.fatal(_LE('--privsep_context must be the (python) name of a ' 'PrivContext object')) sock = socket.socket(socket.AF_UNIX) sock.connect(cfg.CONF.privsep_sock_path) set_cloexec(sock) channel = comm.ServerChannel(sock) # Channel is set up, so fork off daemon "in the background" and exit if os.fork() != 0: # parent return # child # Note we don't move into a new process group/session like a # regular daemon might, since we _want_ to remain associated with # the originating (unprivileged) process. try: Daemon(channel, context).run() except Exception as e: LOG.exception(e) sys.exit(str(e)) LOG.debug('privsep daemon exiting') sys.exit(0)
def __init__(self, context): """Start privsep daemon using exec() Uses sudo/rootwrap to gain privileges. """ listen_sock = socket.socket(socket.AF_UNIX) # Note we listen() on the unprivileged side, and connect to it # from the privileged process. This means there is no exposed # attack point on the privileged side. # NB: Permissions on sockets are not checked on some (BSD) Unices # so create socket in a private directory for safety. Privsep # daemon will (initially) be running as root, so will still be # able to connect to sock path. tmpdir = tempfile.mkdtemp() # NB: created with 0700 perms try: sockpath = os.path.join(tmpdir, 'privsep.sock') listen_sock.bind(sockpath) listen_sock.listen(1) cmd = self._helper_command(context, sockpath) LOG.info(_LI('Running privsep helper: %s'), cmd) proc = subprocess.Popen(cmd, shell=False, stderr=_fd_logger()) if proc.wait() != 0: msg = (_LE('privsep helper command exited non-zero (%s)') % proc.returncode) LOG.critical(msg) raise FailedToDropPrivileges(msg) LOG.info(_LI('Spawned new privsep daemon via rootwrap')) sock, _addr = listen_sock.accept() LOG.debug('Accepted privsep connection to %s', sockpath) finally: # Don't need listen_sock anymore, so clean up. listen_sock.close() try: os.unlink(sockpath) except OSError as e: if e.errno != errno.ENOENT: raise os.rmdir(tmpdir) super(RootwrapClientChannel, self).__init__(sock)
def __init__(self, context): """Start privsep daemon using exec() Uses sudo/rootwrap to gain privileges. """ listen_sock = socket.socket(socket.AF_UNIX) # Note we listen() on the unprivileged side, and connect to it # from the privileged process. This means there is no exposed # attack point on the privileged side. # NB: Permissions on sockets are not checked on some (BSD) Unices # so create socket in a private directory for safety. Privsep # daemon will (initially) be running as root, so will still be # able to connect to sock path. tmpdir = tempfile.mkdtemp() # NB: created with 0700 perms try: sockpath = os.path.join(tmpdir, 'privsep.sock') listen_sock.bind(sockpath) listen_sock.listen(1) cmd = context.helper_command(sockpath) LOG.info(_LI('Running privsep helper: %s'), cmd) proc = subprocess.Popen(cmd, shell=False, stderr=_fd_logger()) if proc.wait() != 0: msg = (_LE('privsep helper command exited non-zero (%s)') % proc.returncode) LOG.critical(msg) raise FailedToDropPrivileges(msg) LOG.info(_LI('Spawned new privsep daemon via rootwrap')) sock, _addr = listen_sock.accept() LOG.debug('Accepted privsep connection to %s', sockpath) finally: # Don't need listen_sock anymore, so clean up. listen_sock.close() try: os.unlink(sockpath) except OSError as e: if e.errno != errno.ENOENT: raise os.rmdir(tmpdir) super(RootwrapClientChannel, self).__init__(sock)
def set_client_mode(self, enabled): if enabled and sys.platform == 'win32': raise RuntimeError( _LE("Enabling the client_mode is not currently " "supported on Windows.")) self.client_mode = enabled
def __init__(self, context): """Start privsep daemon using exec() Uses sudo/rootwrap to gain privileges. """ # We need to be able to reconstruct the context object in the new # python process we'll get after rootwrap/sudo. This means we # need to construct the context object and store it somewhere # globally accessible, and then use that python name to find it # again in the new python interpreter. Yes, it's all a bit # clumsy, and none of it is required when using the fork-based # alternative above. # These asserts here are just attempts to catch errors earlier. # TODO(gus): Consider replacing with setuptools entry_points. assert context.pypath is not None, ( 'RootwrapClientChannel requires priv_context ' 'pypath to be specified') assert importutils.import_class(context.pypath) is context, ( 'RootwrapClientChannel requires priv_context pypath ' 'for context object') listen_sock = socket.socket(socket.AF_UNIX) # Note we listen() on the unprivileged side, and connect to it # from the privileged process. This means there is no exposed # attack point on the privileged side. # NB: Permissions on sockets are not checked on some (BSD) Unices # so create socket in a private directory for safety. Privsep # daemon will (initially) be running as root, so will still be # able to connect to sock path. tmpdir = tempfile.mkdtemp() # NB: created with 0700 perms try: sockpath = os.path.join(tmpdir, 'privsep.sock') listen_sock.bind(sockpath) listen_sock.listen(1) cmd = shlex.split(context.conf.helper_command) + [ '--privsep_context', context.pypath, '--privsep_sock_path', sockpath] LOG.info(_LI('Running privsep helper: %s'), cmd) proc = subprocess.Popen(cmd, shell=False, stderr=_fd_logger()) if proc.wait() != 0: msg = (_LE('privsep helper command exited non-zero (%s)') % proc.returncode) LOG.critical(msg) raise FailedToDropPrivileges(msg) LOG.info(_LI('Spawned new privsep daemon via rootwrap')) sock, _addr = listen_sock.accept() LOG.debug('Accepted privsep connection to %s', sockpath) finally: # Don't need listen_sock anymore, so clean up. listen_sock.close() try: os.unlink(sockpath) except OSError as e: if e.errno != errno.ENOENT: raise os.rmdir(tmpdir) super(RootwrapClientChannel, self).__init__(sock)
def set_client_mode(self, enabled): if enabled and sys.platform == "win32": raise RuntimeError(_LE("Enabling the client_mode is not currently " "supported on Windows.")) self.client_mode = enabled