Example #1
0
 def init(self, opts):
     if not parse_bool("rfb-upgrade", opts.rfb_upgrade):
         self._rfb_upgrade = 0
     else:
         self._rfb_upgrade = parse_number(int, "rfb-upgrade",
                                          opts.rfb_upgrade, 0)
     log("init(..) rfb-upgrade=%i", self._rfb_upgrade)
Example #2
0
 def init(self, opts):
     X11ServerBase.init(self, opts)
     if not parse_bool("rfb-upgrade", opts.rfb_upgrade):
         self._rfb_upgrade = 0
     else:
         self._rfb_upgrade = parse_number(int, "rfb-upgrade",
                                          opts.rfb_upgrade, 0)
Example #3
0
def main():
    import sys
    if len(sys.argv)!=4:
        print("usage: %s DISPLAY WID True|False" % sys.argv[0])
        return
    DISPLAY = int(sys.argv[1])
    wid = int(sys.argv[2])
    from xpra.scripts.config import parse_bool
    flag = parse_bool("flag", sys.argv[3])
    test_dbus(DISPLAY, wid, flag)
def main():
    import sys
    if len(sys.argv)!=4:
        print("usage: %s DISPLAY WID True|False" % sys.argv[0])
        return
    DISPLAY = int(sys.argv[1])
    wid = int(sys.argv[2])
    from xpra.scripts.config import parse_bool
    flag = parse_bool("flag", sys.argv[3])
    test_dbus(DISPLAY, wid, flag)
Example #5
0
 def makeRootWindowModels(self):
     screenlog("makeRootWindowModels() root=%s, display_options=%s", self.root, self.display_options)
     self.capture = self.setup_capture()
     model_class = self.get_root_window_model_class()
     models = []
     display_name = prettify_plug_name(self.root.get_screen().get_display().get_name())
     monitors = self.get_shadow_monitors()
     match_str = None
     multi_window = MULTI_WINDOW
     geometries = None
     if "=" in self.display_options:
         #parse the display options as a dictionary:
         opt_dict = parse_simple_dict(self.display_options)
         windows = opt_dict.get("windows")
         if windows:
             self.window_matches = windows.split("/")
             return self.makeDynamicWindowModels()
         match_str = opt_dict.get("plug")
         multi_window = parse_bool("multi-window", opt_dict.get("multi-window", multi_window))
         geometries_str = opt_dict.get("geometry")
         if geometries_str:
             geometries = parse_geometries(geometries_str)
     else:
         try:
             geometries = parse_geometries(self.display_options)
         except Exception:
             match_str = self.display_options
     if not multi_window or geometries:
         for geometry in (geometries or (self.root.get_geometry()[:4],)):
             model = model_class(self.root, self.capture, display_name, geometry)
             models.append(model)
         return models
     found = []
     screenlog("capture inputs matching %r", match_str or "all")
     for i, monitor in enumerate(monitors):
         plug_name, x, y, width, height, scale_factor = monitor
         title = display_name
         if plug_name or i>1:
             title = plug_name or str(i)
         found.append(plug_name or title)
         if match_str and not(title in match_str or plug_name in match_str):
             screenlog.info(" skipped monitor %s", plug_name or title)
             continue
         geometry = (x, y, width, height)
         model = model_class(self.root, self.capture, title, geometry)
         models.append(model)
         screenlog("monitor %i: %10s geometry=%s, scale factor=%s", i, title, geometry, scale_factor)
     screenlog("makeRootWindowModels()=%s", models)
     if not models and match_str:
         screenlog.warn("Warning: no monitors found matching %r", match_str)
         screenlog.warn(" only found: %s", csv(found))
     return models
Example #6
0
 def do_init(self, opts):
     super().do_init(opts)
     #the server class sets the default value for 'xsettings_enabled'
     #it is overriden in the seamless server (enabled by default),
     #and we let the options have the final say here:
     self._xsettings_enabled = parse_bool("xsettings", opts.xsettings,
                                          self._xsettings_enabled)
     log("xsettings_enabled(%s)=%s", opts.xsettings,
         self._xsettings_enabled)
     if self._xsettings_enabled:
         from xpra.x11.xsettings import XSettingsHelper
         self._default_xsettings = XSettingsHelper().get_settings()
         log("_default_xsettings=%s", self._default_xsettings)
         self.init_all_server_settings()
Example #7
0
    def init(self, opts):
        """ initialize variables from configuration """
        self.init_aliases()
        for c in CLIENT_BASES:
            log("init: %s", c)
            c.init(self, opts)

        self.title = opts.title
        self.session_name = bytestostr(opts.session_name)
        self.xsettings_enabled = not (OSX or WIN32) and parse_bool("xsettings", opts.xsettings, True)
        self.readonly = opts.readonly
        self.client_supports_sharing = opts.sharing is True
        self.client_lock = opts.lock is True
        self.headerbar = opts.headerbar
Example #8
0
 def configbool(key, default_value=True):
     return parse_bool(key, configvalue(key), default_value)
Example #9
0
 def init(self, opts, _extra_args=None):
     self.log_both = (opts.remote_logging or "").lower() == "both"
     self.client_supports_remote_logging = self.log_both or parse_bool(
         "remote-logging", opts.remote_logging)
