Example #1
0
 def start_Xvfb(self, display=None, screens=[(1024, 768)]):
     assert POSIX
     if display is None:
         display = self.find_free_display()
     for x in list(os.environ.keys()):
         if x in ("LOGNAME", "USER", "PATH", "LANG", "TERM", "HOME",
                  "USERNAME", "PYTHONPATH",
                  "HOSTNAME"):  #DBUS_SESSION_BUS_ADDRESS
             #keep it
             continue
         try:
             del os.environ[x]
         except:
             pass
     if len(screens) > 1:
         cmd = [
             "Xvfb", "+extension", "Composite", "-nolisten", "tcp",
             "-noreset", "-auth", self.default_env["XAUTHORITY"]
         ]
         for i, screen in enumerate(screens):
             (w, h) = screen
             cmd += ["-screen", "%i" % i, "%ix%ix24+32" % (w, h)]
     else:
         xvfb_cmd = self.default_config.get("xvfb")
         assert xvfb_cmd, "no 'xvfb' command in default config"
         import shlex
         cmd = shlex.split(osexpand(xvfb_cmd))
         try:
             i = cmd.index("/etc/xpra/xorg.conf")
         except ValueError:
             i = -1
         if i > 0 and os.path.exists("./etc/xpra/xorg.conf"):
             cmd[i] = "./etc/xpra/xorg.conf"
     cmd.append(display)
     os.environ["DISPLAY"] = display
     os.environ["XPRA_LOG_DIR"] = "/tmp"
     cmd_expanded = [osexpand(v) for v in cmd]
     cmdstr = " ".join("'%s'" % x for x in cmd_expanded)
     if SHOW_XORG_OUTPUT:
         stdout = sys.stdout
         stderr = sys.stderr
     else:
         stdout = self._temp_file(prefix="Xorg-stdout-")
         log("stdout=%s for %s", stdout.name, cmd)
         stderr = self._temp_file(prefix="Xorg-stderr-")
         log("stderr=%s for %s", stderr.name, cmd)
     xvfb = self.run_command(cmd_expanded, stdout=stdout, stderr=stderr)
     time.sleep(1)
     log("xvfb(%s)=%s" % (cmdstr, xvfb))
     if pollwait(xvfb, XVFB_TIMEOUT) is not None:
         self.show_proc_error(
             xvfb, "xvfb command \"%s\" failed and returned %s" %
             (cmdstr, xvfb.poll()))
     return xvfb
Example #2
0
 def start_Xvfb(cls, display=None, screens=[(1024, 768)]):
     assert POSIX
     if display is None:
         display = cls.find_free_display()
     with OSEnvContext():
         XAUTHORITY = os.environ.get("XAUTHORITY",
                                     os.path.expanduser("~/.Xauthority"))
         for x in list(os.environ.keys()):
             if x in ("LOGNAME", "USER", "PATH", "LANG", "TERM", "HOME",
                      "USERNAME", "PYTHONPATH",
                      "HOSTNAME"):  #DBUS_SESSION_BUS_ADDRESS
                 #keep it
                 continue
             try:
                 del os.environ[x]
             except:
                 pass
         if len(screens) > 1:
             cmd = [
                 "Xvfb", "+extension", "Composite", "-nolisten", "tcp",
                 "-noreset", "-auth", XAUTHORITY
             ]
             for i, screen in enumerate(screens):
                 (w, h) = screen
                 cmd += ["-screen", "%i" % i, "%ix%ix24+32" % (w, h)]
         else:
             xvfb_cmd = cls.default_config.get("xvfb")
             assert xvfb_cmd, "no 'xvfb' command in default config"
             import shlex
             cmd = shlex.split(osexpand(xvfb_cmd))
             try:
                 i = cmd.index("/etc/xpra/xorg.conf")
             except ValueError:
                 i = -1
             if i > 0 and os.path.exists("./etc/xpra/xorg.conf"):
                 cmd[i] = "./etc/xpra/xorg.conf"
         cmd.append(display)
         os.environ["DISPLAY"] = display
         os.environ["XPRA_LOG_DIR"] = "/tmp"
         cmd_expanded = [osexpand(v) for v in cmd]
         cmdstr = " ".join("'%s'" % x for x in cmd_expanded)
         xvfb = cls.run_command(cmd_expanded,
                                stdout=sys.stdout,
                                stderr=sys.stderr)
         time.sleep(1)
         print("xvfb(%s)=%s" % (cmdstr, xvfb))
         assert pollwait(
             xvfb, XVFB_TIMEOUT
         ) is None, "xvfb command \"%s\" failed and returned %s" % (
             cmdstr, xvfb.poll())
         return xvfb
Example #3
0
 def _process_request_file(self, proto, packet):
     ss = self.get_server_source(proto)
     if not ss:
         printlog.warn("Warning: invalid client source for send-data-response packet")
         return
     argf = u(packet[1])
     openit = packet[2]
     filename = os.path.abspath(osexpand(argf))
     if not os.path.exists(filename):
         filelog.warn("Warning: the file requested does not exist:")
         filelog.warn(" %s", filename)
         ss.may_notify(XPRA_FILETRANSFER_NOTIFICATION_ID,
                       "File not found", "The file requested does not exist:\n%s" % filename,
                        icon_name="file")
         return
     try:
         stat = os.stat(filename)
         filelog("os.stat(%s)=%s", filename, stat)
     except os.error:
         filelog("os.stat(%s)", filename, exc_info=True)
     else:
         file_size = stat.st_size
         if file_size>self.file_transfer.file_size_limit or file_size>ss.file_size_limit:
             ss.may_notify(XPRA_FILETRANSFER_NOTIFICATION_ID,
                           "File too large",
                           "The file requested is too large to send:\n%s\nis %s" % (argf, std_unit(file_size)),
                            icon_name="file")
             return
     data = load_binary_file(filename)
     ss.send_file(filename, "", data, len(data), openit=openit, options={"request-file" : (argf, openit)})
