Example #1
0
def do_set_keymap(xkbmap_layout, xkbmap_variant,
                  xkbmap_print, xkbmap_query):
    """ xkbmap_layout is the generic layout name (used on non posix platforms)
        xkbmap_variant is the layout variant (may not be set)
        xkbmap_print is the output of "setxkbmap -print" on the client
        xkbmap_query is the output of "setxkbmap -query" on the client
        Use those to try to setup the correct keyboard map for the client
        so that all the keycodes sent will be mapped
    """
    #First we try to use data from setxkbmap -query
    if xkbmap_query:
        log.debug("do_set_keymap using xkbmap_query")
        """ The xkbmap_query data will look something like this:
        rules:      evdev
        model:      evdev
        layout:     gb
        options:    grp:shift_caps_toggle
        And we want to call something like:
        setxkbmap -rules evdev -model evdev -layout gb
        setxkbmap -option "" -option grp:shift_caps_toggle
        (we execute the options separately in case that fails..)
        """
        #parse the data into a dict:
        settings = {}
        opt_re = re.compile("(\w*):\s*(.*)")
        for line in xkbmap_query.splitlines():
            m = opt_re.match(line)
            if m:
                settings[m.group(1)] = m.group(2).strip()
        #construct the command line arguments for setxkbmap:
        args = ["setxkbmap"]
        used_settings = {}
        for setting in ["rules", "model", "layout"]:
            if setting in settings:
                value = settings.get(setting)
                args += ["-%s" % setting, value]
                used_settings[setting] = value
        if len(args)==1:
            log.warn("do_set_keymap could not find rules, model or layout in the xkbmap query string..")
        else:
            log.info("setting keymap: %s", ", ".join(["%s=%s" % (std(k), std(v)) for k,v in used_settings.items()]))
        exec_keymap_command(args)
        #try to set the options:
        if "options" in settings:
            log.info("setting keymap options: %s", std(str(settings.get("options"))))
            exec_keymap_command(["setxkbmap", "-option", "", "-option", settings.get("options")])
    elif xkbmap_print:
        debug("do_set_keymap using xkbmap_print")
        #try to guess the layout by parsing "setxkbmap -print"
        try:
            sym_re = re.compile("\s*xkb_symbols\s*{\s*include\s*\"([\w\+]*)")
            for line in xkbmap_print.splitlines():
                m = sym_re.match(line)
                if m:
                    layout = std(m.group(1))
                    log.info("guessing keyboard layout='%s'" % layout)
                    exec_keymap_command(["setxkbmap", layout])
                    break
        except Exception, e:
            log.info("error setting keymap: %s" % e)
Example #2
0
 def test_std(self):
     self.assertEqual(std(""), "")
     self.assertEqual(std("abcd"), "abcd")
     self.assertEqual(std("r1"), "r1")
     for invalid in ("*", "\n", "\r"):
         self.assertEqual(std(invalid), "")
         self.assertEqual(std("a" + invalid + "b"), "ab")
Example #3
0
    def parse_server_capabilities(self):
        for c in CLIENT_BASES:
            if not c.parse_server_capabilities(self):
                log.info("failed to parse server capabilities in %s", c)
                return  False
        c = self.server_capabilities
        self.server_session_name = strtobytes(c.rawget("session_name", b"")).decode("utf-8")
        set_name("Xpra", self.session_name or self.server_session_name or "Xpra")
        self.server_platform = c.strget("platform")
        self.server_sharing = c.boolget("sharing")
        self.server_sharing_toggle = c.boolget("sharing-toggle")
        self.server_lock = c.boolget("lock")
        self.server_lock_toggle = c.boolget("lock-toggle")
        self.server_keyboard = c.boolget("keyboard", True)
        self.server_toggle_keyboard_sync = self.server_keyboard and c.boolget("toggle_keyboard_sync", True)
        self.server_pointer = c.boolget("pointer", True)
        self.server_start_new_commands = c.boolget("start-new-commands")
        if self.server_start_new_commands:
            self.xdg_menu = c.dictget("xdg-menu")
        if self.start_new_commands or self.start_child_new_commands:
            if self.server_start_new_commands:
                self.after_handshake(self.send_start_new_commands)
            else:
                log.warn("Warning: cannot start new commands")
                log.warn(" the feature is currently disabled on the server")
        self.server_commands_info = c.boolget("server-commands-info")
        self.server_commands_signals = c.strlistget("server-commands-signals")
        self.server_readonly = c.boolget("readonly")
        if self.server_readonly and not self.readonly:
            log.info("server is read only")
            self.readonly = True
        if not self.server_keyboard and self.keyboard_helper:
            #swallow packets:
            def nosend(*args):
                pass
            self.keyboard_helper.send = nosend

        i = platform_name(self._remote_platform, c.strlistget("platform.linux_distribution") or c.strget("platform.release", ""))
        r = self._remote_version
        if self._remote_revision:
            r += "-r%s" % self._remote_revision
        mode = c.strget("server.mode", "server")
        bits = c.intget("python.bits", 32)
        log.info("Xpra %s server version %s %i-bit", mode, std(r), bits)
        if i:
            log.info(" running on %s", std(i))
        if c.boolget("proxy"):
            proxy_hostname = c.strget("proxy.hostname")
            proxy_platform = c.strget("proxy.platform")
            proxy_release = c.strget("proxy.platform.release")
            proxy_version = c.strget("proxy.version")
            proxy_version = c.strget("proxy.build.version", proxy_version)
            proxy_distro = c.strget("linux_distribution")
            msg = "via: %s proxy version %s" % (platform_name(proxy_platform, proxy_distro or proxy_release), std(proxy_version or "unknown"))
            if proxy_hostname:
                msg += " on '%s'" % std(proxy_hostname)
            log.info(msg)
        return True
Example #4
0
def do_set_keymap(xkbmap_layout, xkbmap_variant,
                  xkbmap_print, xkbmap_query):
    """ xkbmap_layout is the generic layout name (used on non posix platforms)
        xkbmap_variant is the layout variant (may not be set)
        xkbmap_print is the output of "setxkbmap -print" on the client
        xkbmap_query is the output of "setxkbmap -query" on the client
        Use those to try to setup the correct keyboard map for the client
        so that all the keycodes sent will be mapped
    """
    #First we try to use data from setxkbmap -query
    if xkbmap_query:
        log("do_set_keymap using xkbmap_query")
        """ The xkbmap_query data will look something like this:
        rules:      evdev
        model:      evdev
        layout:     gb
        options:    grp:shift_caps_toggle
        (we execute the options separately in case that fails..)
        """
        #parse the data into a dict:
        settings = parse_xkbmap_query(xkbmap_query)
        rules = settings.get("rules")
        model = settings.get("model")
        layout = settings.get("layout")
        variant = settings.get("variant")
        options = settings.get("options")
        if layout:
            log.info("setting keymap: %s", ", ".join(["%s=%s" % (std(k), std(v)) for k,v in settings.items() if k in ["rules", "model", "layout"] and v]))
            try:
                X11Keyboard.setxkbmap(rules, model, layout, variant, options)
                return
            except:
                log.warn("failed to set exact keymap using %s", settings)
            if options:
                #try again with no options:
                try:
                    X11Keyboard.setxkbmap(rules, model, layout, variant, "")
                except:
                    log.error("failed to set exact keymap even without applying options")
    if xkbmap_print:
        log("do_set_keymap using xkbmap_print")
        #try to guess the layout by parsing "setxkbmap -print"
        try:
            sym_re = re.compile("\s*xkb_symbols\s*{\s*include\s*\"([\w\+]*)")
            for line in xkbmap_print.splitlines():
                m = sym_re.match(line)
                if m:
                    layout = std(m.group(1))
                    log.info("guessing keyboard layout='%s'" % layout)
                    X11Keyboard.setxkbmap("", "pc104", layout, "", "")
                    return
        except Exception as e:
            log.info("error setting keymap: %s" % e)
    #fallback:
    layout = xkbmap_layout or "us"
    log.info("setting keyboard layout to '%s'", std(layout))
    X11Keyboard.setxkbmap("", "", layout, xkbmap_variant, "")