Example #10
0
 def get_run_command(self, attach=False):
     localhost = self.localhost_btn.get_active()
     if xdg and localhost:
         if self.desktop_entry.getTryExec():
             try:
                 command = self.desktop_entry.findTryExec()
             except Exception:
                 command = self.desktop_entry.getTryExec()
         else:
             command = self.desktop_entry.getExec()
     else:
         command = self.entry.get_text()
     cmd = get_xpra_command() + [self.get_run_mode()]
     ewc = self.exit_with_client_cb.get_active()
     cmd.append("--exit-with-client=%s" % ewc)
     shadow = self.shadow_btn.get_active()
     if not shadow:
         ewc = self.exit_with_children_cb.get_active()
         cmd.append("--exit-with-children=%s" % ewc)
         if ewc:
             cmd.append("--start-child=%s" % command)
         else:
             cmd.append("--start=%s" % command)
     cmd.append("--attach=%s" % attach)
     #process session_config if we have one:
     for k in (
         "splash", "border", "headerbar", "notifications", "system-tray", "cursors", "bell", "modal-windows",
         "pixel-depth", "mousewheel",
         ):
         fn = k.replace("-", "_")
         if not hasattr(self.session_options, fn):
             continue
         value = getattr(self.session_options, fn)
         default_value = self.default_config.get(k)
         ot = OPTION_TYPES.get(k)
         if ot is bool:
             value = parse_bool(k, value)
         if value!=default_value:
             log.info("%s=%s (%s) - not %s (%s)", k, value, type(value), default_value, type(default_value))
             cmd.append("--%s=%s" % (k, value))
     localhost = self.localhost_btn.get_active()
     if self.display_entry.is_visible():
         display = self.display_entry.get_text().lstrip(":")
     else:
         display = self.display_combo.get_active_text()
     if localhost:
         uri = ":"+display if display else ""
     else:
         mode = self.mode_combo.get_active_text()
         uri = "%s://" % mode.lower()
         username = self.username_entry.get_text()
         if username:
             uri += "%s@" % username
         host = self.host_entry.get_text()
         if host:
             uri += host
         port = self.port_entry.get_text()
         if port!=self.get_default_port(mode):
             uri += ":%s" % port
         uri += "/"
         if display:
             uri += display
     if uri:
         cmd.append(uri)
     return cmd
Example #11
0
 def __init__(self, **kwargs):
     self.service = kwargs.pop("service", PAM_AUTH_SERVICE)
     self.check_account = parse_bool(
         "check-account", kwargs.pop("check-account", PAM_CHECK_ACCOUNT),
         False)
     super().__init__(**kwargs)