Example #4
0
 def set_icon_from_data(self,
                        pixels,
                        has_alpha,
                        w,
                        h,
                        rowstride,
                        _options=None):
     self.clean_last_tmp_icon()
     #use a temporary file (yuk)
     from xpra.gtk_common.gtk_util import pixbuf_save_to_memory, get_pixbuf_from_data
     tray_icon = get_pixbuf_from_data(pixels, has_alpha, w, h, rowstride)
     png_data = pixbuf_save_to_memory(tray_icon)
     tmp_dir = osexpand(get_xpra_tmp_dir())
     if not os.path.exists(tmp_dir):
         os.mkdir(tmp_dir, 0o755)
     fd = None
     try:
         fd, self.tmp_filename = tempfile.mkstemp(prefix="tray",
                                                  suffix=".png",
                                                  dir=tmp_dir)
         log("set_icon_from_data%s using temporary file %s",
             ("%s pixels" % len(pixels), has_alpha, w, h, rowstride),
             self.tmp_filename)
         os.write(fd, png_data)
     except OSError as e:
         log("error saving temporary file", exc_info=True)
         log.error("Error saving icon data to temporary file")
         log.error(" %s", e)
         return
     finally:
         if fd:
             os.fchmod(fd, 0o644)
             os.close(fd)
     self.do_set_icon_from_file(self.tmp_filename)
Example #5
0
 def auth_publickey():
     log("trying public key authentication")
     for keyfile in ("id_rsa", "id_dsa"):
         keyfile_path = osexpand(os.path.join("~/", ".ssh", keyfile))
         if not os.path.exists(keyfile_path):
             log("no keyfile at '%s'", keyfile_path)
             continue
         key = None
         try:
             key = RSAKey.from_private_key_file(keyfile_path)
         except PasswordRequiredException:
             log("%s keyfile requires a passphrase", keyfile_path)
             passphrase = input_pass("please enter the passphrase for %s:" %
                                     (keyfile_path, ))
             if passphrase:
                 try:
                     key = RSAKey.from_private_key_file(
                         keyfile_path, passphrase)
                 except SSHException as e:
                     log("from_private_key_file", exc_info=True)
                     log.info("cannot load key from file '%s':",
                              keyfile_path)
                     log.info(" %s", e)
         if key:
             log("auth_publickey using %s: %s", keyfile_path, keymd5(key))
             try:
                 transport.auth_publickey(username, key)
             except SSHException as e:
                 log("key '%s' rejected", keyfile_path, exc_info=True)
                 log.info("SSH authentication using key '%s' failed:",
                          keyfile_path)
                 log.info(" %s", e)
             else:
                 if transport.is_authenticated():
                     break
Example #6
0
 def get_icon_string(self, nid: int, app_icon, icon):
     if app_icon and not os.path.isabs(app_icon):
         #safe to use
         return app_icon
     if icon and icon[0] == b"png":
         icon_data = icon[3]
         from xpra.platform.paths import get_xpra_tmp_dir
         tmp = osexpand(get_xpra_tmp_dir())
         d = tmp
         missing = []
         while d and not os.path.exists(d):
             missing.append(d)
             d = os.path.dirname(d)
         for d in reversed(missing):
             os.mkdir(d, 0o700)
         temp = tempfile.NamedTemporaryFile(
             mode='w+b',
             suffix='.png',
             prefix='xpra-notification-icon-',
             dir=tmp,
             delete=False)
         temp.write(icon_data)
         temp.close()
         self.temp_files[nid] = temp.name
         return temp.name
     return ""
Example #7
0
def find_ssl_cert(filename="ssl-cert.pem"):
    from xpra.log import Logger
    ssllog = Logger("ssl")
    #try to locate the cert file from known locations
    from xpra.platform.paths import get_ssl_cert_dirs  #pylint: disable=import-outside-toplevel
    dirs = get_ssl_cert_dirs()
    ssllog("find_ssl_cert(%s) get_ssl_cert_dirs()=%s", filename, dirs)
    for d in dirs:
        p = osexpand(d)
        if not os.path.exists(p):
            ssllog("ssl cert dir '%s' does not exist", p)
            continue
        f = os.path.join(p, "ssl-cert.pem")
        if not os.path.exists(f):
            ssllog("ssl cert '%s' does not exist", f)
            continue
        if not os.path.isfile(f):
            ssllog.warn("Warning: '%s' is not a file", f)
            continue
        if not os.access(p, os.R_OK):
            ssllog.info("SSL certificate file '%s' is not accessible", f)
            continue
        ssllog("found ssl cert '%s'", f)
        return f
    return None