Example #5
0
def do_set_keymap(xkbmap_layout, xkbmap_variant, xkbmap_options,
                  xkbmap_print, xkbmap_query, xkbmap_query_struct={}):
    """ xkbmap_layout is the generic layout name (used on non posix platforms)
        xkbmap_variant is the layout variant (may not be set)
        xkbmap_print is the output of "setxkbmap -print" on the client
        xkbmap_query is the output of "setxkbmap -query" on the client
        xkbmap_query_struct is xkbmap_query parsed into a dictionary
        Use those to try to setup the correct keyboard map for the client
        so that all the keycodes sent will be mapped
    """
    #First we try to use data from setxkbmap -query,
    #preferably as structured data:
    if xkbmap_query and not xkbmap_query_struct:
        from xpra.keyboard.layouts import parse_xkbmap_query
        xkbmap_query_struct = parse_xkbmap_query(xkbmap_query)
    if xkbmap_query_struct:
        log("do_set_keymap using xkbmap_query struct=%s", xkbmap_query_struct)
        """ The xkbmap_query_struct data will look something like this:
            {
            b"rules"       : b"evdev",
            b"model"       : b"pc105",
            b"layout"      : b"gb",
            b"options"     : b"grp:shift_caps_toggle",
            }
        """
        #parse the data into a dict:
        rules = xkbmap_query_struct.get(b"rules")
        model = xkbmap_query_struct.get(b"model")
        layout = xkbmap_query_struct.get(b"layout")
        variant = xkbmap_query_struct.get(b"variant")
        options = xkbmap_query_struct.get(b"options")
        if layout:
            log.info("setting keymap: %s",
                     csv("%s=%s" % (std(k), std(v)) for k,v in xkbmap_query_struct.items()
                         if k in ("rules", "model", "layout") and v))
            safe_setxkbmap(rules, model, layout, variant, options)
        else:
            safe_setxkbmap(rules, model, "", "", "")
    if xkbmap_print:
        #TODO: this is no longer used with any client, remove it
        log("do_set_keymap using xkbmap_print")
        #try to guess the layout by parsing "setxkbmap -print"
        try:
            sym_re = re.compile(r"\s*xkb_symbols\s*{\s*include\s*\"([\w\+]*)")
            for line in xkbmap_print.splitlines():
                m = sym_re.match(line)
                if m:
                    layout = std(m.group(1))
                    log.info("guessing keyboard layout='%s'" % layout)
                    safe_setxkbmap("evdev", "pc105", layout, "", xkbmap_options)
                    return
        except Exception as e:
            log.info("error setting keymap: %s" % e)
    #fallback for non X11 clients:
    layout = xkbmap_layout or "us"
    log.info("setting keyboard layout to '%s'", std(layout))
    safe_setxkbmap("evdev", "pc105", layout, xkbmap_variant, xkbmap_options)
Example #6
0
def do_set_keymap(xkbmap_layout, xkbmap_variant,
                  xkbmap_print, xkbmap_query):
    """ xkbmap_layout is the generic layout name (used on non posix platforms)
        xkbmap_variant is the layout variant (may not be set)
        xkbmap_print is the output of "setxkbmap -print" on the client
        xkbmap_query is the output of "setxkbmap -query" on the client
        Use those to try to setup the correct keyboard map for the client
        so that all the keycodes sent will be mapped
    """
    #First we try to use data from setxkbmap -query
    if xkbmap_query:
        log("do_set_keymap using xkbmap_query")
        """ The xkbmap_query data will look something like this:
        rules:      evdev
        model:      evdev
        layout:     gb
        options:    grp:shift_caps_toggle
        And we want to call something like:
        setxkbmap -rules evdev -model evdev -layout gb
        setxkbmap -option "" -option grp:shift_caps_toggle
        (we execute the options separately in case that fails..)
        """
        #parse the data into a dict:
        settings = parse_xkbmap_query(xkbmap_query)
        #construct the command line arguments for setxkbmap:
        args = ["setxkbmap"]
        used_settings = {}
        for setting in ["rules", "model", "layout"]:
            if setting in settings:
                value = settings.get(setting)
                args += ["-%s" % setting, value]
                used_settings[setting] = value
        if len(args)==1:
            log.warn("do_set_keymap could not find rules, model or layout in the xkbmap query string..")
        else:
            log.info("setting keymap: %s", ", ".join(["%s=%s" % (std(k), std(v)) for k,v in used_settings.items()]))
        exec_keymap_command(args)
        #try to set the options:
        if "options" in settings:
            log.info("setting keymap options: %s", std(str(settings.get("options"))))
            exec_keymap_command(["setxkbmap", "-option", "", "-option", settings.get("options")])
    elif xkbmap_print:
        log("do_set_keymap using xkbmap_print")
        #try to guess the layout by parsing "setxkbmap -print"
        try:
            sym_re = re.compile("\s*xkb_symbols\s*{\s*include\s*\"([\w\+]*)")
            for line in xkbmap_print.splitlines():
                m = sym_re.match(line)
                if m:
                    layout = std(m.group(1))
                    log.info("guessing keyboard layout='%s'" % layout)
                    exec_keymap_command(["setxkbmap", layout])
                    break
        except Exception, e:
            log.info("error setting keymap: %s" % e)
Example #7
0
def do_set_keymap(xkbmap_layout, xkbmap_variant,
                  xkbmap_print, xkbmap_query):
    """ xkbmap_layout is the generic layout name (used on non posix platforms)
        xkbmap_variant is the layout variant (may not be set)
        xkbmap_print is the output of "setxkbmap -print" on the client
        xkbmap_query is the output of "setxkbmap -query" on the client
        Use those to try to setup the correct keyboard map for the client
        so that all the keycodes sent will be mapped
    """
    #First we try to use data from setxkbmap -query
    if xkbmap_query:
        log("do_set_keymap using xkbmap_query")
        """ The xkbmap_query data will look something like this:
        rules:      evdev
        model:      evdev
        layout:     gb
        options:    grp:shift_caps_toggle
        (we execute the options separately in case that fails..)
        """
        #parse the data into a dict:
        settings = parse_xkbmap_query(xkbmap_query)
        rules = settings.get("rules")
        model = settings.get("model")
        layout = settings.get("layout")
        variant = settings.get("variant")
        options = settings.get("options")
        log.info("setting keymap: %s", ", ".join(["%s=%s" % (std(k), std(v)) for k,v in settings.items() if k in ["rules", "model", "layout"] and v]))
        try:
            X11Keyboard.setxkbmap(rules, model, layout, variant, options)
        except:
            log.warn("failed to set exact keymap using %s", settings)
            #try again with no options:
            try:
                X11Keyboard.setxkbmap(rules, model, layout, variant, "")
            except:
                log.error("failed to set exact keymap even without applying options")
    elif xkbmap_print:
        log("do_set_keymap using xkbmap_print")
        #try to guess the layout by parsing "setxkbmap -print"
        try:
            sym_re = re.compile("\s*xkb_symbols\s*{\s*include\s*\"([\w\+]*)")
            for line in xkbmap_print.splitlines():
                m = sym_re.match(line)
                if m:
                    layout = std(m.group(1))
                    log.info("guessing keyboard layout='%s'" % layout)
                    X11Keyboard.setxkbmap("", "pc104", layout, "", "")
        except Exception as e:
            log.info("error setting keymap: %s" % e)
    else:
        layout = xkbmap_layout or "us"
        log.info("setting keyboard layout to '%s'", std(layout))
        X11Keyboard.setxkbmap("", "", layout, xkbmap_variant, "")