Example #12
0
def do_run_server(error_cb,
                  opts,
                  mode,
                  xpra_file,
                  extra_args,
                  desktop_display=None,
                  progress_cb=None):
    assert mode in (
        "start",
        "start-desktop",
        "upgrade",
        "upgrade-desktop",
        "shadow",
        "proxy",
    )

    def _progress(i, msg):
        if progress_cb:
            progress_cb(i, msg)

    progress = _progress

    progress(10, "initializing environment")
    try:
        cwd = os.getcwd()
    except OSError:
        cwd = os.path.expanduser("~")
        warn("current working directory does not exist, using '%s'\n" % cwd)
    validate_encryption(opts)
    if opts.encoding == "help" or "help" in opts.encodings:
        return show_encoding_help(opts)

    #remove anything pointing to dbus from the current env
    #(so we only detect a dbus instance started by pam,
    # and override everything else)
    for k in tuple(os.environ.keys()):
        if k.startswith("DBUS_"):
            del os.environ[k]

    use_display = parse_bool("use-display", opts.use_display)
    starting = mode == "start"
    starting_desktop = mode == "start-desktop"
    upgrading = mode == "upgrade"
    upgrading_desktop = mode == "upgrade-desktop"
    shadowing = mode == "shadow"
    proxying = mode == "proxy"

    if not proxying and POSIX and not OSX:
        #we don't support wayland servers,
        #so make sure GDK will use the X11 backend:
        from xpra.os_util import saved_env
        saved_env["GDK_BACKEND"] = "x11"
        os.environ["GDK_BACKEND"] = "x11"

    has_child_arg = (opts.start_child or opts.start_child_on_connect
                     or opts.start_child_after_connect
                     or opts.start_child_on_last_client_exit)
    if proxying or upgrading or upgrading_desktop:
        #when proxying or upgrading, don't exec any plain start commands:
        opts.start = opts.start_child = []
    elif opts.exit_with_children:
        assert has_child_arg, "exit-with-children was specified but start-child* is missing!"
    elif opts.start_child:
        warn("Warning: the 'start-child' option is used,")
        warn(" but 'exit-with-children' is not enabled,")
        warn(" use 'start' instead")

    if opts.bind_rfb and (proxying or starting):
        get_util_logger().warn(
            "Warning: bind-rfb sockets cannot be used with '%s' mode" % mode)
        opts.bind_rfb = []

    if not shadowing and not starting_desktop:
        opts.rfb_upgrade = 0

    if upgrading or upgrading_desktop or shadowing:
        #there should already be one running
        #so change None ('auto') to False
        if opts.pulseaudio is None:
            opts.pulseaudio = False

    #get the display name:
    if shadowing and not extra_args:
        if WIN32 or OSX:
            #just a virtual name for the only display available:
            display_name = "Main"
        else:
            from xpra.scripts.main import guess_X11_display
            dotxpra = DotXpra(opts.socket_dir, opts.socket_dirs)
            display_name = guess_X11_display(dotxpra, desktop_display)
    elif (upgrading or upgrading_desktop) and not extra_args:
        display_name = guess_xpra_display(opts.socket_dir, opts.socket_dirs)
    else:
        if len(extra_args) > 1:
            error_cb(
                "too many extra arguments (%i): only expected a display number"
                % len(extra_args))
        if len(extra_args) == 1:
            display_name = extra_args[0]
            if not shadowing and not upgrading and not use_display:
                display_name_check(display_name)
        else:
            if proxying:
                #find a free display number:
                dotxpra = DotXpra(opts.socket_dir, opts.socket_dirs)
                all_displays = dotxpra.sockets()
                #ie: [("LIVE", ":100"), ("LIVE", ":200"), ...]
                displays = [v[1] for v in all_displays]
                display_name = None
                for x in range(1000, 20000):
                    v = ":%s" % x
                    if v not in displays:
                        display_name = v
                        break
                if not display_name:
                    error_cb(
                        "you must specify a free virtual display name to use with the proxy server"
                    )
            elif use_display:
                #only use automatic guess for xpra displays and not X11 displays:
                display_name = guess_xpra_display(opts.socket_dir,
                                                  opts.socket_dirs)
            else:
                # We will try to find one automaticaly
                # Use the temporary magic value 'S' as marker:
                display_name = 'S' + str(os.getpid())

    if not (shadowing or proxying or upgrading or upgrading_desktop) and \
    opts.exit_with_children and not has_child_arg:
        error_cb(
            "--exit-with-children specified without any children to spawn; exiting immediately"
        )

    atexit.register(run_cleanups)

    # Generate the script text now, because os.getcwd() will
    # change if/when we daemonize:
    from xpra.server.server_util import (
        xpra_runner_shell_script,
        write_runner_shell_scripts,
        find_log_dir,
        create_input_devices,
        source_env,
    )
    script = None
    if POSIX and getuid() != 0:
        script = xpra_runner_shell_script(xpra_file, cwd, opts.socket_dir)

    uid = int(opts.uid)
    gid = int(opts.gid)
    username = get_username_for_uid(uid)
    home = get_home_for_uid(uid)
    ROOT = POSIX and getuid() == 0

    protected_fds = []
    protected_env = {}
    stdout = sys.stdout
    stderr = sys.stderr
    # Daemonize:
    if POSIX and opts.daemon:
        #daemonize will chdir to "/", so try to use an absolute path:
        if opts.password_file:
            opts.password_file = tuple(
                os.path.abspath(x) for x in opts.password_file)
        from xpra.server.server_util import daemonize
        daemonize()

    displayfd = 0
    if POSIX and opts.displayfd:
        try:
            displayfd = int(opts.displayfd)
            if displayfd > 0:
                protected_fds.append(displayfd)
        except ValueError as e:
            stderr.write("Error: invalid displayfd '%s':\n" % opts.displayfd)
            stderr.write(" %s\n" % e)
            del e

    clobber = int(upgrading or upgrading_desktop) * CLOBBER_UPGRADE | int(
        use_display or 0) * CLOBBER_USE_DISPLAY
    start_vfb = not (shadowing or proxying or clobber)
    xauth_data = None
    if start_vfb:
        xauth_data = get_hex_uuid()

    # if pam is present, try to create a new session:
    pam = None
    PAM_OPEN = POSIX and envbool("XPRA_PAM_OPEN", ROOT and uid != 0)
    if PAM_OPEN:
        try:
            from xpra.server.pam import pam_session  #@UnresolvedImport
        except ImportError as e:
            stderr.write("Error: failed to import pam module\n")
            stderr.write(" %s" % e)
            del e
            PAM_OPEN = False
    if PAM_OPEN:
        fdc = FDChangeCaptureContext()
        with fdc:
            pam = pam_session(username)
            env = {
                #"XDG_SEAT"               : "seat1",
                #"XDG_VTNR"               : "0",
                "XDG_SESSION_TYPE": "x11",
                #"XDG_SESSION_CLASS"      : "user",
                "XDG_SESSION_DESKTOP": "xpra",
            }
            #maybe we should just bail out instead?
            if pam.start():
                pam.set_env(env)
                items = {}
                if display_name.startswith(":"):
                    items["XDISPLAY"] = display_name
                if xauth_data:
                    items["XAUTHDATA"] = xauth_data
                pam.set_items(items)
                if pam.open():
                    #we can't close it, because we're not going to be root any more,
                    #but since we're the process leader for the session,
                    #terminating will also close the session
                    #add_cleanup(pam.close)
                    protected_env = pam.get_envlist()
                    os.environ.update(protected_env)
        #closing the pam fd causes the session to be closed,
        #and we don't want that!
        protected_fds += fdc.get_new_fds()

    #get XDG_RUNTIME_DIR from env options,
    #which may not be have updated os.environ yet when running as root with "--uid="
    xrd = os.path.abspath(parse_env(opts.env).get("XDG_RUNTIME_DIR", ""))
    if ROOT and (uid > 0 or gid > 0):
        #we're going to chown the directory if we create it,
        #ensure this cannot be abused, only use "safe" paths:
        if not any(x for x in ("/run/user/%i" % uid, "/tmp", "/var/tmp")
                   if xrd.startswith(x)):
            xrd = ""
        #these paths could cause problems if we were to create and chown them:
        if xrd.startswith("/tmp/.X11-unix") or xrd.startswith(
                "/tmp/.XIM-unix"):
            xrd = ""
    if not xrd:
        xrd = os.environ.get("XDG_RUNTIME_DIR")
    xrd = create_runtime_dir(xrd, uid, gid)
    if xrd:
        #this may override the value we get from pam
        #with the value supplied by the user:
        protected_env["XDG_RUNTIME_DIR"] = xrd

    if script:
        # Write out a shell-script so that we can start our proxy in a clean
        # environment:
        write_runner_shell_scripts(script)

    import datetime
    extra_expand = {
        "TIMESTAMP": datetime.datetime.now().strftime("%Y%m%d-%H%M%S")
    }
    log_to_file = opts.daemon or os.environ.get("XPRA_LOG_TO_FILE", "") == "1"
    if start_vfb or log_to_file:
        #we will probably need a log dir
        #either for the vfb, or for our own log file
        log_dir = opts.log_dir or ""
        if not log_dir or log_dir.lower() == "auto":
            log_dir = find_log_dir(username, uid=uid, gid=gid)
            if not log_dir:
                raise InitException(
                    "cannot find or create a logging directory")
        #expose the log-dir as "XPRA_LOG_DIR",
        #this is used by Xdummy for the Xorg log file
        if "XPRA_LOG_DIR" not in os.environ:
            os.environ["XPRA_LOG_DIR"] = log_dir

    if log_to_file:
        from xpra.server.server_util import select_log_file, open_log_file, redirect_std_to_log
        log_filename0 = osexpand(
            select_log_file(log_dir, opts.log_file, display_name), username,
            uid, gid, extra_expand)
        if os.path.exists(log_filename0) and not display_name.startswith("S"):
            #don't overwrite the log file just yet,
            #as we may still fail to start
            log_filename0 += ".new"
        logfd = open_log_file(log_filename0)
        if POSIX and ROOT and (uid > 0 or gid > 0):
            try:
                os.fchown(logfd, uid, gid)
            except OSError as e:
                noerr(stderr.write,
                      "failed to chown the log file '%s'\n" % log_filename0)
                noerr(stderr.flush)
        stdout, stderr = redirect_std_to_log(logfd, *protected_fds)
        noerr(
            stderr.write, "Entering daemon mode; " +
            "any further errors will be reported to:\n" +
            ("  %s\n" % log_filename0))
        noerr(stderr.flush)
        os.environ["XPRA_SERVER_LOG"] = log_filename0
    else:
        #server log does not exist:
        os.environ.pop("XPRA_SERVER_LOG", None)

    #warn early about this:
    if (starting or starting_desktop
        ) and desktop_display and opts.notifications and not opts.dbus_launch:
        print_DE_warnings()

    if start_vfb and opts.xvfb.find("Xephyr") >= 0 and opts.sync_xvfb <= 0:
        warn("Warning: using Xephyr as vfb")
        warn(" you should also enable the sync-xvfb option")
        warn(" to keep the Xephyr window updated")

    progress(10, "creating sockets")
    from xpra.net.socket_util import get_network_logger, setup_local_sockets, create_sockets
    sockets = create_sockets(opts, error_cb)

    sanitize_env()
    os.environ.update(source_env(opts.source))
    if POSIX:
        if xrd:
            os.environ["XDG_RUNTIME_DIR"] = xrd
        if not OSX:
            os.environ["XDG_SESSION_TYPE"] = "x11"
        if not starting_desktop:
            os.environ["XDG_CURRENT_DESKTOP"] = opts.wm_name
        configure_imsettings_env(opts.input_method)
    if display_name[0] != 'S':
        os.environ["DISPLAY"] = display_name
        if POSIX:
            os.environ["CKCON_X11_DISPLAY"] = display_name
    elif not start_vfb or opts.xvfb.find("Xephyr") < 0:
        os.environ.pop("DISPLAY", None)
    os.environ.update(protected_env)
    from xpra.log import Logger
    log = Logger("server")
    log("env=%s", os.environ)

    UINPUT_UUID_LEN = 12
    UINPUT_UUID_MIN_LEN = 12
    UINPUT_UUID_MAX_LEN = 32
    # Start the Xvfb server first to get the display_name if needed
    odisplay_name = display_name
    xvfb = None
    xvfb_pid = None
    uinput_uuid = None
    if start_vfb and use_display is None:
        #use-display='auto' so we have to figure out
        #if we have to start the vfb or not:
        if not display_name:
            use_display = False
        else:
            progress(20, "connecting to the display")
            start_vfb = verify_display(
                None, display_name, log_errors=False, timeout=1) != 0
    if start_vfb:
        progress(20, "starting a virtual display")
        assert not proxying and xauth_data
        pixel_depth = validate_pixel_depth(opts.pixel_depth, starting_desktop)
        from xpra.x11.vfb_util import start_Xvfb, check_xvfb_process, parse_resolution
        from xpra.server.server_util import has_uinput
        uinput_uuid = None
        if has_uinput() and opts.input_devices.lower() in (
                "uinput", "auto") and not shadowing:
            from xpra.os_util import get_rand_chars
            uinput_uuid = get_rand_chars(UINPUT_UUID_LEN)
        vfb_geom = ""
        try:
            vfb_geom = parse_resolution(opts.resize_display)
        except Exception:
            pass
        xvfb, display_name, cleanups = start_Xvfb(opts.xvfb, vfb_geom,
                                                  pixel_depth, display_name,
                                                  cwd, uid, gid, username,
                                                  xauth_data, uinput_uuid)
        for f in cleanups:
            add_cleanup(f)
        xvfb_pid = xvfb.pid
        #always update as we may now have the "real" display name:
        os.environ["DISPLAY"] = display_name
        os.environ["CKCON_X11_DISPLAY"] = display_name
        os.environ.update(protected_env)
        if display_name != odisplay_name and pam:
            pam.set_items({"XDISPLAY": display_name})

        def check_xvfb(timeout=0):
            return check_xvfb_process(xvfb, timeout=timeout, command=opts.xvfb)
    else:
        if POSIX and clobber:
            #if we're meant to be using a private XAUTHORITY file,
            #make sure to point to it:
            from xpra.x11.vfb_util import get_xauthority_path
            xauthority = get_xauthority_path(display_name, username, uid, gid)
            if os.path.exists(xauthority):
                log("found XAUTHORITY=%s", xauthority)
                os.environ["XAUTHORITY"] = xauthority

        def check_xvfb(timeout=0):  #pylint: disable=unused-argument
            return True

    if POSIX and not OSX and displayfd > 0:
        from xpra.platform.displayfd import write_displayfd
        try:
            display_no = display_name[1:]
            #ensure it is a string containing the number:
            display_no = str(int(display_no))
            log("writing display_no='%s' to displayfd=%i", display_no,
                displayfd)
            assert write_displayfd(displayfd, display_no), "timeout"
        except Exception as e:
            log.error("write_displayfd failed", exc_info=True)
            log.error("Error: failed to write '%s' to fd=%s", display_name,
                      displayfd)
            log.error(" %s", str(e) or type(e))
            del e

    if not check_xvfb(1):
        noerr(stderr.write, "vfb failed to start, exiting\n")
        return EXIT_VFB_ERROR

    if WIN32 and os.environ.get("XPRA_LOG_FILENAME"):
        os.environ["XPRA_SERVER_LOG"] = os.environ["XPRA_LOG_FILENAME"]
    if opts.daemon:
        log_filename1 = osexpand(
            select_log_file(log_dir, opts.log_file, display_name), username,
            uid, gid, extra_expand)
        if log_filename0 != log_filename1:
            # we now have the correct log filename, so use it:
            try:
                os.rename(log_filename0, log_filename1)
            except (OSError, IOError):
                pass
            else:
                os.environ["XPRA_SERVER_LOG"] = log_filename1
            if odisplay_name != display_name:
                #this may be used by scripts, let's try not to change it:
                noerr(stderr.write, "Actual display used: %s\n" % display_name)
            noerr(stderr.write,
                  "Actual log file name is now: %s\n" % log_filename1)
            noerr(stderr.flush)
        noerr(stdout.close)
        noerr(stderr.close)
    #we should not be using stdout or stderr from this point:
    del stdout
    del stderr

    if not check_xvfb():
        noerr(stderr.write, "vfb failed to start, exiting\n")
        return EXIT_VFB_ERROR

    #create devices for vfb if needed:
    devices = {}
    if not start_vfb and not proxying and not shadowing and envbool(
            "XPRA_UINPUT", True):
        #try to find the existing uinput uuid:
        #use a subprocess to avoid polluting our current process
        #with X11 connections before we get a chance to change uid
        prop = "_XPRA_UINPUT_ID"
        cmd = ["xprop", "-display", display_name, "-root", prop]
        log("looking for '%s' on display '%s' with XAUTHORITY='%s'", prop,
            display_name, os.environ.get("XAUTHORITY"))
        try:
            code, out, err = get_status_output(cmd)
        except Exception as e:
            log("failed to get existing uinput id: %s", e)
            del e
        else:
            log("Popen(%s)=%s", cmd, (code, out, err))
            if code == 0 and out.find("=") > 0:
                uinput_uuid = out.split("=", 1)[1]
                log("raw uinput uuid=%s", uinput_uuid)
                uinput_uuid = strtobytes(uinput_uuid.strip('\n\r"\\ '))
                if uinput_uuid:
                    if len(uinput_uuid) > UINPUT_UUID_MAX_LEN or len(
                            uinput_uuid) < UINPUT_UUID_MIN_LEN:
                        log.warn("Warning: ignoring invalid uinput id:")
                        log.warn(" '%s'", uinput_uuid)
                        uinput_uuid = None
                    else:
                        log.info("retrieved existing uinput id: %s",
                                 bytestostr(uinput_uuid))
    if uinput_uuid:
        devices = create_input_devices(uinput_uuid, uid)

    if ROOT and (uid != 0 or gid != 0):
        log("root: switching to uid=%i, gid=%i", uid, gid)
        setuidgid(uid, gid)
        os.environ.update({
            "HOME": home,
            "USER": username,
            "LOGNAME": username,
        })
        shell = get_shell_for_uid(uid)
        if shell:
            os.environ["SHELL"] = shell
        #now we've changed uid, it is safe to honour all the env updates:
        configure_env(opts.env)
        os.environ.update(protected_env)

    if opts.chdir:
        log("chdir(%s)", opts.chdir)
        os.chdir(opts.chdir)

    dbus_pid, dbus_env = 0, {}
    if not shadowing and POSIX and not OSX and not clobber:
        no_gtk()
        assert starting or starting_desktop or proxying
        try:
            from xpra.server.dbus.dbus_start import start_dbus
        except ImportError as e:
            log("dbus components are not installed: %s", e)
        else:
            dbus_pid, dbus_env = start_dbus(opts.dbus_launch)
            if dbus_env:
                os.environ.update(dbus_env)

    if not proxying:
        if POSIX and not OSX:
            no_gtk()
            if starting or starting_desktop or shadowing:
                r = verify_display(xvfb, display_name, shadowing)
                if r:
                    return r
        #on win32, this ensures that we get the correct screen size to shadow:
        from xpra.platform.gui import init as gui_init
        log("gui_init()")
        gui_init()

    progress(50, "creating local sockets")
    #setup unix domain socket:
    netlog = get_network_logger()
    local_sockets = setup_local_sockets(opts.bind, opts.socket_dir,
                                        opts.socket_dirs, display_name,
                                        clobber, opts.mmap_group,
                                        opts.socket_permissions, username, uid,
                                        gid)
    netlog("setting up local sockets: %s", local_sockets)
    sockets.update(local_sockets)
    if POSIX and (starting or upgrading or starting_desktop
                  or upgrading_desktop):
        #all unix domain sockets:
        ud_paths = [
            sockpath for stype, _, sockpath, _ in local_sockets
            if stype == "unix-domain"
        ]
        if ud_paths:
            #choose one so our xdg-open override script can use to talk back to us:
            if opts.forward_xdg_open:
                for x in ("/usr/libexec/xpra", "/usr/lib/xpra"):
                    xdg_override = os.path.join(x, "xdg-open")
                    if os.path.exists(xdg_override):
                        os.environ["PATH"] = x + os.pathsep + os.environ.get(
                            "PATH", "")
                        os.environ["XPRA_SERVER_SOCKET"] = ud_paths[0]
                        break
        else:
            log.warn("Warning: no local server sockets,")
            if opts.forward_xdg_open:
                log.warn(" forward-xdg-open cannot be enabled")
            log.warn(" non-embedded ssh connections will not be available")

    set_server_features(opts)

    if not proxying and POSIX and not OSX:
        if not check_xvfb():
            return 1
        from xpra.x11.gtk_x11.gdk_display_source import init_gdk_display_source
        if os.environ.get("NO_AT_BRIDGE") is None:
            os.environ["NO_AT_BRIDGE"] = "1"
        init_gdk_display_source()
        #(now we can access the X11 server)
        if uinput_uuid:
            save_uinput_id(uinput_uuid)

    progress(60, "initializing server")
    if shadowing:
        app = make_shadow_server()
    elif proxying:
        app = make_proxy_server()
    else:
        if starting or upgrading:
            app = make_server(clobber)
        else:
            assert starting_desktop or upgrading_desktop
            app = make_desktop_server(clobber)
        app.init_virtual_devices(devices)

    try:
        app.exec_cwd = opts.chdir or cwd
        app.display_name = display_name
        app.init(opts)
        progress(70, "initializing sockets")
        app.init_sockets(sockets)
        app.init_dbus(dbus_pid, dbus_env)
        if not shadowing and not proxying:
            app.init_display_pid(xvfb_pid)
        app.original_desktop_display = desktop_display
        del opts
        if not app.server_ready():
            return 1
        progress(80, "finalizing")
        app.server_init()
        app.setup()
        app.init_when_ready(_when_ready)
    except InitException as e:
        log.error("xpra server initialization error:")
        log.error(" %s", e)
        app.cleanup()
        return 1
    except Exception as e:
        log.error("Error: cannot start the %s server",
                  app.session_type,
                  exc_info=True)
        log.error(str(e))
        log.info("")
        if upgrading or upgrading_desktop:
            #something abnormal occurred,
            #don't kill the vfb on exit:
            from xpra.server import EXITING_CODE
            app._upgrading = EXITING_CODE
        app.cleanup()
        return 1

    try:
        progress(100, "running")
        log("running %s", app.run)
        r = app.run()
        log("%s()=%s", app.run, r)
    except KeyboardInterrupt:
        log.info("stopping on KeyboardInterrupt")
        app.cleanup()
        return EXIT_OK
    except Exception:
        log.error("server error", exc_info=True)
        app.cleanup()
        return -128
    else:
        if r > 0:
            r = 0
    return r