Example #8
0
 def check_auth_publickey(self, username, key):
     log("check_auth_publickey(%s, %r) pubkey_auth=%s", username, key,
         self.pubkey_auth)
     if not self.pubkey_auth:
         return paramiko.AUTH_FAILED
     if not POSIX or getuid() != 0:
         import getpass
         sysusername = getpass.getuser()
         if sysusername != username:
             log.warn("Warning: ssh password authentication failed,")
             log.warn(" username does not match:")
             log.warn(" expected '%s', got '%s'", sysusername, username)
             return paramiko.AUTH_FAILED
     authorized_keys_filename = osexpand(AUTHORIZED_KEYS)
     if not os.path.exists(authorized_keys_filename) or not os.path.isfile(
             authorized_keys_filename):
         log("file '%s' does not exist", authorized_keys_filename)
         return paramiko.AUTH_FAILED
     import base64
     import binascii
     fingerprint = key.get_fingerprint()
     hex_fingerprint = binascii.hexlify(fingerprint)
     log("looking for key fingerprint '%s' in '%s'", hex_fingerprint,
         authorized_keys_filename)
     count = 0
     with open(authorized_keys_filename, "rb") as f:
         for line in f:
             if line.startswith("#"):
                 continue
             line = line.strip("\n\r")
             try:
                 key = base64.b64decode(
                     line.strip().split()[1].encode('ascii'))
             except Exception as e:
                 log("ignoring line '%s': %s", line, e)
                 continue
             import hashlib
             for hash_algo in AUTHORIZED_KEYS_HASHES:
                 hash_instance = None
                 try:
                     hash_class = getattr(hashlib,
                                          hash_algo)  #ie: hashlib.md5
                     hash_instance = hash_class(
                         key
                     )  #can raise ValueError (ie: on FIPS compliant systems)
                 except ValueError:
                     hash_instance = None
                 if not hash_instance:
                     if first_time("hash-%s-missing" % hash_algo):
                         log.warn("Warning: unsupported hash '%s'",
                                  hash_algo)
                     continue
                 fp_plain = hash_instance.hexdigest()
                 log("%s(%s)=%s", hash_algo, line, fp_plain)
                 if fp_plain == hex_fingerprint:
                     return paramiko.OPEN_SUCCEEDED
             count += 1
     log("no match in %i keys from '%s'", count, authorized_keys_filename)
     return paramiko.AUTH_FAILED
Example #9
0
File: ssh.py Project: qmutz/xpra
def get_default_keyfiles():
    dkf = os.environ.get("XPRA_SSH_DEFAULT_KEYFILES", None)
    if dkf is not None:
        return [x for x in dkf.split(":") if x]
    return [
        osexpand(os.path.join("~/", ".ssh", keyfile))
        for keyfile in ("id_ed25519", "id_ecdsa", "id_rsa", "id_dsa")
    ]
Example #10
0
 def __init__(self, **kwargs):
     self.app_id = kwargs.pop("app_id", APP_ID)
     key_hexstring = kwargs.pop("public_key", "")
     super().__init__(**kwargs)
     self.public_keys = {}
     key_strs = {}
     if key_hexstring:
         log("u2f_auth: public key from configuration=%s", key_hexstring)
         key_strs["command-option"] = key_hexstring
     #try to load public keys from the user conf dir(s):
     if getuid() == 0 and POSIX:
         #root: use the uid of the username specified:
         uid = self.get_uid()
     else:
         uid = getuid()
     conf_dirs = get_user_conf_dirs(uid)
     log("u2f: will try to load public keys from %s", csv(conf_dirs))
     #load public keys:
     for d in conf_dirs:
         ed = osexpand(d)
         if os.path.exists(ed) and os.path.isdir(ed):
             pub_keyfiles = glob.glob(os.path.join(ed, "u2f*-pub.hex"))
             log("u2f: keyfiles(%s)=%s", ed, pub_keyfiles)
             for f in sorted(pub_keyfiles):
                 key_hexstring = load_binary_file(f)
                 if key_hexstring:
                     key_hexstring = key_hexstring.rstrip(b" \n\r")
                     key_strs[f] = key_hexstring
                     log("u2f_auth: loaded public key from file '%s': %s",
                         f, key_hexstring)
     #parse public key data:
     #pylint: disable=import-outside-toplevel
     from cryptography.hazmat.primitives.serialization import load_der_public_key
     from cryptography.hazmat.backends import default_backend
     for origin, key_hexstring in key_strs.items():
         try:
             key = binascii.unhexlify(key_hexstring)
         except Exception as e:
             log("unhexlify(%s)", key_hexstring, exc_info=True)
             log.warn("Warning: failed to parse key '%s'", origin)
             log.warn(" %s", e)
             continue
         log("u2f: trying to load DER public key %s", repr(key))
         if not key.startswith(PUB_KEY_DER_PREFIX):
             key = PUB_KEY_DER_PREFIX + key
         try:
             k = load_der_public_key(key, default_backend())
         except Exception as e:
             log("load_der_public_key(%r)", key, exc_info=True)
             log.warn("Warning: failed to parse key '%s'", origin)
             log.warn(" %s", e)
             continue
         self.public_keys[origin] = k
     if not self.public_keys:
         raise Exception(
             "u2f authenticator requires at least one public key")