Example #8
0
 def get_connect_info(self):
     cinfo = []
     pinfo = ""
     if self.client_platform:
         pinfo = " %s" % platform_name(
             self.client_platform, self.client_linux_distribution
             or self.client_release)
     if self.client_session_type:
         pinfo += " %s" % self.client_session_type
     revinfo = ""
     if self.client_revision:
         revinfo = "-r%s" % self.client_revision
     bitsstr = ""
     if self.client_bits:
         bitsstr = " %i-bit" % self.client_bits
     cinfo.append("%s%s client version %s%s%s" %
                  (std(self.client_type), pinfo, std(
                      self.client_version), std(revinfo), bitsstr))
     msg = ""
     if self.hostname:
         msg += "connected from '%s'" % std(self.hostname)
     if self.username:
         msg += " as '%s'" % std(self.username)
         if self.name and self.name != self.username:
             msg += " - '%s'" % std(self.name)
     if msg:
         cinfo.append(msg)
     if self.client_proxy:
         msg = "via %s proxy version %s" % (platform_name(
             self.proxy_platform,
             self.proxy_release), std(self.proxy_version or "unknown"))
         if self.proxy_hostname:
             msg += " on '%s'" % std(self.proxy_hostname)
         cinfo.append(msg)
     return cinfo
Example #9
0
    def parse_server_capabilities(self):
        for c in UIXpraClient.__bases__:
            if not c.parse_server_capabilities(self):
                log.info("failed to parse server capabilities in %s", c)
                return False
        c = self.server_capabilities
        self.server_session_name = strtobytes(c.rawget("session_name",
                                                       b"")).decode("utf-8")
        set_name("Xpra", self.session_name or self.server_session_name
                 or "Xpra")
        self.server_platform = c.strget("platform")
        self.server_sharing = c.boolget("sharing")
        self.server_sharing_toggle = c.boolget("sharing-toggle")
        self.server_lock = c.boolget("lock")
        self.server_lock_toggle = c.boolget("lock-toggle")
        self.server_start_new_commands = c.boolget("start-new-commands")
        self.server_commands_info = c.boolget("server-commands-info")
        self.server_commands_signals = c.strlistget("server-commands-signals")
        self.server_readonly = c.boolget("readonly")
        if self.server_readonly and not self.readonly:
            log.info("server is read only")
            self.readonly = True

        i = platform_name(
            self._remote_platform,
            c.strlistget("platform.linux_distribution")
            or c.strget("platform.release", ""))
        r = self._remote_version
        if self._remote_revision:
            r += "-r%s" % self._remote_revision
        mode = c.strget("server.mode", "server")
        bits = c.intget("python.bits", 32)
        log.info("Xpra %s server version %s %i-bit", mode, std(r), bits)
        if i:
            log.info(" running on %s", std(i))
        if c.boolget("proxy"):
            proxy_hostname = c.strget("proxy.hostname")
            proxy_platform = c.strget("proxy.platform")
            proxy_release = c.strget("proxy.platform.release")
            proxy_version = c.strget("proxy.version")
            proxy_version = c.strget("proxy.build.version", proxy_version)
            proxy_distro = c.strget("linux_distribution")
            msg = "via: %s proxy version %s" % (platform_name(
                proxy_platform, proxy_distro
                or proxy_release), std(proxy_version or "unknown"))
            if proxy_hostname:
                msg += " on '%s'" % std(proxy_hostname)
            log.info(msg)
        return True
Example #10
0
 def handle(self, packet):
     prompt = "password"
     digest = bytestostr(packet[3])
     if digest.startswith("gss:") or digest.startswith("kerberos:"):
         prompt = "%s token" % (digest.split(":", 1)[0])
     if len(packet) >= 6:
         prompt = std(bytestostr(packet[5]))
     return self.client.do_process_challenge_prompt(packet, prompt)
Example #11
0
 def process_challenge_prompt(self, packet):
     prompt = "password"
     digest = packet[3]
     if digest.startswith(b"gss:") or digest.startswith(b"kerberos:"):
         prompt = "%s token" % (digest.split(b":", 1)[0])
     if len(packet)>=6:
         prompt = std(packet[5])
     return self.do_process_challenge_prompt(packet, prompt)
Example #12
0
def do_set_keymap(xkbmap_layout, xkbmap_variant, xkbmap_options, xkbmap_query,
                  xkbmap_query_struct):
    """ xkbmap_layout is the generic layout name (used on non posix platforms)
        xkbmap_variant is the layout variant (may not be set)
        xkbmap_print is the output of "setxkbmap -print" on the client
        xkbmap_query is the output of "setxkbmap -query" on the client
        xkbmap_query_struct is xkbmap_query parsed into a dictionary
        Use those to try to setup the correct keyboard map for the client
        so that all the keycodes sent will be mapped
    """
    #First we try to use data from setxkbmap -query,
    #preferably as structured data:
    if xkbmap_query and not xkbmap_query_struct:
        xkbmap_query_struct = parse_xkbmap_query(xkbmap_query)
    xkbmap_query_struct = typedict(xkbmap_query_struct)
    if xkbmap_query_struct:
        log("do_set_keymap using xkbmap_query struct=%s", xkbmap_query_struct)
        #The xkbmap_query_struct data will look something like this:
        #    {
        #    b"rules"       : b"evdev",
        #    b"model"       : b"pc105",
        #    b"layout"      : b"gb",
        #    b"options"     : b"grp:shift_caps_toggle",
        #    }
        #parse the data into a dict:
        rules = xkbmap_query_struct.strget("rules")
        model = xkbmap_query_struct.strget("model")
        layout = xkbmap_query_struct.strget("layout")
        variant = xkbmap_query_struct.strget("variant")
        options = xkbmap_query_struct.strget("options")
        if layout:
            log.info(
                "setting keymap: %s",
                csv("%s=%s" % (std(k), std(v))
                    for k, v in xkbmap_query_struct.items()
                    if k in ("rules", "model", "layout", "variant",
                             "options") and v))
            safe_setxkbmap(rules, model, layout, variant, options)
        else:
            safe_setxkbmap(rules, model, "", "", "")
    #fallback for non X11 clients:
    layout = xkbmap_layout or "us"
    log.info("setting keyboard layout to '%s'", std(layout))
    safe_setxkbmap("evdev", "pc105", layout, xkbmap_variant, xkbmap_options)
Example #13
0
 def log_keyboard_info(self):
     #show the user a summary of what we have detected:
     kb_info = {}
     if self.xkbmap_query_struct or self.xkbmap_query:
         xkbqs = self.xkbmap_query_struct
         if xkbqs:
             #parse query into a dict
             from xpra.keyboard.layouts import parse_xkbmap_query
             xkbqs = parse_xkbmap_query(self.xkbmap_query)
         for x in ["rules", "model", "layout"]:
             v = xkbqs.get(x)
             if v:
                 kb_info[x] = v
     if self.xkbmap_layout:
         kb_info["layout"] = self.xkbmap_layout
     if len(kb_info)==0:
         log.info(" using default keyboard settings")
     else:
         log.info(" keyboard settings: %s", ", ".join(["%s=%s" % (std(k), std(v)) for k,v in kb_info.items()]))
Example #14
0
 def log_keyboard_info(self):
     #show the user a summary of what we have detected:
     kb_info = {}
     if self.xkbmap_query_struct or self.xkbmap_query:
         xkbqs = self.xkbmap_query_struct
         if xkbqs:
             #parse query into a dict
             from xpra.keyboard.layouts import parse_xkbmap_query
             xkbqs = parse_xkbmap_query(self.xkbmap_query)
         for x in ["rules", "model", "layout"]:
             v = xkbqs.get(x)
             if v:
                 kb_info[x] = v
     if self.xkbmap_layout:
         kb_info["layout"] = self.xkbmap_layout
     if len(kb_info)==0:
         log.info(" using default keyboard settings")
     else:
         log.info(" keyboard settings: %s", ", ".join(["%s=%s" % (std(k), std(v)) for k,v in kb_info.items()]))