Example #13
0
 def __init__(self, username, **kwargs):
     self.service = kwargs.pop("service", PAM_AUTH_SERVICE)
     self.check_account = parse_bool("check-account", kwargs.pop("check-account", PAM_CHECK_ACCOUNT), False)
     SysAuthenticator.__init__(self, username, **kwargs)
 def control_command_set_lock(self, lock):
     self.lock = parse_bool("lock", lock)
     self.setting_changed("lock", lock is not False)
     self.setting_changed("lock-toggle", lock is None)
     return "lock set to %s" % self.lock
Example #15
0
File: ssh.py Project: chewi/xpra
    def check_channel_exec_request(self, channel, command):
        def fail():
            self.event.set()
            channel.close()
            return False

        log("check_channel_exec_request(%s, %s)", channel, command)
        cmd = shlex.split(decode_str(command))
        log("check_channel_exec_request: cmd=%s", cmd)
        # not sure if this is the best way to handle this, 'command -v xpra' has len=3
        if cmd[0] in ("type", "which", "command") and len(cmd) in (2, 3):
            xpra_cmd = cmd[-1]  #ie: $XDG_RUNTIME_DIR/xpra/run-xpra or "xpra"
            if not POSIX:
                assert WIN32
                #we can't execute "type" or "which" on win32,
                #so we just answer as best we can
                #and only accept "xpra" as argument:
                if xpra_cmd.strip('"').strip("'") == "xpra":
                    chan_send(channel.send, "xpra is xpra")
                    channel.send_exit_status(0)
                else:
                    chan_send(channel.send_stderr,
                              "type: %s: not found" % xpra_cmd)
                    channel.send_exit_status(1)
                return True
            #we don't want to use a shell,
            #but we need to expand the file argument:
            cmd[-1] = osexpand(xpra_cmd)
            try:
                proc = Popen(cmd,
                             stdout=PIPE,
                             stderr=PIPE,
                             close_fds=not WIN32)
                out, err = proc.communicate()
            except Exception as e:
                log("check_channel_exec_request(%s, %s)",
                    channel,
                    command,
                    exc_info=True)
                chan_send(channel.send_stderr,
                          "failed to execute command: %s" % e)
                channel.send_exit_status(1)
            else:
                log("check_channel_exec_request: out(%s)=%s", cmd, out)
                log("check_channel_exec_request: err(%s)=%s", cmd, err)
                chan_send(channel.send, out)
                chan_send(channel.send_stderr, err)
                channel.send_exit_status(proc.returncode)
        elif cmd[0].endswith("xpra") and len(cmd) >= 2:
            subcommand = cmd[1].strip("\"'").rstrip(";")
            log("ssh xpra subcommand: %s", subcommand)
            if subcommand in ("_proxy_start", "_proxy_start_desktop",
                              "_proxy_shadow_start"):
                proxy_start = parse_bool("proxy-start",
                                         self.options.get("proxy-start"),
                                         False)
                if not proxy_start:
                    log.warn("Warning: received a %r session request",
                             subcommand)
                    log.warn(
                        " this feature is not yet implemented with the builtin ssh server"
                    )
                    return fail()
                self.proxy_start(channel, subcommand, cmd[2:])
            elif subcommand == "_proxy":
                if len(cmd) == 3:
                    #only the display can be specified here
                    display = cmd[2]
                    display_name = getattr(self, "display_name", None)
                    if display_name != display:
                        log.warn("Warning: the display requested (%r)",
                                 display)
                        log.warn(" is not the current display (%r)",
                                 display_name)
                        return fail()
            else:
                log.warn("Warning: unsupported xpra subcommand '%s'", cmd[1])
                return fail()
            #we're ready to use this socket as an xpra channel
            self._run_proxy(channel)
        else:
            #plain 'ssh' clients execute a long command with if+else statements,
            #try to detect it and extract the actual command the client is trying to run.
            #ie:
            #['sh', '-c',
            # ': run-xpra _proxy;xpra initenv;\
            #  if [ -x $XDG_RUNTIME_DIR/xpra/run-xpra ]; then $XDG_RUNTIME_DIR/xpra/run-xpra _proxy;\
            #  elif [ -x ~/.xpra/run-xpra ]; then ~/.xpra/run-xpra _proxy;\
            #  elif type "xpra" > /dev/null 2>&1; then xpra _proxy;\
            #  elif [ -x /usr/local/bin/xpra ]; then /usr/local/bin/xpra _proxy;\
            #  else echo "no run-xpra command found"; exit 1; fi']
            #if .* ; then .*/run-xpra _proxy;
            log("parse cmd=%s (len=%i)", cmd, len(cmd))
            if len(cmd) == 1:  #ie: 'thelongcommand'
                parse_cmd = cmd[0]
            elif len(cmd) == 3 and cmd[:2] == [
                    "sh", "-c"
            ]:  #ie: 'sh' '-c' 'thelongcommand'
                parse_cmd = cmd[2]
            else:
                parse_cmd = ""
            #for older clients, try to parse the long command
            #and identify the subcommands from there
            subcommands = []
            for s in parse_cmd.split("if "):
                if (s.startswith("type \"xpra\"")
                        or s.startswith("which \"xpra\"")
                        or s.startswith("[ -x")) and s.find("then ") > 0:
                    then_str = s.split("then ", 1)[1]
                    #ie: then_str="$XDG_RUNTIME_DIR/xpra/run-xpra _proxy; el"
                    if then_str.find(";") > 0:
                        then_str = then_str.split(";")[0]
                    parts = shlex.split(then_str)
                    if len(parts) >= 2:
                        subcommand = parts[1]  #ie: "_proxy"
                        subcommands.append(subcommand)
            log("subcommands=%s", subcommands)
            if subcommands and tuple(set(subcommands))[0] == "_proxy":
                self._run_proxy(channel)
            else:
                log.warn("Warning: unsupported ssh command:")
                log.warn(" %s", cmd)
                return fail()
        return True