Example #11
0
    def start_Xvfb(cls, display=None, screens=((1024,768),), depth=24, extensions=("Composite", )):
        assert POSIX
        if display is None:
            display = cls.find_free_display()
        env = {}
        for x in list(os.environ.keys()):
            if x in (
				"LOGNAME", "USER", "PATH", "LANG", "TERM",
				"HOME", "USERNAME", "PYTHONPATH", "HOSTNAME",
                #"XAUTHORITY",
				):    #DBUS_SESSION_BUS_ADDRESS
                #keep it
                env[x] = os.environ.get(x)
        real_display = os.environ.get("DISPLAY")
        cmd = [cls.which(TEST_XVFB_COMMAND)]
        is_xephyr = TEST_XVFB_COMMAND.find("Xephyr")>=0
        if is_xephyr:
            if len(screens)>1 or not real_display:
                #we can't use Xephyr for multi-screen
                cmd = [cls.which("Xvfb")]
            elif real_display:
                env["DISPLAY"] = real_display
        for ext in extensions:
            if ext.startswith("-"):
                cmd += ["-extension", ext[1:]]
            else:
                cmd += ["+extension", ext]
        cmd += ["-nolisten", "tcp", "-noreset"]
        #"-auth", self.default_env["XAUTHORITY"]]
        depth_str = "%i+%i" % (depth, 32)
        for i, screen in enumerate(screens):
            (w, h) = screen
            cmd += ["-screen"]
            if not is_xephyr:
                cmd += ["%i" % i]
            cmd += ["%ix%ix%s" % (w, h, depth_str)]
        cmd.append(display)
        env["XPRA_LOG_DIR"] = tempfile.gettempdir()
        cmd_expanded = [osexpand(v) for v in cmd]
        cmdstr = " ".join("'%s'" % x for x in cmd_expanded)
        if SHOW_XORG_OUTPUT:
            stdout = sys.stdout
            stderr = sys.stderr
        else:
            stdout = cls._temp_file(prefix="Xorg-stdout-")
            log("stdout=%s for %s", stdout.name, cmd)
            stderr = cls._temp_file(prefix="Xorg-stderr-")
            log("stderr=%s for %s", stderr.name, cmd)
        xvfb = cls.class_run_command(cmd_expanded, env=env, stdout=stdout, stderr=stderr)
        xvfb.display = display
        time.sleep(1)
        log("xvfb(%s)=%s" % (cmdstr, xvfb))
        if pollwait(xvfb, XVFB_TIMEOUT) is not None:
            show_proc_error(xvfb, "xvfb command \"%s\" failed and returned %s" % (cmdstr, xvfb.poll()))
        return xvfb
Example #12
0
 def start_Xvfb(self, display=None, screens=((1024, 768), )):
     assert POSIX
     if display is None:
         display = self.find_free_display()
     env = {}
     for x in list(os.environ.keys()):
         if x in (
                 "LOGNAME",
                 "USER",
                 "PATH",
                 "LANG",
                 "TERM",
                 "HOME",
                 "USERNAME",
                 "PYTHONPATH",
                 "HOSTNAME",
                 #"XAUTHORITY",
         ):  #DBUS_SESSION_BUS_ADDRESS
             #keep it
             env[x] = os.environ.get(x)
     cmd = [
         "Xvfb", "+extension", "Composite", "-nolisten", "tcp", "-noreset"
     ]
     #"-auth", self.default_env["XAUTHORITY"]]
     for i, screen in enumerate(screens):
         (w, h) = screen
         cmd += ["-screen", "%i" % i, "%ix%ix24+32" % (w, h)]
     cmd.append(display)
     env["DISPLAY"] = display
     env["XPRA_LOG_DIR"] = "/tmp"
     cmd_expanded = [osexpand(v) for v in cmd]
     cmdstr = " ".join("'%s'" % x for x in cmd_expanded)
     if SHOW_XORG_OUTPUT:
         stdout = sys.stdout
         stderr = sys.stderr
     else:
         stdout = self._temp_file(prefix="Xorg-stdout-")
         log("stdout=%s for %s", stdout.name, cmd)
         stderr = self._temp_file(prefix="Xorg-stderr-")
         log("stderr=%s for %s", stderr.name, cmd)
     xvfb = self.run_command(cmd_expanded,
                             env=env,
                             stdout=stdout,
                             stderr=stderr)
     xvfb.display = display
     time.sleep(1)
     log("xvfb(%s)=%s" % (cmdstr, xvfb))
     if pollwait(xvfb, XVFB_TIMEOUT) is not None:
         self.show_proc_error(
             xvfb, "xvfb command \"%s\" failed and returned %s" %
             (cmdstr, xvfb.poll()))
     return xvfb
Example #13
0
    def run(self):
        register_SIGUSR_signals(self.idle_add)
        client_protocol_class = get_client_protocol_class(self.client_conn.socktype)
        server_protocol_class = get_server_protocol_class(self.server_conn.socktype)
        self.client_protocol = client_protocol_class(self, self.client_conn,
                                                     self.process_client_packet, self.get_client_packet)
        self.client_protocol.restore_state(self.client_state)
        self.server_protocol = server_protocol_class(self, self.server_conn,
                                                     self.process_server_packet, self.get_server_packet)
        self.log_start()

        log("ProxyProcessProcess.run() pid=%s, uid=%s, gid=%s", os.getpid(), getuid(), getgid())
        set_proc_title("Xpra Proxy Instance for %s" % self.server_conn)
        if POSIX and (getuid()!=self.uid or getgid()!=self.gid):
            #do we need a valid XDG_RUNTIME_DIR for the socket-dir?
            username = get_username_for_uid(self.uid)
            socket_dir = osexpand(self.socket_dir, username, self.uid, self.gid)
            if not os.path.exists(socket_dir):
                log("the socket directory '%s' does not exist, checking for $XDG_RUNTIME_DIR path", socket_dir)
                for prefix in ("/run/user/", "/var/run/user/"):
                    if socket_dir.startswith(prefix):
                        from xpra.scripts.server import create_runtime_dir
                        xrd = os.path.join(prefix, str(self.uid))   #ie: /run/user/99
                        log("creating XDG_RUNTIME_DIR=%s for uid=%i, gid=%i", xrd, self.uid, self.gid)
                        create_runtime_dir(xrd, self.uid, self.gid)
                        break
            #change uid or gid:
            setuidgid(self.uid, self.gid)
        if self.env_options:
            #TODO: whitelist env update?
            os.environ.update(self.env_options)

        signal.signal(signal.SIGTERM, self.signal_quit)
        signal.signal(signal.SIGINT, self.signal_quit)
        log("registered signal handler %s", self.signal_quit)

        start_thread(self.server_message_queue, "server message queue")

        if not self.create_control_socket():
            return
        self.control_socket_thread = start_thread(self.control_socket_loop, "control", daemon=True)

        self.main_queue = Queue()

        ProxyInstance.run(self)

        try:
            QueueScheduler.run(self)
        except KeyboardInterrupt as e:
            self.stop(None, str(e))
        finally:
            log("ProxyProcess.run() ending %s", os.getpid())