Example #15
0
 def end_headers(self):
     #magic for querying request header values:
     path = getattr(self, "path", "")
     if path.endswith("?echo-headers"):
         #ie: "en-GB,en-US;q=0.8,en;q=0.6"
         accept = self.headers.get("Accept-Language")
         if accept:
             self.send_header("Echo-Accept-Language", std(accept, extras="-,./:;="))
     for k,v in self.get_headers().items():
         self.send_header(k, v)
     BaseHTTPRequestHandler.end_headers(self)
Example #16
0
 def end_headers(self):
     #magic for querying request header values:
     path = getattr(self, "path", "")
     if path.endswith("?echo-headers"):
         #ie: "en-GB,en-US;q=0.8,en;q=0.6"
         accept = self.headers.get("Accept-Language")
         if accept:
             self.send_header("Echo-Accept-Language", std(accept, extras="-,./:;="))
     if HTTP_NOCACHE:
         self.send_nocache_headers()
     WebSocketRequestHandler.end_headers(self)
Example #17
0
 def get_connect_info(self) -> list:
     cinfo = []
     #client platform / version info:
     pinfo = ""
     if self.client_platform:
         pinfo = " %s" % platform_name(
             self.client_platform, self.client_linux_distribution
             or self.client_release)
     if self.client_session_type:
         pinfo += " %s" % self.client_session_type
     revinfo = ""
     if self.client_revision:
         revinfo = "-r%s" % self.client_revision
     bitsstr = ""
     if self.client_bits:
         bitsstr = " %i-bit" % self.client_bits
     cinfo.append("%s%s client version %s%s%s" %
                  (std(self.client_type), pinfo, std(
                      self.client_version), std(revinfo), bitsstr))
     #opengl info:
     if self.client_opengl:
         msg = "OpenGL is "
         if not self.client_opengl.boolget("enabled"):
             msg += "disabled"
         else:
             msg += "enabled"
             driver_info = self.client_opengl.strget(
                 "renderer") or self.client_opengl.strget("vendor")
             if driver_info:
                 msg += " with %s" % driver_info
         cinfo.append(msg)
     #connection info:
     msg = ""
     if self.hostname:
         msg += "connected from '%s'" % std(self.hostname)
     if self.username:
         msg += " as '%s'" % std(self.username)
         if self.name and self.name != self.username:
             msg += " - '%s'" % std(self.name)
     if msg:
         cinfo.append(msg)
     #proxy info
     if self.client_proxy:
         msg = "via %s proxy version %s" % (platform_name(
             self.proxy_platform,
             self.proxy_release), std(self.proxy_version or "unknown"))
         if self.proxy_hostname:
             msg += " on '%s'" % std(self.proxy_hostname)
         cinfo.append(msg)
     return cinfo
Example #18
0
 def end_headers(self):
     #magic for querying request header values:
     path = getattr(self, "path", "")
     if path.endswith("?echo-headers"):
         #ie: "en-GB,en-US;q=0.8,en;q=0.6"
         accept = self.headers.get("Accept-Language")
         if accept:
             self.extra_headers["Echo-Accept-Language"] = std(accept, extras="-,./:;=")
     headers = self.get_headers()
     if self.extra_headers:
         headers.update(self.extra_headers)
     if headers:
         for k,v in headers.items():
             self.send_header(k, v)
     super().end_headers()
Example #19
0
 def __init__(self, **kwargs):
     self.username = kwargs.get("username", get_username())
     if str(kwargs.get("client-username",
                       self.CLIENT_USERNAME)).lower() in TRUE_OPTIONS:
         #allow the client to specify the username to authenticate with:
         self.username = kwargs.get("remote",
                                    {}).get("username", self.username)
     self.salt = None
     self.digest = None
     self.salt_digest = None
     prompt_attr = {"username": std(self.username)}
     self.prompt = kwargs.pop("prompt",
                              self.DEFAULT_PROMPT).format(**prompt_attr)
     self.socket_dirs = kwargs.pop("socket-dirs", get_socket_dirs())
     self.challenge_sent = False
     self.passed = False
     self.password_used = None
     #we can't warn about unused options
     #because the options are shared with other socket options (nodelay, cork, etc)
     #unused = dict((k,v) for k,v in kwargs.items() if k not in ("connection", "exec_cwd", "username"))
     #if unused:
     #    log.warn("Warning: unused keyword arguments for %s authentication:", self)
     #    log.warn(" %s", unused)
     log("auth prompt=%s, socket_dirs=%s", self.prompt, self.socket_dirs)
Example #20
0
 def process_server_packet(self, proto, packet):
     packet_type = packet[0]
     log("process_server_packet: %s", packet_type)
     if packet_type==Protocol.CONNECTION_LOST:
         self.stop("server connection lost", proto)
         return
     elif packet_type=="disconnect":
         log("got disconnect from server: %s", packet[1])
         if self.exit:
             self.server_protocol.close()
         else:
             self.stop("disconnect from server: %s" % packet[1])
     elif packet_type=="hello":
         c = typedict(packet[1])
         maxw, maxh = c.intpair("max_desktop_size", (4096, 4096))
         caps = self.filter_server_caps(c)
         #add new encryption caps:
         if self.cipher:
             from xpra.net.crypto import crypto_backend_init, new_cipher_caps, DEFAULT_PADDING
             crypto_backend_init()
             padding_options = self.caps.strlistget("cipher.padding.options", [DEFAULT_PADDING])
             auth_caps = new_cipher_caps(self.client_protocol, self.cipher, self.encryption_key, padding_options)
             caps.update(auth_caps)
         #may need to bump packet size:
         proto.max_packet_size = maxw*maxh*4*4
         file_transfer = self.caps.boolget("file-transfer") and c.boolget("file-transfer")
         file_size_limit = max(self.caps.intget("file-size-limit"), c.intget("file-size-limit"))
         file_max_packet_size = int(file_transfer) * (1024 + file_size_limit*1024*1024)
         self.client_protocol.max_packet_size = max(self.client_protocol.max_packet_size, file_max_packet_size)
         self.server_protocol.max_packet_size = max(self.server_protocol.max_packet_size, file_max_packet_size)
         packet = ("hello", caps)
     elif packet_type=="info-response":
         #adds proxy info:
         #note: this is only seen by the client application
         #"xpra info" is a new connection, which talks to the proxy server...
         info = packet[1]
         info.update(self.get_proxy_info(proto))
     elif packet_type=="lost-window":
         wid = packet[1]
         #mark it as lost so we can drop any current/pending frames
         self.lost_windows.add(wid)
         #queue it so it gets cleaned safely (for video encoders mostly):
         self.encode_queue.put(packet)
         #and fall through so tell the client immediately
     elif packet_type=="draw":
         #use encoder thread:
         self.encode_queue.put(packet)
         #which will queue the packet itself when done:
         return
     #we do want to reformat cursor packets...
     #as they will have been uncompressed by the network layer already:
     elif packet_type=="cursor":
         #packet = ["cursor", x, y, width, height, xhot, yhot, serial, pixels, name]
         #or:
         #packet = ["cursor", "png", x, y, width, height, xhot, yhot, serial, pixels, name]
         #or:
         #packet = ["cursor", ""]
         if len(packet)>=8:
             #hard to distinguish png cursors from normal cursors...
             try:
                 int(packet[1])
                 self._packet_recompress(packet, 8, "cursor")
             except:
                 self._packet_recompress(packet, 9, "cursor")
     elif packet_type=="window-icon":
         self._packet_recompress(packet, 5, "icon")
     elif packet_type=="send-file":
         if packet[6]:
             packet[6] = Compressed("file-data", packet[6])
     elif packet_type=="send-file-chunk":
         if packet[3]:
             packet[3] = Compressed("file-chunk-data", packet[3])
     elif packet_type=="challenge":
         from xpra.net.crypto import get_salt
         #client may have already responded to the challenge,
         #so we have to handle authentication from this end
         salt = packet[1]
         digest = packet[3]
         client_salt = get_salt(len(salt))
         salt = xor_str(salt, client_salt)
         if digest!=b"hmac":
             self.stop("digest mode '%s' not supported", std(digest))
             return
         password = self.session_options.get("password")
         if not password:
             self.stop("authentication requested by the server, but no password available for this session")
             return
         import hmac, hashlib
         password = strtobytes(password)
         salt = strtobytes(salt)
         challenge_response = hmac.HMAC(password, salt, digestmod=hashlib.md5).hexdigest()
         log.info("sending %s challenge response", digest)
         self.send_hello(challenge_response, client_salt)
         return
     self.queue_client_packet(packet)