Example #16
0
        parser.error("invalid dpi: %s" % e)
    if options.encoding and options.encoding not in ENCODINGS:
        parser.error("encoding %s is not supported, try: %s" %
                     (options.encoding, ", ".join(ENCODINGS)))
    if options.encryption:
        assert len(ENCRYPTION_CIPHERS
                   ) > 0, "cannot use encryption: no ciphers available"
        if options.encryption not in ENCRYPTION_CIPHERS:
            parser.error("encryption %s is not supported, try: %s" %
                         (options.encryption, ", ".join(ENCRYPTION_CIPHERS)))
        if not options.password_file:
            parser.error(
                "encryption %s cannot be used without a password (see --password-file option)"
                % options.encryption)
    #ensure opengl is either True, False or None
    options.opengl = parse_bool("opengl", options.opengl)

    def toggle_logging(level):
        if not options.debug:
            logging.root.setLevel(level)
            return
        categories = options.debug.split(",")
        for cat in categories:
            if cat.startswith("-"):
                logging.getLogger(cat[1:]).setLevel(logging.INFO)
            if cat == "all":
                logger = logging.root
            else:
                logger = logging.getLogger(cat)
            logger.setLevel(level)
Example #17
0
    def makeRootWindowModels(self):
        screenlog("makeRootWindowModels() root=%s, display_options=%s",
                  self.root, self.display_options)
        self.capture = self.setup_capture()
        model_class = self.get_root_window_model_class()
        models = []
        display_name = prettify_plug_name(
            self.root.get_screen().get_display().get_name())
        monitors = self.get_shadow_monitors()
        match_str = None
        multi_window = MULTI_WINDOW
        geometries = None

        def parse_geometry(s):
            try:
                parts = s.split("@")
                if len(parts) == 1:
                    x = y = 0
                else:
                    x, y = [int(v.strip(" ")) for v in parts[1].split("x")]
                w, h = [int(v.strip(" ")) for v in parts[0].split("x")]
                geometry = [x, y, w, h]
                screenlog("capture geometry: %s", geometry)
                return geometry
            except ValueError:
                screenlog("failed to parse geometry %r", s, exc_info=True)
                screenlog.error(
                    "Error: invalid display geometry specified: %r", s)
                screenlog.error(" use the format: WIDTHxHEIGHT@x,y")
                raise

        def parse_geometries(s):
            g = []
            for geometry_str in s.split("/"):
                if geometry_str:
                    g.append(parse_geometry(geometry_str))
            return g

        if "=" in self.display_options:
            #parse the display options as a dictionary:
            opt_dict = parse_simple_dict(self.display_options)
            match_str = opt_dict.get("plug")
            multi_window = parse_bool(
                "multi-window", opt_dict.get("multi-window", multi_window))
            geometries_str = opt_dict.get("geometry")
            if geometries_str:
                geometries = parse_geometries(geometries_str)
        else:
            try:
                geometries = parse_geometries(self.display_options)
            except:
                match_str = self.display_options
        if not multi_window or geometries:
            for geometry in (geometries or (None, )):
                model = model_class(self.root, self.capture)
                model.title = display_name
                if geometry:
                    model.geometry = geometry
                models.append(model)
            return models
        found = []
        screenlog("capture inputs matching %r", match_str or "all")
        for i, monitor in enumerate(monitors):
            plug_name, x, y, width, height, scale_factor = monitor
            title = display_name
            if plug_name or i > 1:
                title = plug_name or str(i)
            found.append(plug_name or title)
            if match_str and not (title in match_str
                                  or plug_name in match_str):
                screenlog.info(" skipped monitor %s", plug_name or title)
                continue
            model = model_class(self.root, self.capture)
            model.title = title
            model.geometry = (x, y, width, height)
            models.append(model)
            screenlog("monitor %i: %10s geometry=%s, scale factor=%s", i,
                      title, model.geometry, scale_factor)
        screenlog("makeRootWindowModels()=%s", models)
        if not models and match_str:
            screenlog.warn("Warning: no monitors found matching %r", match_str)
            screenlog.warn(" only found: %s", csv(found))
        return models