Example #14
0
 def do_run_client(self, client_display, *args):
     from xpra.x11.vfb_util import xauth_add
     xauth_data = get_hex_uuid()
     xauthority = self.default_env.get("XAUTHORITY",
                                       osexpand("~/.Xauthority"))
     xauth_add(xauthority, client_display, xauth_data, os.getuid(),
               os.getgid())
     env = self.get_run_env()
     env["DISPLAY"] = client_display
     env["XPRA_LOG_PREFIX"] = "client %i: " % X11ClientTestUtil.uq
     X11ClientTestUtil.uq += 1
     log("starting test client on Xvfb %s", client_display)
     return self.run_xpra(["attach"] + list(args), env=env)
Example #15
0
 def process_challenge_u2f(self, packet):
     digest = packet[3]
     if not digest.startswith(b"u2f:"):
         authlog("%s is not a u2f challenge", digest)
         return False
     import binascii
     import logging
     if not is_debug_enabled("auth"):
         logging.getLogger("pyu2f.hardware").setLevel(logging.INFO)
         logging.getLogger("pyu2f.hidtransport").setLevel(logging.INFO)
     from pyu2f import model
     from pyu2f.u2f import GetLocalU2FInterface
     dev = GetLocalU2FInterface()
     APP_ID = os.environ.get("XPRA_U2F_APP_ID", "Xpra")
     key_handle_str = os.environ.get("XPRA_U2F_KEY_HANDLE")
     authlog("process_challenge_u2f XPRA_U2F_KEY_HANDLE=%s", key_handle_str)
     if not key_handle_str:
         #try to load the key handle from the user conf dir(s):
         from xpra.platform.paths import get_user_conf_dirs
         info = self._protocol.get_info(False)
         key_handle_filenames = []
         for hostinfo in ("-%s" % info.get("host", ""), ""):
             key_handle_filenames += [
                 os.path.join(d, "u2f-keyhandle%s.hex" % hostinfo)
                 for d in get_user_conf_dirs()
             ]
         for filename in key_handle_filenames:
             p = osexpand(filename)
             key_handle_str = load_binary_file(p)
             authlog("key_handle_str(%s)=%s", p, key_handle_str)
             if key_handle_str:
                 key_handle_str = key_handle_str.rstrip(b" \n\r")
                 break
         if not key_handle_str:
             authlog.warn("Warning: no U2F key handle found")
             return False
     authlog("process_challenge_u2f key_handle=%s", key_handle_str)
     key_handle = binascii.unhexlify(key_handle_str)
     key = model.RegisteredKey(key_handle)
     #use server salt as challenge directly
     challenge = packet[1]
     authlog.info("activate your U2F device for authentication")
     response = dev.Authenticate(APP_ID, challenge, [key])
     sig = response.signature_data
     client_data = response.client_data
     authlog("process_challenge_u2f client data=%s, signature=%s",
             client_data, binascii.hexlify(sig))
     self.do_send_challenge_reply(bytes(sig), client_data.origin)
     return True
Example #16
0
 def check_peercred(self, connection, uids="", gids="", allow_owner=False):
     allow_uids = allow_gids = None
     if uids or allow_owner:
         allow_uids = []
         if allow_owner:
             allow_uids.append(getuid())
         for x in uids.split(":"):
             if not x.strip():
                 continue
             x = osexpand(x.strip())
             try:
                 allow_uids.append(int(x))
             except ValueError:
                 import pwd  #pylint: disable=import-outside-toplevel
                 try:
                     pw = pwd.getpwnam(x)
                     allow_uids.append(pw.pw_uid)
                 except KeyError:
                     log.warn("Warning: unknown username '%s'", x)
         log("peercred: allow_uids(%s)=%s", uids, allow_uids)
     if gids:
         allow_gids = []
         for x in gids.split(":"):
             if not x.strip():
                 continue
             x = osexpand(x.strip())
             try:
                 allow_gids.append(int(x))
             except ValueError:
                 gid = get_group_id(x)
                 if gid >= 0:
                     allow_gids.append(gid)
                 else:
                     log.warn("Warning: unknown group '%s'", x)
         log("peercred: allow_gids(%s)=%s", gids, allow_gids)
     self.do_check_peercred(connection, allow_uids, allow_gids)
Example #17
0
 def set_icon_from_data(self, pixels, has_alpha, w, h, rowstride, _options=None):
     self.clean_last_tmp_icon()
     #use a temporary file (yuk)
     from xpra.gtk_common.gtk_util import COLORSPACE_RGB, pixbuf_new_from_data, pixbuf_save_to_memory
     import tempfile
     tmp_dir = osexpand(get_xpra_tmp_dir())
     if not os.path.exists(tmp_dir):
         os.mkdir(tmp_dir, 0o755)
     self.tmp_filename = tempfile.mkstemp(prefix="tray", suffix=".png", dir=tmp_dir)[1]
     log("set_icon_from_data%s using temporary file %s",
         ("%s pixels" % len(pixels), has_alpha, w, h, rowstride), self.tmp_filename)
     tray_icon = pixbuf_new_from_data(pixels, COLORSPACE_RGB, has_alpha, 8, w, h, rowstride)
     png_data = pixbuf_save_to_memory(tray_icon)
     with open(self.tmp_filename, "wb") as f:
         f.write(png_data)
     self.do_set_icon_from_file(self.tmp_filename)