Example #21
0
    def parse_server_capabilities(self, c : typedict) -> bool:
        for cb in CLIENT_BASES:
            if not cb.parse_server_capabilities(self, c):
                log.info("failed to parse server capabilities in %s", cb)
                return False
        self.server_session_name = c.uget("session_name")
        set_name("Xpra", self.session_name or self.server_session_name or "Xpra")
        self.server_platform = c.strget("platform")
        self.server_sharing = c.boolget("sharing")
        self.server_sharing_toggle = c.boolget("sharing-toggle")
        self.server_lock = c.boolget("lock")
        self.server_lock_toggle = c.boolget("lock-toggle")
        self.server_keyboard = c.boolget("keyboard", True)
        self.server_pointer = c.boolget("pointer", True)
        self.server_start_new_commands = c.boolget("start-new-commands")
        if self.server_start_new_commands:
            self.server_xdg_menu = c.dictget("xdg-menu", None)
        if self.start_new_commands or self.start_child_new_commands:
            if self.server_start_new_commands:
                self.after_handshake(self.send_start_new_commands)
            else:
                log.warn("Warning: cannot start new commands")
                log.warn(" the feature is currently disabled on the server")
        self.server_commands_info = c.boolget("server-commands-info")
        self.server_commands_signals = c.strtupleget("server-commands-signals")
        self.server_readonly = c.boolget("readonly")
        if self.server_readonly and not self.readonly:
            log.info("server is read only")
            self.readonly = True
        if not self.server_keyboard and self.keyboard_helper:
            #swallow packets:
            def nosend(*_args):
                pass
            self.keyboard_helper.send = nosend

        i = platform_name(self._remote_platform,
                          c.strtupleget("platform.linux_distribution") or c.strget("platform.release", ""))
        r = self._remote_version
        if self._remote_revision:
            r += "-r%s" % self._remote_revision
        mode = c.strget("server.mode", "server")
        bits = c.intget("python.bits", 32)
        log.info("Xpra %s server version %s %i-bit", mode, std(r), bits)
        if i:
            log.info(" running on %s", std(i))
        if c.boolget("desktop") or c.boolget("shadow"):
            v = c.intpair("actual_desktop_size")
            if v:
                w, h = v
                ss = c.tupleget("screen_sizes")
                if ss:
                    log.info(" remote desktop size is %sx%s with %s screen%s:", w, h, len(ss), engs(ss))
                    log_screen_sizes(w, h, ss)
                else:
                    log.info(" remote desktop size is %sx%s", w, h)
        if c.boolget("proxy"):
            proxy_hostname = c.strget("proxy.hostname")
            proxy_platform = c.strget("proxy.platform")
            proxy_release = c.strget("proxy.platform.release")
            proxy_version = c.strget("proxy.version")
            proxy_version = c.strget("proxy.build.version", proxy_version)
            proxy_distro = c.strget("proxy.linux_distribution")
            msg = "via: %s proxy version %s" % (
                platform_name(proxy_platform, proxy_distro or proxy_release),
                std(proxy_version or "unknown")
                )
            if proxy_hostname:
                msg += " on '%s'" % std(proxy_hostname)
            log.info(msg)
        return True
Example #22
0
        log("do_set_keymap using xkbmap_print")
        #try to guess the layout by parsing "setxkbmap -print"
        try:
            sym_re = re.compile("\s*xkb_symbols\s*{\s*include\s*\"([\w\+]*)")
            for line in xkbmap_print.splitlines():
                m = sym_re.match(line)
                if m:
                    layout = std(m.group(1))
                    log.info("guessing keyboard layout='%s'" % layout)
                    exec_keymap_command(["setxkbmap", layout])
                    break
        except Exception, e:
            log.info("error setting keymap: %s" % e)
    else:
        layout = xkbmap_layout or "us"
        log.info("setting keyboard layout to '%s'", std(layout))
        set_layout = ["setxkbmap", "-layout", layout]
        if xkbmap_variant:
            set_layout += ["-variant", xkbmap_variant]
        if not exec_keymap_command(set_layout) and xkbmap_variant:
            log.info("error setting keymap with variant %s, retrying with just layout %s", std(xkbmap_variant), std(layout))
            set_layout = ["setxkbmap", "-layout", layout]
            exec_keymap_command(set_layout)

    display = os.environ.get("DISPLAY")
    if xkbmap_print:
        #there may be a junk header, if so remove it:
        pos = xkbmap_print.find("xkb_keymap {")
        if pos>0:
            xkbmap_print = xkbmap_print[pos:]
        log.info("setting full keymap definition from client via xkbcomp")