Example #18
0
 def init(self, opts):
     if opts.mmap and os.path.isabs(opts.mmap):
         self.supports_mmap = True
         self.mmap_filename = opts.mmap
     else:
         self.supports_mmap = bool(parse_bool("mmap", opts.mmap.lower()))
Example #19
0
 def pbool(name, v):
     return parse_bool(name, v, True)
Example #20
0
File: ssh.py Project: chewi/xpra
def make_ssh_server_connection(conn,
                               socket_options,
                               none_auth=False,
                               password_auth=None):
    log("make_ssh_server_connection%s",
        (conn, socket_options, none_auth, password_auth))
    ssh_server = SSHServer(none_auth=none_auth,
                           password_auth=password_auth,
                           options=socket_options)
    DoGSSAPIKeyExchange = parse_bool(
        "ssh-gss-key-exchange",
        socket_options.get("ssh-gss-key-exchange", False), False)
    sock = conn._socket
    t = None

    def close():
        if t:
            log("close() closing %s", t)
            try:
                t.close()
            except Exception:
                log("%s.close()", t, exc_info=True)
        log("close() closing %s", conn)
        try:
            conn.close()
        except Exception:
            log("%s.close()", conn)

    try:
        t = paramiko.Transport(sock, gss_kex=DoGSSAPIKeyExchange)
        gss_host = socket_options.get("ssh-gss-host", socket.getfqdn(""))
        t.set_gss_host(gss_host)
        #load host keys:
        PREFIX = "ssh_host_"
        SUFFIX = "_key"
        host_keys = {}

        def add_host_key(fd, f):
            ff = os.path.join(fd, f)
            keytype = f[len(PREFIX):-len(SUFFIX)]
            if not keytype:
                log.warn("Warning: unknown host key format '%s'", f)
                return False
            keyclass = getattr(paramiko, "%sKey" % keytype.upper(), None)
            if keyclass is None:
                #Ed25519Key
                keyclass = getattr(
                    paramiko, "%s%sKey" % (keytype[:1].upper(), keytype[1:]),
                    None)
            if keyclass is None:
                log("key type %s is not supported, cannot load '%s'", keytype,
                    ff)
                return False
            log("loading %s key from '%s' using %s", keytype, ff, keyclass)
            try:
                host_key = keyclass(filename=ff)
                if host_key not in host_keys:
                    host_keys[host_key] = ff
                    t.add_server_key(host_key)
                    return True
            except IOError as e:
                log("cannot add host key '%s'", ff, exc_info=True)
            except paramiko.SSHException as e:
                log("error adding host key '%s'", ff, exc_info=True)
                log.error("Error: cannot add %s host key '%s':", keytype, ff)
                log.error(" %s", e)
            return False

        host_key = socket_options.get("ssh-host-key")
        if host_key:
            d, f = os.path.split(host_key)
            if f.startswith(PREFIX) and f.endswith(SUFFIX):
                add_host_key(d, f)
            if not host_keys:
                log.error("Error: failed to load host key '%s'", host_key)
                close()
                return None
        else:
            ssh_key_dirs = get_ssh_conf_dirs()
            log("trying to load ssh host keys from: %s", csv(ssh_key_dirs))
            for d in ssh_key_dirs:
                fd = osexpand(d)
                log("osexpand(%s)=%s", d, fd)
                if not os.path.exists(fd) or not os.path.isdir(fd):
                    log("ssh host key directory '%s' is invalid", fd)
                    continue
                for f in os.listdir(fd):
                    if f.startswith(PREFIX) and f.endswith(SUFFIX):
                        add_host_key(fd, f)
            if not host_keys:
                log.error("Error: cannot start SSH server,")
                log.error(" no readable SSH host keys found in:")
                log.error(" %s", csv(ssh_key_dirs))
                close()
                return None
        log("loaded host keys: %s", tuple(host_keys.values()))
        t.start_server(server=ssh_server)
    except (paramiko.SSHException, EOFError) as e:
        log("failed to start ssh server", exc_info=True)
        log.error("Error handling SSH connection:")
        log.error(" %s", e)
        close()
        return None
    try:
        chan = t.accept(SERVER_WAIT)
        if chan is None:
            log.warn("Warning: SSH channel setup failed")
            #prevent errors trying to access this connection, now likely dead:
            conn.set_active(False)
            close()
            return None
    except paramiko.SSHException as e:
        log("failed to open ssh channel", exc_info=True)
        log.error("Error opening channel:")
        log.error(" %s", e)
        close()
        return None
    log("client authenticated, channel=%s", chan)
    timedout = not ssh_server.event.wait(SERVER_WAIT)
    proxy_channel = ssh_server.proxy_channel
    log("proxy channel=%s, timedout=%s", proxy_channel, timedout)
    if not ssh_server.event.is_set() or not proxy_channel:
        if timedout:
            log.warn("Warning: timeout waiting for xpra SSH subcommand,")
            log.warn(" closing connection from %s", pretty_socket(conn.target))
        close()
        return None
    if getattr(proxy_channel, "proxy_process", None):
        log("proxy channel is handled using a subprocess")
        return None
    log("client authenticated, channel=%s", chan)
    return SSHSocketConnection(proxy_channel,
                               sock,
                               conn.local,
                               conn.endpoint,
                               conn.target,
                               socket_options=socket_options)