Example #18
0
    def do_setup_menu_watcher(self):
        if self.watch_manager:
            #already setup
            return
        try:
            import pyinotify
        except ImportError as e:
            log("setup_menu_watcher() cannot import pyinotify", exc_info=True)
            log.warn(
                "Warning: cannot watch for application menu changes without pyinotify:"
            )
            log.warn(" %s", e)
            return
        self.watch_manager = pyinotify.WatchManager()

        def menu_data_updated(create, pathname):
            log("menu_data_updated(%s, %s)", create, pathname)
            self.schedule_xdg_menu_reload()

        class EventHandler(pyinotify.ProcessEvent):
            def process_IN_CREATE(self, event):
                menu_data_updated(True, event.pathname)

            def process_IN_DELETE(self, event):
                menu_data_updated(False, event.pathname)

        mask = pyinotify.IN_DELETE | pyinotify.IN_CREATE  #@UndefinedVariable pylint: disable=no-member
        handler = EventHandler()
        self.watch_notifier = pyinotify.ThreadedNotifier(
            self.watch_manager, handler)
        self.watch_notifier.setDaemon(True)
        data_dirs = os.environ.get("XDG_DATA_DIRS",
                                   DEFAULT_XDG_DATA_DIRS).split(":")
        watched = []
        for data_dir in data_dirs:
            menu_dir = os.path.join(osexpand(data_dir), "applications")
            if not os.path.exists(menu_dir) or menu_dir in watched:
                continue
            wdd = self.watch_manager.add_watch(menu_dir, mask)
            watched.append(menu_dir)
            log("watch_notifier=%s, watch=%s", self.watch_notifier, wdd)
        self.watch_notifier.start()
        if watched:
            log.info("watching for applications menu changes in:")
            for wd in watched:
                log.info(" '%s'", wd)
Example #19
0
def find_log_dir(username="", uid=0, gid=0):
    from xpra.platform.paths import get_default_log_dirs
    errs  = []
    for x in get_default_log_dirs():
        v = osexpand(x, username, uid, gid)
        if not os.path.exists(v):
            if getuid()==0 and uid!=0:
                continue
            try:
                os.mkdir(v, 0o700)
            except Exception as e:
                errs.append((v, e))
                continue
        return v
    for d, e in errs:
        sys.stderr.write("Error: cannot create log directory '%s':" % d)
        sys.stderr.write(" %s\n" % e)
    return None
Example #20
0
def write_runner_shell_scripts(contents, overwrite=True):
    assert POSIX
    # This used to be given a display-specific name, but now we give it a
    # single fixed name and if multiple servers are started then the last one
    # will clobber the rest.  This isn't great, but the tradeoff is that it
    # makes it possible to use bare 'ssh:hostname' display names and
    # autodiscover the proper numeric display name when only one xpra server
    # is running on the remote host.  Might need to revisit this later if
    # people run into problems or autodiscovery turns out to be less useful
    # than expected.
    log = get_util_logger()
    MODE = 0o700
    from xpra.platform.paths import get_script_bin_dirs
    for d in get_script_bin_dirs():
        scriptdir = osexpand(d)
        if not os.path.exists(scriptdir):
            try:
                os.mkdir(scriptdir, MODE)
            except Exception as e:
                log("os.mkdir(%s, %s)", scriptdir, oct(MODE), exc_info=True)
                log.warn("Warning: failed to create script directory '%s':",
                         scriptdir)
                log.warn(" %s", e)
                if scriptdir.startswith(
                        "/var/run/user") or scriptdir.startswith("/run/user"):
                    log.warn(" ($XDG_RUNTIME_DIR has not been created?)")
                continue
        scriptpath = os.path.join(scriptdir, "run-xpra")
        if os.path.exists(scriptpath) and not overwrite:
            continue
        # Write out a shell-script so that we can start our proxy in a clean
        # environment:
        try:
            with umask_context(0o022):
                h = os.open(scriptpath, os.O_WRONLY | os.O_CREAT | os.O_TRUNC,
                            MODE)
                try:
                    os.write(h, contents)
                finally:
                    os.close(h)
        except Exception as e:
            log("writing to %s", scriptpath, exc_info=True)
            log.error("Error: failed to write script file '%s':", scriptpath)
            log.error(" %s\n", e)
Example #21
0
 def check_auth_publickey(self, username, key):
     log("check_auth_publickey(%s, %r) pubkey_auth=%s", username, key,
         self.pubkey_auth)
     if not self.pubkey_auth:
         return paramiko.AUTH_FAILED
     if not POSIX or getuid() != 0:
         import getpass
         sysusername = getpass.getuser()
         if sysusername != username:
             log.warn("Warning: ssh password authentication failed,")
             log.warn(" username does not match:")
             log.warn(" expected '%s', got '%s'", sysusername, username)
             return paramiko.AUTH_FAILED
     authorized_keys_filename = osexpand(AUTHORIZED_KEYS)
     if not os.path.exists(authorized_keys_filename) or not os.path.isfile(
             authorized_keys_filename):
         log("file '%s' does not exist", authorized_keys_filename)
         return paramiko.AUTH_FAILED
     import base64
     import binascii
     fingerprint = key.get_fingerprint()
     hex_fingerprint = binascii.hexlify(fingerprint)
     log("looking for key fingerprint '%s' in '%s'", hex_fingerprint,
         authorized_keys_filename)
     count = 0
     with open(authorized_keys_filename, "rb") as f:
         for line in f:
             if line.startswith("#"):
                 continue
             line = line.strip("\n\r")
             try:
                 key = base64.b64decode(
                     line.strip().split()[1].encode('ascii'))
             except Exception as e:
                 log("ignoring line '%s': %s", line, e)
                 continue
             import hashlib
             fp_plain = hashlib.md5(key).hexdigest()
             log("key(%s)=%s", line, fp_plain)
             if fp_plain == hex_fingerprint:
                 return paramiko.OPEN_SUCCEEDED
             count += 1
     log("no match in %i keys from '%s'", count, authorized_keys_filename)
     return paramiko.AUTH_FAILED
