Ejemplo n.º 1
0
 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)
Ejemplo n.º 2
0
 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)
Ejemplo n.º 3
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)
Ejemplo n.º 4
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)
Ejemplo n.º 5
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)
Ejemplo n.º 6
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 = 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)
Ejemplo n.º 7
0
 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
Ejemplo n.º 8
0
    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)
Ejemplo n.º 9
0
 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