Example #21
0
            #assume tcp if not specified
            address = "tcp:%s" % address
        args[1] = address

    try:
        int(options.dpi)
    except Exception, e:
        parser.error("invalid dpi: %s" % e)
    if options.encryption:
        assert len(ENCRYPTION_CIPHERS)>0, "cannot use encryption: no ciphers available"
        if options.encryption not in ENCRYPTION_CIPHERS:
            parser.error("encryption %s is not supported, try: %s" % (options.encryption, ", ".join(ENCRYPTION_CIPHERS)))
        if not options.password_file and not options.encryption_keyfile:
            parser.error("encryption %s cannot be used without a keyfile (see --encryption-keyfile option)" % options.encryption)
    #ensure opengl is either True, False or None
    options.opengl = parse_bool("opengl", options.opengl)
    return parser, options, args

def dump_frames(*arsg):
    import traceback
    frames = sys._current_frames()
    print("")
    print("found %s frames:" % len(frames))
    for fid,frame in frames.items():
        print("%s - %s:" % (fid, frame))
        traceback.print_stack(frame)
    print("")


def configure_logging(options, mode):
    if mode in ("start", "upgrade", "attach", "shadow", "proxy"):
 def control_command_set_sharing(self, sharing):
     self.sharing = parse_bool("sharing", sharing)
     self.setting_changed("sharing", sharing is not False)
     self.setting_changed("sharing-toggle", sharing is None)
     return "sharing set to %s" % self.sharing