Example #22
0
 def _unique_sock_dirs(self):
     dirs = []
     if self._sockdir!="undefined":
         dirs.append(self._sockdir)
     dirs += [x for x in self._sockdirs if x not in dirs]
     seen = set()
     for d in dirs:
         if d in seen or not d:
             continue
         seen.add(d)
         real_dir = os.path.realpath(osexpand(d))
         if real_dir!=d:
             if real_dir in seen:
                 continue
             seen.add(real_dir)
         if not os.path.exists(real_dir):
             debug("socket_details: directory '%s' does not exist", real_dir)
             continue
         yield real_dir
Example #23
0
 def get_icon_string(self, nid, app_icon, icon):
     if app_icon and not os.path.isabs(app_icon):
         #safe to use
         return app_icon
     elif icon and icon[0] == b"png":
         icon_data = icon[3]
         from xpra.platform.paths import get_xpra_tmp_dir
         tmp = osexpand(get_xpra_tmp_dir())
         if not os.path.exists(tmp):
             os.mkdir(tmp, 0o700)
         temp = tempfile.NamedTemporaryFile(mode='w+b',
                                            suffix='png',
                                            prefix='xpra-notification',
                                            dir=tmp,
                                            delete=False)
         temp.write(icon_data)
         temp.close()
         self.temp_files[nid] = temp.name
         return temp.name
     return ""
Example #24
0
def write_runner_shell_scripts(contents, overwrite=True):
    # This used to be given a display-specific name, but now we give it a
    # single fixed name and if multiple servers are started then the last one
    # will clobber the rest.  This isn't great, but the tradeoff is that it
    # makes it possible to use bare 'ssh:hostname' display names and
    # autodiscover the proper numeric display name when only one xpra server
    # is running on the remote host.  Might need to revisit this later if
    # people run into problems or autodiscovery turns out to be less useful
    # than expected.
    log = get_util_logger()
    from xpra.platform.paths import get_script_bin_dirs
    for d in get_script_bin_dirs():
        scriptdir = osexpand(d)
        if not os.path.exists(scriptdir):
            try:
                os.mkdir(scriptdir, 0o700)
            except Exception as e:
                log("os.mkdir(%s, 0o700)", scriptdir, exc_info=True)
                log.warn("Warning: failed to create script directory '%s':",
                         scriptdir)
                log.warn(" %s", e)
                if scriptdir.startswith(
                        "/var/run/user") or scriptdir.startswith("/run/user"):
                    log.warn(" ($XDG_RUNTIME_DIR has not been created?)")
                continue
        scriptpath = os.path.join(scriptdir, "run-xpra")
        if os.path.exists(scriptpath) and not overwrite:
            continue
        # Write out a shell-script so that we can start our proxy in a clean
        # environment:
        try:
            with open(scriptpath, "w") as scriptfile:
                # Unix is a little silly sometimes:
                umask = os.umask(0)
                os.umask(umask)
                os.fchmod(scriptfile.fileno(), 0o700 & ~umask)
                scriptfile.write(contents.encode())
        except Exception as e:
            log("writing to %s", scriptpath, exc_info=True)
            log.error("Error: failed to write script file '%s':", scriptpath)
            log.error(" %s\n", e)
Example #25
0
 def get_key_handle(self) -> bytes:
     key_handle_str = os.environ.get("XPRA_U2F_KEY_HANDLE")
     log("process_challenge_u2f XPRA_U2F_KEY_HANDLE=%s", key_handle_str)
     if not key_handle_str:
         #try to load the key handle from the user conf dir(s):
         from xpra.platform.paths import get_user_conf_dirs
         info = self.client._protocol.get_info(False)
         key_handle_filenames = []
         for hostinfo in ("-%s" % info.get("host", ""), ""):
             for d in get_user_conf_dirs():
                 key_handle_filenames.append(os.path.join(d, "u2f-keyhandle%s.hex" % hostinfo))
         for filename in key_handle_filenames:
             p = osexpand(filename)
             key_handle_str = load_binary_file(p)
             log("key_handle_str(%s)=%s", p, key_handle_str)
             if key_handle_str:
                 key_handle_str = key_handle_str.rstrip(b" \n\r")
                 break
         if not key_handle_str:
             log.warn("Warning: no U2F key handle found")
             return None
     log("process_challenge_u2f key_handle=%s", key_handle_str)
     return binascii.unhexlify(key_handle_str)
Example #26
0
 def pathexpand(s):
     return osexpand(s,
                     actual_username=username,
                     uid=uid,
                     gid=gid,
                     subs=subs)