Example #23
0
    def do_update_screen(self):
        self.log("do_update_screen()")
        #c = self.stdscr.getch()
        #if c==curses.KEY_RESIZE:
        height, width = self.stdscr.getmaxyx()
        #log.info("update_screen() %ix%i", height, width)
        title = get_title()
        sli = self.server_last_info

        def _addstr(pad, y, x, s, *args):
            if len(s) + x >= width - pad:
                s = s[:max(0, width - x - 2 - pad)] + ".."
            self.stdscr.addstr(y, x, s, *args)

        def addstr_main(y, x, s, *args):
            _addstr(0, y, x, s, *args)

        def addstr_box(y, x, s, *args):
            _addstr(2, y, x, s, *args)

        try:
            x = max(0, width // 2 - len(title) // 2)
            addstr_main(0, x, title, curses.A_BOLD)
            if height <= 1:
                return
            server_info = self.slidictget("server")
            build = self.slidictget("server", "build")
            vstr = caps_to_version(build)
            mode = server_info.strget("mode", "server")
            python_info = typedict(server_info.dictget("python", {}))
            bits = python_info.intget("bits", 32)
            server_str = "Xpra %s server version %s %i-bit" % (mode, vstr,
                                                               bits)
            proxy_info = self.slidictget("proxy")
            if proxy_info:
                proxy_platform_info = typedict(
                    proxy_info.dictget("platform", {}))
                proxy_platform = proxy_platform_info.strget("")
                proxy_release = proxy_platform_info.strget("release")
                proxy_build_info = typedict(proxy_info.dictget("build", {}))
                proxy_version = proxy_build_info.strget("version")
                proxy_distro = proxy_info.strget("linux_distribution")
                server_str += " via: %s proxy version %s" % (platform_name(
                    proxy_platform, proxy_distro
                    or proxy_release), std(proxy_version or "unknown"))
            addstr_main(1, 0, server_str)
            if height <= 2:
                return
            #load and uptime:
            now = datetime.now()
            uptime = ""
            elapsed_time = server_info.intget("elapsed_time")
            if elapsed_time:
                td = timedelta(seconds=elapsed_time)
                uptime = " up %s" % str(td).lstrip("0:")
            clients_info = self.slidictget("clients")
            nclients = clients_info.intget("")
            load_average = ""
            load = sli.inttupleget("load")
            if load and len(load) == 3:
                float_load = tuple(v / 1000.0 for v in load)
                load_average = ", load average: %1.2f, %1.2f, %1.2f" % float_load
            addstr_main(
                2, 0, "xpra top - %s%s, %2i users%s" %
                (now.strftime("%H:%M:%S"), uptime, nclients, load_average))
            if height <= 3:
                return
            thread_info = self.slidictget("threads")
            rinfo = "%i threads" % thread_info.intget("count")
            server_pid = server_info.intget("pid", 0)
            if server_pid:
                rinfo += ", pid %i" % server_pid
                machine_id = server_info.get("machine-id")
                if machine_id is None or machine_id == get_machine_id():
                    try:
                        process = self.psprocess.get(server_pid)
                        if not process:
                            import psutil
                            process = psutil.Process(server_pid)
                            self.psprocess[server_pid] = process
                        else:
                            cpu = process.cpu_percent()
                            rinfo += ", %i%% CPU" % (cpu)
                    except Exception:
                        pass
            cpuinfo = self.slidictget("cpuinfo")
            if cpuinfo:
                rinfo += ", %s" % cpuinfo.strget("hz_actual")
            elapsed = monotonic_time() - self.server_last_info_time
            color = WHITE
            if self.server_last_info_time == 0:
                rinfo += " - no server data"
            elif elapsed > 2:
                rinfo += " - last updated %i seconds ago" % elapsed
                color = RED
            addstr_main(3, 0, rinfo, curses.color_pair(color))
            if height <= 4:
                return
            #display:
            dinfo = []
            server = self.slidictget("server")
            rws = server.intpair("root_window_size", None)
            if rws:
                sinfo = "%ix%i display" % (rws[0], rws[1])
                mds = server.intpair("max_desktop_size")
                if mds:
                    sinfo += " (max %ix%i)" % (mds[0], mds[1])
                dinfo.append(sinfo)
            cursor_info = self.slidictget("cursor")
            if cursor_info:
                cx, cy = cursor_info.inttupleget("position", (0, 0))
                dinfo.append("cursor at %ix%i" % (cx, cy))
            display_info = self.slidictget("display")
            pid = display_info.intget("pid")
            if pid:
                dinfo.append("pid %i" % pid)
            addstr_main(4, 0, csv(dinfo))
            if height <= 5:
                return
            hpos = 5
            gl_info = self.get_gl_info(display_info.dictget("opengl"))
            if gl_info:
                addstr_main(5, 0, gl_info)
                hpos += 1

            if hpos < height - 3:
                hpos += 1
                if nclients == 0:
                    addstr_main(hpos, 0, "no clients connected")
                else:
                    addstr_main(
                        hpos, 0,
                        "%i client%s connected:" % (nclients, engs(nclients)))
                hpos += 1
            client_info = self.slidictget("client")
            client_no = 0
            while True:
                ci = client_info.dictget(client_no)
                if not ci:
                    break
                client_no += 1
                ci = typedict(ci)
                session_id = ci.strget("session-id")
                if session_id:
                    #don't show ourselves:
                    if session_id == self.session_id:
                        continue
                elif not ci.boolget("windows", True):
                    #for older servers, hide any client that doesn't display windows:
                    continue
                ci = self.get_client_info(ci)
                l = len(ci)
                if hpos + 2 + l > height:
                    if hpos < height:
                        more = nclients - client_no
                        addstr_box(
                            hpos, 0,
                            "%i client%s not shown" % (more, engs(more)),
                            curses.A_BOLD)
                    break
                self.box(1, hpos, width - 2, 2 + l)
                for i, info in enumerate(ci):
                    info_text, color = info
                    cpair = curses.color_pair(color)
                    addstr_box(hpos + i + 1, 2, info_text, cpair)
                hpos += 2 + l

            windows = self.slidictget("windows")
            if hpos < height - 3:
                hpos += 1
                addstr_main(hpos, 0,
                            "%i window%s:" % (len(windows), engs(windows)))
                hpos += 1
            wins = tuple(windows.values())
            nwindows = len(wins)
            for win_no, win in enumerate(wins):
                wi = self.get_window_info(typedict(win))
                l = len(wi)
                if hpos + 2 + l > height:
                    if hpos < height:
                        more = nwindows - win_no
                        addstr_main(hpos, 0, "terminal window is too small: %i window%s not shown" % \
                                           (more, engs(more)), curses.A_BOLD)
                    break
                self.box(1, hpos, width - 2, 2 + l)
                for i, info in enumerate(wi):
                    info_text, color = info
                    cpair = curses.color_pair(color)
                    addstr_box(hpos + i + 1, 2, info_text, cpair)
                hpos += 2 + l
        except Exception as e:
            self.err(e)
 def process_server_packet(self, proto, packet):
     packet_type = packet[0]
     log("process_server_packet: %s", packet_type)
     if packet_type==Protocol.CONNECTION_LOST:
         self.stop("server connection lost", proto)
         return
     elif packet_type=="disconnect":
         log("got disconnect from server: %s", packet[1])
         if self.exit:
             self.server_protocol.close()
         else:
             self.stop("disconnect from server: %s" % packet[1])
     elif packet_type=="hello":
         c = typedict(packet[1])
         maxw, maxh = c.intpair("max_desktop_size", (4096, 4096))
         caps = self.filter_server_caps(c)
         #add new encryption caps:
         if self.cipher:
             from xpra.net.crypto import crypto_backend_init, new_cipher_caps, DEFAULT_PADDING
             crypto_backend_init()
             padding_options = self.caps.strlistget("cipher.padding.options", [DEFAULT_PADDING])
             auth_caps = new_cipher_caps(self.client_protocol, self.cipher, self.encryption_key, padding_options)
             caps.update(auth_caps)
         #may need to bump packet size:
         proto.max_packet_size = maxw*maxh*4*4
         file_transfer = self.caps.boolget("file-transfer") and c.boolget("file-transfer")
         file_size_limit = max(self.caps.intget("file-size-limit"), c.intget("file-size-limit"))
         file_max_packet_size = int(file_transfer) * (1024 + file_size_limit*1024*1024)
         self.client_protocol.max_packet_size = max(self.client_protocol.max_packet_size, file_max_packet_size)
         self.server_protocol.max_packet_size = max(self.server_protocol.max_packet_size, file_max_packet_size)
         packet = ("hello", caps)
     elif packet_type=="info-response":
         #adds proxy info:
         #note: this is only seen by the client application
         #"xpra info" is a new connection, which talks to the proxy server...
         info = packet[1]
         info.update(self.get_proxy_info(proto))
     elif packet_type=="lost-window":
         wid = packet[1]
         #mark it as lost so we can drop any current/pending frames
         self.lost_windows.add(wid)
         #queue it so it gets cleaned safely (for video encoders mostly):
         self.encode_queue.put(packet)
         #and fall through so tell the client immediately
     elif packet_type=="draw":
         #use encoder thread:
         self.encode_queue.put(packet)
         #which will queue the packet itself when done:
         return
     #we do want to reformat cursor packets...
     #as they will have been uncompressed by the network layer already:
     elif packet_type=="cursor":
         #packet = ["cursor", x, y, width, height, xhot, yhot, serial, pixels, name]
         #or:
         #packet = ["cursor", "png", x, y, width, height, xhot, yhot, serial, pixels, name]
         #or:
         #packet = ["cursor", ""]
         if len(packet)>=8:
             #hard to distinguish png cursors from normal cursors...
             try:
                 int(packet[1])
                 self._packet_recompress(packet, 8, "cursor")
             except:
                 self._packet_recompress(packet, 9, "cursor")
     elif packet_type=="window-icon":
         self._packet_recompress(packet, 5, "icon")
     elif packet_type=="send-file":
         if packet[6]:
             packet[6] = Compressed("file-data", packet[6])
     elif packet_type=="send-file-chunk":
         if packet[3]:
             packet[3] = Compressed("file-chunk-data", packet[3])
     elif packet_type=="challenge":
         from xpra.net.crypto import get_salt
         #client may have already responded to the challenge,
         #so we have to handle authentication from this end
         salt = packet[1]
         digest = packet[3]
         client_salt = get_salt(len(salt))
         salt = xor_str(salt, client_salt)
         if digest!=b"hmac":
             self.stop("digest mode '%s' not supported", std(digest))
             return
         password = self.disp_desc.get("password", self.session_options.get("password"))
         log("password from %s / %s = %s", self.disp_desc, self.session_options, password)
         if not password:
             self.stop("authentication requested by the server, but no password available for this session")
             return
         import hmac, hashlib
         password = strtobytes(password)
         salt = strtobytes(salt)
         challenge_response = hmac.HMAC(password, salt, digestmod=hashlib.md5).hexdigest()
         log.info("sending %s challenge response", digest)
         self.send_hello(challenge_response, client_salt)
         return
     self.queue_client_packet(packet)
Example #25
0
def do_set_keymap(xkbmap_layout, xkbmap_variant,
                  xkbmap_print, xkbmap_query):
    """ xkbmap_layout is the generic layout name (used on non posix platforms)
        xkbmap_variant is the layout variant (may not be set)
        xkbmap_print is the output of "setxkbmap -print" on the client
        xkbmap_query is the output of "setxkbmap -query" on the client
        Use those to try to setup the correct keyboard map for the client
        so that all the keycodes sent will be mapped
    """
    #First we try to use data from setxkbmap -query
    if xkbmap_query:
        log("do_set_keymap using xkbmap_query")
        """ The xkbmap_query data will look something like this:
        rules:      evdev
        model:      evdev
        layout:     gb
        options:    grp:shift_caps_toggle
        And we want to call something like:
        setxkbmap -rules evdev -model evdev -layout gb
        setxkbmap -option "" -option grp:shift_caps_toggle
        (we execute the options separately in case that fails..)
        """
        #parse the data into a dict:
        settings = parse_xkbmap_query(xkbmap_query)
        #construct the command line arguments for setxkbmap:
        args = ["setxkbmap"]
        used_settings = {}
        for setting in ["rules", "model", "layout"]:
            if setting in settings:
                value = settings.get(setting)
                args += ["-%s" % setting, value]
                used_settings[setting] = value
        if len(args)==1:
            log.warn("do_set_keymap could not find rules, model or layout in the xkbmap query string..")
        else:
            log.info("setting keymap: %s", ", ".join(["%s=%s" % (std(k), std(v)) for k,v in used_settings.items()]))
        exec_keymap_command(args)
        #try to set the options:
        if "options" in settings:
            log.info("setting keymap options: %s", std(str(settings.get("options"))))
            exec_keymap_command(["setxkbmap", "-option", "", "-option", settings.get("options")])
    elif xkbmap_print:
        log("do_set_keymap using xkbmap_print")
        #try to guess the layout by parsing "setxkbmap -print"
        try:
            sym_re = re.compile("\s*xkb_symbols\s*{\s*include\s*\"([\w\+]*)")
            for line in xkbmap_print.splitlines():
                m = sym_re.match(line)
                if m:
                    layout = std(m.group(1))
                    log.info("guessing keyboard layout='%s'" % layout)
                    exec_keymap_command(["setxkbmap", layout])
                    break
        except Exception as e:
            log.info("error setting keymap: %s" % e)
    else:
        layout = xkbmap_layout or "us"
        log.info("setting keyboard layout to '%s'", std(layout))
        set_layout = ["setxkbmap", "-layout", layout]
        if xkbmap_variant:
            set_layout += ["-variant", xkbmap_variant]
        if not exec_keymap_command(set_layout) and xkbmap_variant:
            log.info("error setting keymap with variant %s, retrying with just layout %s", std(xkbmap_variant), std(layout))
            set_layout = ["setxkbmap", "-layout", layout]
            exec_keymap_command(set_layout)

    display = os.environ.get("DISPLAY")
    if xkbmap_print:
        #there may be a junk header, if so remove it:
        pos = xkbmap_print.find("xkb_keymap {")
        if pos>0:
            xkbmap_print = xkbmap_print[pos:]
        log.info("setting full keymap definition from client via xkbcomp")
        exec_keymap_command(["xkbcomp", "-", display], xkbmap_print)
Example #26
0
    def do_update_screen(self):
        #c = self.stdscr.getch()
        #if c==curses.KEY_RESIZE:
        height, width = self.stdscr.getmaxyx()
        #log.info("update_screen() %ix%i", height, width)
        title = "Xpra top %s" % __version__
        try:
            from xpra.src_info import REVISION, LOCAL_MODIFICATIONS
            title += "-r%s" % REVISION
            if LOCAL_MODIFICATIONS:
                title += "M"
        except ImportError:
            pass
        x = max(0, width // 2 - len(title) // 2)
        sli = self.server_last_info
        try:
            self.stdscr.addstr(0, x, title, curses.A_BOLD)
            if height <= 1:
                return
            server_info = self.dictget("server")
            build = self.dictget("build")
            v = build.strget("version")
            revision = build.strget("revision")
            if v and revision:
                v = " version %s-r%s" % (v, revision)
            mode = server_info.strget("mode", "server")
            python_info = typedict(server_info.dictget("python", {}))
            bits = python_info.intget("bits", 32)
            server_str = "Xpra %s server%s %i-bit" % (mode, std(v), bits)
            proxy_info = self.dictget("proxy")
            if proxy_info:
                proxy_platform_info = typedict(
                    proxy_info.dictget("platform", {}))
                proxy_platform = proxy_platform_info.strget("")
                proxy_release = proxy_platform_info.strget("release")
                proxy_build_info = typedict(proxy_info.dictget("build", {}))
                proxy_version = proxy_build_info.strget("version")
                proxy_distro = proxy_info.strget("linux_distribution")
                server_str += " via: %s proxy version %s" % (platform_name(
                    proxy_platform, proxy_distro
                    or proxy_release), std(proxy_version or "unknown"))
            self.stdscr.addstr(1, 0, server_str)
            if height <= 2:
                return
            #load and uptime:
            now = datetime.now()
            uptime = ""
            elapsed_time = server_info.intget("elapsed_time")
            if elapsed_time:
                td = timedelta(seconds=elapsed_time)
                uptime = " up %s" % str(td).lstrip("0:")
            clients_info = self.dictget("clients")
            nclients = clients_info.intget("")
            load_average = ""
            load = sli.intlistget("load")
            if load and len(load) == 3:
                float_load = tuple(v / 1000.0 for v in load)
                load_average = ", load average: %1.2f, %1.2f, %1.2f" % float_load
            self.stdscr.addstr(
                2, 0, "xpra top - %s%s, %2i users%s" %
                (now.strftime("%H:%M:%S"), uptime, nclients, load_average))
            if height <= 3:
                return
            thread_info = self.dictget("threads")
            self.stdscr.addstr(3, 0,
                               "%i threads" % thread_info.intget("count"))
            if height <= 4:
                return
            #cursor:
            cursor_info = self.dictget("cursor")
            cx, cy = cursor_info.intlistget("position", (0, 0))
            self.stdscr.addstr(4, 0, "cursor at %ix%i" % (cx, cy))
            if height <= 5:
                return

            hpos = 6
            client_info = self.dictget("client")
            client_no = 0
            while True:
                ci = client_info.dictget(client_no)
                if not ci:
                    break
                client_no += 1
                ci = typedict(ci)
                if not ci.boolget("windows", True):
                    continue
                ci = self.get_client_info(ci)
                l = len(ci)
                if hpos + 2 + l > height:
                    if hpos < height:
                        more = nclients - client_no
                        self.stdscr.addstr(
                            hpos, 0,
                            "%i client%s not shown" % (more, engs(more)),
                            curses.A_BOLD)
                    break
                self.box(self.stdscr, 1, hpos, width - 2, 2 + l)
                for i, info in enumerate(ci):
                    info_text, color = info
                    cpair = curses.color_pair(color)
                    self.stdscr.addstr(hpos + i + 1, 2, info_text, cpair)
                hpos += 2 + l

            windows = self.dictget("windows")
            if hpos < height - 3:
                hpos += 1
                self.stdscr.addstr(hpos, 0, "%i windows" % len(windows))
                hpos += 1
            wins = tuple(windows.values())
            nwindows = len(wins)
            for win_no, win in enumerate(wins):
                wi = self.get_window_info(typedict(win))
                l = len(wi)
                if hpos + 2 + l > height:
                    if hpos < height:
                        more = nwindows - win_no
                        self.stdscr.addstr(
                            hpos, 0,
                            "terminal window is too small: %i window%s not shown"
                            % (more, engs(more)), curses.A_BOLD)
                    break
                self.box(self.stdscr, 1, hpos, width - 2, 2 + l)
                for i, info in enumerate(wi):
                    info_text, color = info
                    cpair = curses.color_pair(color)
                    self.stdscr.addstr(hpos + i + 1, 2, info_text, cpair)
                hpos += 2 + l
        except Exception as e:
            import traceback
            self.stdscr.addstr(0, 0, str(e))
            self.stdscr.addstr(0, 1, traceback.format_exc())
Example #27
0
        debug("do_set_keymap using xkbmap_print")
        #try to guess the layout by parsing "setxkbmap -print"
        try:
            sym_re = re.compile("\s*xkb_symbols\s*{\s*include\s*\"([\w\+]*)")
            for line in xkbmap_print.splitlines():
                m = sym_re.match(line)
                if m:
                    layout = std(m.group(1))
                    log.info("guessing keyboard layout='%s'" % layout)
                    exec_keymap_command(["setxkbmap", layout])
                    break
        except Exception, e:
            log.info("error setting keymap: %s" % e)
    else:
        layout = xkbmap_layout or "us"
        log.info("setting keyboard layout to '%s'", std(layout))
        set_layout = ["setxkbmap", "-layout", layout]
        if xkbmap_variant:
            set_layout += ["-variant", xkbmap_variant]
        if not exec_keymap_command(set_layout) and xkbmap_variant:
            log.info(
                "error setting keymap with variant %s, retrying with just layout %s",
                std(xkbmap_variant), std(layout))
            set_layout = ["setxkbmap", "-layout", layout]
            exec_keymap_command(set_layout)

    display = os.environ.get("DISPLAY")
    if xkbmap_print:
        #there may be a junk header, if so remove it:
        pos = xkbmap_print.find("xkb_keymap {")
        if pos > 0:
Example #28
0
def ssl_retry(e, ssl_ca_certs):
    SSL_RETRY = envbool("XPRA_SSL_RETRY", True)
    if not SSL_RETRY:
        return None
    if not isinstance(e, SSLVerifyFailure):
        return None
    #we may be able to ask the user if we wants to accept this certificate
    from xpra.log import Logger
    ssllog = Logger("ssl")
    verify_code = e.verify_code
    ssl_sock = e.ssl_sock
    msg = str(e)
    del e
    addr = ssl_sock.getpeername()[:2]
    port = addr[-1]
    server_hostname = ssl_sock.server_hostname
    ssllog("ssl_retry: peername=%s, server_hostname=%s", addr, server_hostname)
    if verify_code not in (
        SSL_VERIFY_SELF_SIGNED, SSL_VERIFY_WRONG_HOST,
        SSL_VERIFY_IP_MISMATCH, SSL_VERIFY_HOSTNAME_MISMATCH,
        ):
        ssllog("ssl_retry: %s not handled here", SSL_VERIFY_CODES.get(verify_code, verify_code))
        return None
    if not server_hostname:
        ssllog("ssl_retry: not server hostname")
        return None
    ssllog("ssl_retry: server_hostname=%s, ssl verify_code=%s (%i)",
           server_hostname, SSL_VERIFY_CODES.get(verify_code, verify_code), verify_code)
    from xpra.platform.paths import get_ssl_hosts_config_dirs
    from xpra.scripts.pinentry_wrapper import confirm
    host_dirname = std(server_hostname, extras="-.:#_")+"_%i" % port
    #self-signed cert:
    if verify_code==SSL_VERIFY_SELF_SIGNED:
        if ssl_ca_certs not in ("", "default"):
            ssllog("self-signed cert does not match %r", ssl_ca_certs)
            return None
        #perhaps we already have the certificate for this hostname
        dirs = get_ssl_hosts_config_dirs()
        host_dirs = [os.path.join(osexpand(d), host_dirname) for d in dirs]
        cert_filename = "cert.pem"
        ssllog("looking for %s in %s", cert_filename, host_dirs)
        for d in host_dirs:
            f = os.path.join(d, cert_filename)
            if os.path.exists(f):
                ssllog("found certificate for %s: %s", server_hostname, f)
                ssllog("retrying")
                return {"ssl_ca_certs" : f}
        #download the certificate data
        import ssl
        try:
            cert_data = ssl.get_server_certificate(addr)
        except ssl.SSLError:
            cert_data = None
        if not cert_data:
            ssllog("failed to get server certificate from %s", addr)
            return None
        ssllog("downloaded ssl cert data for %s: %s", addr, ellipsizer(cert_data))
        #ask the user if he wants to accept this certificate:
        title = "SSL Certificate Verification Failure"
        prompt = "Do you want to accept this certificate?"
        r = confirm((msg, ), title, prompt)
        ssllog("run_pinentry_confirm(..) returned %r", r)
        if not r:
            return None
        #if there is an existing host config dir, try to use it:
        for d in [x for x in host_dirs if os.path.exists(x)]:
            try:
                filename = os.path.join(d, cert_filename)
                with open(filename, "wb") as f:
                    f.write(cert_data.encode("latin1"))
                ssllog.info("saved SSL certificate to %s", filename)
                return {"ssl_ca_certs" : filename}
            except OSError:
                ssllog("failed to save cert data to %r", filename, exc_info=True)
        #try to create a host config dir:
        for d in host_dirs:
            folders = os.path.normpath(d).split(os.sep)
            #we have to be careful and create the 'ssl' dir with 0o700 permissions
            #but any directory above that can use 0o755
            try:
                ssl_dir_index = len(folders)-1
                while ssl_dir_index>0 and folders[ssl_dir_index]!="ssl":
                    ssl_dir_index -= 1
                if ssl_dir_index>1:
                    parent = os.path.join(*folders[:ssl_dir_index-1])
                    ssl_dir = os.path.join(*folders[:ssl_dir_index])
                    os.makedirs(parent, exist_ok=True)
                    os.makedirs(ssl_dir, mode=0o700, exist_ok=True)
                os.makedirs(d, mode=0o700)
                filename = os.path.join(d, cert_filename)
                with open(filename, "wb") as f:
                    f.write(cert_data.encode("latin1"))
                ssllog.info("saved SSL certificate to %s", filename)
                return {"ssl_ca_certs" : filename}
            except OSError:
                ssllog("failed to save cert data to %r", d, exc_info=True)
        ssllog.warn("Warning: failed to save certificate data")
        return None
    if verify_code in (SSL_VERIFY_WRONG_HOST, SSL_VERIFY_IP_MISMATCH, SSL_VERIFY_HOSTNAME_MISMATCH):
        #ask the user if he wants to skip verifying the host
        title = "SSL Certificate Verification Failure"
        prompt = "Do you want to connect anyway?"
        r = confirm((msg,), title, prompt)
        ssllog("run_pinentry_confirm(..) returned %r", r)
        if r:
            ssllog.info("retrying without checking the hostname")
            return {"ssl_check_hostname" : False}
    return None