Example #23
0
    def init_ui(self, opts):
        """ initialize user interface """
        if not self.readonly:

            def noauto(v):
                if not v:
                    return None
                if str(v).lower() == "auto":
                    return None
                return v

            overrides = [
                noauto(getattr(opts, "keyboard_%s" % x)) for x in (
                    "layout",
                    "layouts",
                    "variant",
                    "variants",
                    "options",
                )
            ]

            def send_keyboard(*parts):
                self.after_handshake(self.send, *parts)

            try:
                self.keyboard_helper = self.keyboard_helper_class(
                    send_keyboard, opts.keyboard_sync, opts.shortcut_modifiers,
                    opts.key_shortcut, opts.keyboard_raw, *overrides)
            except ImportError as e:
                keylog("error instantiating %s",
                       self.keyboard_helper_class,
                       exc_info=True)
                keylog.warn("Warning: no keyboard support, %s", e)

        if mixin_features.windows:
            self.init_opengl(opts.opengl)

        if ClientExtras is not None:
            self.client_extras = ClientExtras(self, opts)  #pylint: disable=not-callable

        self.start_new_commands = parse_bool("start-new-commands",
                                             opts.start_new_commands, True)
        if self.start_new_commands and (opts.start or opts.start_child):
            from xpra.scripts.main import strip_defaults_start_child
            from xpra.scripts.config import make_defaults_struct
            defaults = make_defaults_struct()
            self.request_start = strip_defaults_start_child(
                opts.start, defaults.start)  #pylint: disable=no-member
            self.request_start_child = strip_defaults_start_child(
                opts.start_child, defaults.start_child)  #pylint: disable=no-member

        if MOUSE_DELAY_AUTO:
            try:
                #some platforms don't detect the vrefresh correctly
                #(ie: macos in virtualbox?), so use a sane default minimum
                #discount by 5ms to ensure we have time to hit the target
                v = max(60, self.get_vrefresh())
                self._mouse_position_delay = max(5, 1000 // v // 2 - 5)
                log("mouse delay: %s", self._mouse_position_delay)
            except Exception:
                log("failed to calculate automatic delay", exc_info=True)