Example #27
0
 def __init__(self, username, **kwargs):
     log("peercred.Authenticator(%s, %s)", username, kwargs)
     if not POSIX:
         log.warn("Warning: peercred authentication is not supported on %s",
                  os.name)
         return
     self.uid = -1
     self.gid = -1
     self.peercred_check = False
     connection = kwargs.get("connection", None)
     uids = kwargs.pop("uid", None)
     gids = kwargs.pop("gid", None)
     allow_uids = None
     allow_gids = None
     if uids:
         allow_uids = []
         for x in uids.split(","):
             x = osexpand(x.strip())
             try:
                 allow_uids.append(int(x))
             except ValueError:
                 import pwd
                 try:
                     pw = pwd.getpwnam(x)
                     uids.append(pw.pw_uid)
                 except KeyError:
                     log.warn("Warning: unknown username '%s'", x)
         log("peercred: allow_uids(%s)=%s", uids, allow_uids)
     if gids:
         allow_gids = []
         for x in gids.split(","):
             x = osexpand(x.strip())
             try:
                 allow_gids.append(int(x))
             except ValueError:
                 gid = get_group_id(x)
                 if gid >= 0:
                     allow_gids.append(gid)
                 else:
                     log.warn("Warning: unknown group '%s'", x)
         log("peercred: allow_gids(%s)=%s", gids, allow_gids)
     try:
         from xpra.net.bytestreams import SocketConnection
         if connection and isinstance(connection, SocketConnection):
             sock = connection._socket
             peercred = get_peercred(sock)
             log("get_peercred(%s)=%s", sock, peercred)
             if not peercred:
                 log.warn("Warning: failed to get peer credentials on %s",
                          sock)
                 return
             _, uid, gid = peercred
             if allow_uids is not None and uid not in allow_uids:
                 log.warn("Warning: peercred access denied,")
                 log.warn(" uid %i is not in the whitelist: %s", uid,
                          csv(allow_uids))
             elif allow_gids is not None and gid not in allow_gids:
                 log.warn("Warning: peercred access denied,")
                 log.warn(" gid %i is not in the whitelist: %s", gid,
                          csv(allow_gids))
             else:
                 self.peercred_check = True
                 self.uid = uid
                 self.gid = gid
         else:
             log(
                 "peercred: invalid connection '%s' (not a socket connection)",
                 connection)
     except Exception as e:
         log.error("Error: cannot get peer uid")
         log.error(" %s", e)
     SysAuthenticator.__init__(self, username, **kwargs)
Example #28
0
 def osexpand(self, v):
     return osexpand(v, self.username, self.uid, self.gid)
Example #29
0
 def socket_expand(self, path):
     return osexpand(path, self.username, uid=self.uid, gid=self.gid)
Example #30
0
def main():
    from xpra.platform import program_context
    with program_context("U2F-Register", "Xpra U2F Registration Tool"):
        gui = not sys.stdin.isatty() or os.environ.get("MSYSCON")
        if gui:
            from xpra.gtk_common.gobject_compat import import_gtk, import_glib
            gtk = import_gtk()
            glib = import_glib()
            from xpra.gtk_common.gtk_util import MESSAGE_INFO, MESSAGE_ERROR, BUTTONS_CLOSE

            def show_dialog(mode, *msgs):
                dialog = gtk.MessageDialog(None, 0, mode, BUTTONS_CLOSE,
                                           "\n".join(msgs))
                dialog.set_title("Xpra U2F Registration Tool")
                v = dialog.run()
                dialog.destroy()
                #run the main loop long enough to destroy the dialog:
                glib.idle_add(gtk.main_quit)
                gtk.main()
                return v

            def error(*msgs):
                return show_dialog(MESSAGE_ERROR, *msgs)

            def info(*msgs):
                return show_dialog(MESSAGE_INFO, *msgs)
        else:
            print("U2F Registration Tool")

            def printmsgs(*msgs):
                for x in msgs:
                    print(x)

            error = info = printmsgs

        key_handle_filenames = [
            os.path.join(d, "u2f-keyhandle.hex") for d in get_user_conf_dirs()
        ]
        assert len(key_handle_filenames) > 0
        for filename in key_handle_filenames:
            p = osexpand(filename)
            key_handle_str = load_binary_file(p)
            if key_handle_str:
                error(
                    " found an existing key handle in file '%s':" % p,
                    #" %s" % key_handle_str,
                    " skipping U2F registration",
                    " delete this file if you want to register again")
                return 1
        public_key_filenames = []
        for d in get_user_conf_dirs():
            public_key_filenames += glob.glob(os.path.join(d, "u2f*.pub"))
        if public_key_filenames:
            info(
                " found %i existing public key%s" %
                (len(public_key_filenames, engs(public_key_filenames))),
                *((" - %s" % x) for x in public_key_filenames))

        #pick the first directory:
        conf_dir = osexpand(get_user_conf_dirs()[0])
        if not os.path.exists(conf_dir):
            os.mkdir(conf_dir)

        from pyu2f.u2f import GetLocalU2FInterface  #@UnresolvedImport
        try:
            dev = GetLocalU2FInterface()
        except Exception as e:
            error("Failed to open local U2F device:",
                  "%s" % (str(e) or type(e)))
            return 1

        info("Please activate your U2F device now to generate a new key")
        registered_keys = []
        challenge = b'01234567890123456789012345678901'  #unused
        rr = dev.Register(APP_ID, challenge, registered_keys)
        b = rr.registration_data
        assert b[0] == 5
        pubkey = bytes(b[1:66])
        khl = b[66]
        key_handle = bytes(b[67:67 + khl])

        #save to files:
        key_handle_filename = osexpand(key_handle_filenames[0])
        f = open(key_handle_filename, "wb")
        f.write(hexstr(key_handle).encode())
        f.close
        #find a filename we can use for this public key:
        i = 1
        while True:
            c = ""
            if i > 1:
                c = "-%i"
            public_key_filename = os.path.join(conf_dir, "u2f%s-pub.hex" % c)
            if not os.path.exists(public_key_filename):
                break
        f = open(public_key_filename, "wb")
        f.write(hexstr(pubkey).encode())
        f.close
        #info("key handle: %s" % csv(hex40(key_handle)),
        #     "saved to file '%s'" % key_handle_filename,
        #     "public key: %s" % csv(hex40(pubkey)),
        #     "saved to file '%s'" % public_key_filename,
        #     )
        info(
            "key handle saved to file:",
            "'%s'" % key_handle_filename,
            "public key saved to file:",
            "'%s'" % public_key_filename,
        )
        return 0