コード例 #1
0
ファイル: clipboard_core.py プロジェクト: DiGuoZhiMeng/Xpra
 def proxy_got_contents(self, request_id, selection, target, dtype, dformat, data):
     def no_contents():
         self.send("clipboard-contents-none", request_id, selection)
     dtype = bytestostr(dtype)
     if is_debug_enabled("clipboard"):
         log("proxy_got_contents(%s, %s, %s, %s, %s, %s:%s) data=0x%s..",
               request_id, selection, target,
               dtype, dformat, type(data), len(data or ""), hexstr((data or "")[:200]))
     if dtype is None or data is None or (dformat==0 and not data):
         no_contents()
         return
     truncated = 0
     if self.max_clipboard_send_size > 0:
         log("perform clipboard limit checking - datasize - %d, %d", len(data), self.max_clipboard_send_size)
         max_send_datalen = self.max_clipboard_send_size * 8 // get_format_size(dformat)
         if len(data) > max_send_datalen:
             truncated = len(data) - max_send_datalen
             data = data[:max_send_datalen]
     munged = self._munge_raw_selection_to_wire(target, dtype, dformat, data)
     if is_debug_enabled("clipboard"):
         log("clipboard raw -> wire: %r -> %r",
             (dtype, dformat, ellipsizer(data)), ellipsizer(munged))
     wire_encoding, wire_data = munged
     if wire_encoding is None:
         no_contents()
         return
     wire_data = self._may_compress(dtype, dformat, wire_data)
     if wire_data is not None:
         packet = ["clipboard-contents", request_id, selection,
                 dtype, dformat, wire_encoding, wire_data]
         if self.clipboard_contents_slice_fix:
             #sending the extra argument requires the fix
             packet.append(truncated)
         self.send(*packet)
コード例 #2
0
ファイル: remote_logging.py プロジェクト: dochench/xpra
 def parse_server_capabilities(self, c: typedict) -> bool:
     if self.remote_logging.lower(
     ) in ("send", "both", "yes", "true", "on") and (
             #'remote-logging.receive' was only added in v4.1 so check both:
             c.boolget("remote-logging")
             or c.boolget("remote-logging.receive")):
         #check for debug:
         from xpra.log import is_debug_enabled
         conflict = tuple(v
                          for v in ("network", "crypto", "udp", "websocket")
                          if is_debug_enabled(v))
         if conflict:
             log.warn("Warning: cannot enable remote logging")
             log.warn(" because debug logging is enabled for: %s",
                      csv(conflict))
             return True
         log.info("enabled remote logging")
         if not self.log_both:
             log.info(" see server log file for further output")
         self.local_logging = set_global_logging_handler(
             self.remote_logging_handler)
     elif self.remote_logging.lower() == "receive":
         self.request_server_log = c.boolget("remote-logging.send")
         if not self.request_server_log:
             log.warn("Warning: cannot receive log output from the server")
             log.warn(
                 " the feature is not enabled or not supported by the server"
             )
         else:
             self.after_handshake(self.start_receiving_logging)  #pylint: disable=no-member
     return True
コード例 #3
0
	def test_remotelogging(self):
		from xpra.log import Logger, is_debug_enabled
		for x in ("network", "crypto", "udp"):
			if is_debug_enabled(x):
				#remote logging will be disabled,
				#so we have to skip this test
				return
		opts = AdHocStruct()
		opts.remote_logging = "yes"
		self._test_mixin_class(RemoteLogging, opts, {
			"remote-logging"	: True,
			})
		assert len(self.packets)==0
		log = Logger("util")
		message = b"hello"
		log.info(message)
		assert len(self.packets)==1
		packet = self.packets[0]
		assert packet[0]=="logging", "expected logging packet but got '%s'" % (packet[0],)
		assert packet[1]==20, "expected INFO level (20) but got %s" % (packet[1],)
		assert packet[2].data==message, "expected message '%s' but got '%s'" % (message, packet[2].data)
		#after cleanup, log messages should not be intercepted:
		self.packets = []
		self.mixin.cleanup()
		log.info("foo")
		assert len(self.packets)==0
コード例 #4
0
 def handle(self, packet) -> bool:
     digest = bytestostr(packet[3])
     if not digest.startswith("u2f:"):
         log("%s is not a u2f challenge", digest)
         return False
     try:
         from pyu2f import model                     #@UnresolvedImport
         from pyu2f.u2f import GetLocalU2FInterface  #@UnresolvedImport
     except ImportError as e:
         log.warn("Warning: cannot use u2f authentication handler")
         log.warn(" %s", e)
         return False
     if not is_debug_enabled("auth"):
         logging.getLogger("pyu2f.hardware").setLevel(logging.INFO)
         logging.getLogger("pyu2f.hidtransport").setLevel(logging.INFO)
     dev = GetLocalU2FInterface()
     APP_ID = os.environ.get("XPRA_U2F_APP_ID", "Xpra")
     key_handle = self.get_key_handle()
     if not key_handle:
         return False
     key = model.RegisteredKey(key_handle)
     #use server salt as challenge directly
     challenge = packet[1]
     log.info("activate your U2F device for authentication")
     response = dev.Authenticate(APP_ID, challenge, [key])
     sig = response.signature_data
     client_data = response.client_data
     log("process_challenge_u2f client data=%s, signature=%s", client_data, binascii.hexlify(sig))
     self.client.do_send_challenge_reply(bytes(sig), client_data.origin)
     return True
コード例 #5
0
ファイル: ldap_auth.py プロジェクト: DiGuoZhiMeng/Xpra
 def check(self, password):
     log("check(%s)", obsc(password))
     def emsg(e):
         try:
             log.warn(" LDAP Error: %s", e.message["desc"])
             if "info" in e.message:
                 log.warn("  %s", e.message["info"])
         except:
             #python3: no way to get to the message dict?
             log.warn(" %s", e)
     try:
         import ldap
     except ImportError as e:
         log("check(..)", exc_info=True)
         log.warn("Warning: cannot use ldap authentication:")
         log.warn(" %s", e)
         return False
     try:
         assert self.username and password
         if self.tls:
             protocol = "ldaps"
         else:
             protocol = "ldap"
         server = "%s://%s:%i" % (protocol, self.host, self.port)
         conn = ldap.initialize(server, trace_level=LDAP_TRACE_LEVEL or is_debug_enabled("auth"))
         conn.protocol_version = LDAP_PROTOCOL_VERSION
         conn.set_option(ldap.OPT_REFERRALS, LDAP_REFERRALS)
         if self.cacert:
             conn.set_option(ldap.OPT_X_TLS_CACERTFILE, self.cacert)
         log("ldap.open(%s)=%s", server, conn)
         try:
             domain = socket.getfqdn().split(".", 1)[1]
         except:
             domain = "localdomain"
         user = self.username_format.replace("%username", self.username).replace("%domain", domain)
         log("user=%s", user)
         try:
             #password should be the result of a digest function,
             #ie: xor will return bytes..
             p = bytestostr(password)
             password = p.encode(self.encoding)
             log("ldap encoded password as %s", self.encoding)
         except:
             pass
         v = conn.simple_bind_s(user, password)
         log("simple_bind_s(%s, %s)=%s", user, obsc(password), v)
         return True
     except ldap.INVALID_CREDENTIALS:
         log("check(..)", exc_info=True)
         return False
     except ldap.SERVER_DOWN as e:
         log("check(..)", exc_info=True)
         log.warn("Warning: LDAP %sserver at %s:%i is unreachable", ["", "TLS "][self.tls], self.host, self.port)
         emsg(e)
     except ldap.LDAPError as e:
         log("check(..)", exc_info=True)
         log.warn("Error: ldap authentication failed:")
         emsg(e)
         return False
コード例 #6
0
ファイル: ldap3_auth.py プロジェクト: tardyp/Xpra
 def check(self, password):
     log("check(%s)", obsc(password))
     try:
         from ldap3 import Server, Connection, Tls, ALL, SIMPLE, SASL, NTLM  #@UnresolvedImport
     except ImportError as e:
         log("check(..)", exc_info=True)
         log.warn("Warning: cannot use ldap3 authentication:")
         log.warn(" %s", e)
         return False
     try:
         MECHANISM = {
             "SIMPLE": SIMPLE,
             "SASL": SASL,
             "NTLM": NTLM,
         }
         authentication = MECHANISM[self.authentication]
         tls = None
         if self.tls:
             tls = Tls(validate=self.tls_validate,
                       version=self.tls_version,
                       ca_certs_file=self.cacert)
             log("TLS=%s", tls)
         server = Server(self.host,
                         port=self.port,
                         tls=tls,
                         use_ssl=self.tls,
                         get_info=ALL)
         log("ldap3 Server(%s)=%s", (self.host, self.port, self.tls),
             server)
         conn = Connection(server,
                           user=self.username,
                           password=password,
                           authentication=authentication,
                           receive_timeout=10)
         log("ldap3 Connection(%s, %s, %s)=%s", server, self.username,
             self.authentication, conn)
         if self.tls:
             conn.start_tls()
         r = conn.bind()
         log("ldap3 %s.bind()=%s", conn, r)
         if not r:
             return False
         if is_debug_enabled("auth"):
             log("ldap3 server info:")
             for l in server.info.splitlines():
                 log(" %s", l)
         log("ldap3 who_am_i()=%s", conn.extend.standard.who_am_i())
         return True
     except Exception as e:
         log("ldap3 check(..)", exc_info=True)
         log.error("Error: ldap3 authentication failed:")
         log.error(" %s", e)
         return False
コード例 #7
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
コード例 #8
0
ファイル: remote_logging.py プロジェクト: rudresh2319/Xpra
 def parse_server_capabilities(self):
     c = self.server_capabilities
     if self.client_supports_remote_logging and c.boolget("remote-logging"):
         #check for debug:
         from xpra.log import is_debug_enabled
         for x in ("network", "crypto", "udp"):
             if is_debug_enabled(x):
                 log.warn("Warning: cannot enable remote logging")
                 log.warn(" because '%s' debug logging is enabled", x)
                 return True
         log.info("enabled remote logging")
         if not self.log_both:
             log.info(" see server log file for further output")
         self.local_logging = set_global_logging_handler(self.remote_logging_handler)
     return True
コード例 #9
0
 def parse_server_capabilities(self, c: typedict) -> bool:
     if self.client_supports_remote_logging and c.boolget("remote-logging"):
         #check for debug:
         from xpra.log import is_debug_enabled
         conflict = tuple(v
                          for v in ("network", "crypto", "udp", "websocket")
                          if is_debug_enabled(v))
         if conflict:
             log.warn("Warning: cannot enable remote logging")
             log.warn(" because debug logging is enabled for: %s",
                      csv(conflict))
             return True
         log.info("enabled remote logging")
         if not self.log_both:
             log.info(" see server log file for further output")
         self.local_logging = set_global_logging_handler(
             self.remote_logging_handler)
     return True
コード例 #10
0
    def test_remotelogging(self):
        from xpra.log import is_debug_enabled
        for x in ("network", "crypto", "udp"):
            if is_debug_enabled(x):
                #remote logging will be disabled,
                #so we have to skip this test
                return
        x = RemoteLogging()
        opts = AdHocStruct()
        opts.remote_logging = "yes"
        x.init(opts)
        assert x.get_caps() is not None
        x.server_capabilities = typedict({
            "remote-logging": True,
        })
        x.parse_server_capabilities()
        packets = []

        def send(*args):
            packets.append(args)

        x.send = send
        from xpra.log import Logger
        log = Logger("util")
        message = b"hello"
        log.info(message)
        assert len(packets) == 1
        packet = packets[0]
        assert packet[
            0] == "logging", "expected logging packet but got '%s'" % (
                packet[0], )
        assert packet[1] == 20, "expected INFO level (20) but got %s" % (
            packet[1], )
        assert packet[
            2].data == message, "expected message '%s' but got '%s'" % (
                message, packet[2].data)
        #after cleanup, log messages should not be intercepted:
        x.cleanup()
        log.info("foo")
        assert len(packets) == 1
コード例 #11
0
ファイル: ssh.py プロジェクト: gitmirrors2/xpra
def ssh_exec_connect_to(display_desc, opts=None, debug_cb=None, ssh_fail_cb=ssh_connect_failed):
    if not ssh_fail_cb:
        ssh_fail_cb = ssh_connect_failed
    sshpass_command = None
    try:
        cmd = list(display_desc["full_ssh"])
        kwargs = {}
        env = display_desc.get("env")
        kwargs["stderr"] = sys.stderr
        if WIN32:
            from subprocess import CREATE_NEW_PROCESS_GROUP, CREATE_NEW_CONSOLE, STARTUPINFO, STARTF_USESHOWWINDOW
            startupinfo = STARTUPINFO()
            startupinfo.dwFlags |= STARTF_USESHOWWINDOW
            startupinfo.wShowWindow = 0     #aka win32.con.SW_HIDE
            flags = CREATE_NEW_PROCESS_GROUP | CREATE_NEW_CONSOLE
            kwargs.update({
                "startupinfo"   : startupinfo,
                "creationflags" : flags,
                "stderr"        : PIPE,
                })
        elif not display_desc.get("exit_ssh", False) and not OSX:
            kwargs["start_new_session"] = True
        remote_xpra = display_desc["remote_xpra"]
        assert remote_xpra
        socket_dir = display_desc.get("socket_dir")
        proxy_command = display_desc["proxy_command"]       #ie: "_proxy_start"
        display_as_args = display_desc["display_as_args"]   #ie: "--start=xterm :10"
        remote_cmd = ""
        for x in remote_xpra:
            if not remote_cmd:
                check = "if"
            else:
                check = "elif"
            if x=="xpra":
                #no absolute path, so use "which" to check that the command exists:
                pc = ['%s which "%s" > /dev/null 2>&1; then' % (check, x)]
            else:
                pc = ['%s [ -x %s ]; then' % (check, x)]
            pc += [x] + proxy_command + [shellquote(x) for x in display_as_args]
            if socket_dir:
                pc.append("--socket-dir=%s" % socket_dir)
            remote_cmd += " ".join(pc)+";"
        remote_cmd += "else echo \"no run-xpra command found\"; exit 1; fi"
        if INITENV_COMMAND:
            remote_cmd = INITENV_COMMAND + ";" + remote_cmd
        #how many times we need to escape the remote command string
        #depends on how many times the ssh command is parsed
        nssh = sum(int(x=="ssh") for x in cmd)
        if nssh>=2 and MAGIC_QUOTES:
            for _ in range(nssh):
                remote_cmd = shlex.quote(remote_cmd)
        else:
            remote_cmd = "'%s'" % remote_cmd
        cmd.append("sh -c %s" % remote_cmd)
        if debug_cb:
            debug_cb("starting %s tunnel" % str(cmd[0]))
        #non-string arguments can make Popen choke,
        #instead of lazily converting everything to a string, we validate the command:
        for x in cmd:
            if not isinstance(x, str):
                raise InitException("argument is not a string: %s (%s), found in command: %s" % (x, type(x), cmd))
        password = display_desc.get("password")
        if password and not display_desc.get("is_putty", False):
            from xpra.platform.paths import get_sshpass_command
            sshpass_command = get_sshpass_command()
            if sshpass_command:
                #sshpass -e ssh ...
                cmd.insert(0, sshpass_command)
                cmd.insert(1, "-e")
                if env is None:
                    env = os.environ.copy()
                env["SSHPASS"] = password
                #the password will be used by ssh via sshpass,
                #don't try to authenticate again over the ssh-proxy connection,
                #which would trigger warnings if the server does not require
                #authentication over unix-domain-sockets:
                opts.password = None
                del display_desc["password"]
        if env:
            kwargs["env"] = env
        if is_debug_enabled("ssh"):
            log.info("executing ssh command: %s" % (" ".join("\"%s\"" % x for x in cmd)))
        child = Popen(cmd, stdin=PIPE, stdout=PIPE, **kwargs)
    except OSError as e:
        raise InitExit(EXIT_SSH_FAILURE,
                       "Error running ssh command '%s': %s" % (" ".join("\"%s\"" % x for x in cmd), e))
    def abort_test(action):
        """ if ssh dies, we don't need to try to read/write from its sockets """
        e = child.poll()
        if e is not None:
            had_connected = conn.input_bytecount>0 or conn.output_bytecount>0
            if had_connected:
                error_message = "cannot %s using SSH" % action
            else:
                error_message = "SSH connection failure"
            sshpass_error = None
            if sshpass_command:
                sshpass_error = {
                                 1  : "Invalid command line argument",
                                 2  : "Conflicting arguments given",
                                 3  : "General runtime error",
                                 4  : "Unrecognized response from ssh (parse error)",
                                 5  : "Invalid/incorrect password",
                                 6  : "Host public key is unknown. sshpass exits without confirming the new key.",
                                 }.get(e)
                if sshpass_error:
                    error_message += ": %s" % sshpass_error
            if debug_cb:
                debug_cb(error_message)
            if ssh_fail_cb:
                ssh_fail_cb(error_message)
            if "ssh_abort" not in display_desc:
                display_desc["ssh_abort"] = True
                if not had_connected:
                    log.error("Error: SSH connection to the xpra server failed")
                    if sshpass_error:
                        log.error(" %s", sshpass_error)
                    else:
                        log.error(" check your username, hostname, display number, firewall, etc")
                    display_name = display_desc["display_name"]
                    log.error(" for server: %s", display_name)
                else:
                    log.error("The SSH process has terminated with exit code %s", e)
                cmd_info = " ".join(display_desc["full_ssh"])
                log.error(" the command line used was:")
                log.error(" %s", cmd_info)
            raise ConnectionClosedException(error_message) from None
    def stop_tunnel():
        if POSIX:
            #on posix, the tunnel may be shared with other processes
            #so don't kill it... which may leave it behind after use.
            #but at least make sure we close all the pipes:
            for name,fd in {
                            "stdin" : child.stdin,
                            "stdout" : child.stdout,
                            "stderr" : child.stderr,
                            }.items():
                try:
                    if fd:
                        fd.close()
                except Exception as e:
                    print("error closing ssh tunnel %s: %s" % (name, e))
            if not display_desc.get("exit_ssh", False):
                #leave it running
                return
        try:
            if child.poll() is None:
                child.terminate()
        except Exception as e:
            print("error trying to stop ssh tunnel process: %s" % e)
    host = display_desc["host"]
    port = display_desc.get("ssh-port", 22)
    username = display_desc.get("username")
    display = display_desc.get("display")
    info = {
        "host"  : host,
        "port"  : port,
        }
    from xpra.net.bytestreams import TwoFileConnection
    conn = TwoFileConnection(child.stdin, child.stdout,
                             abort_test, target=(host, port),
                             socktype="ssh", close_cb=stop_tunnel, info=info)
    conn.endpoint = host_target_string("ssh", username, host, port, display)
    conn.timeout = 0            #taken care of by abort_test
    conn.process = (child, "ssh", cmd)
    if kwargs.get("stderr")==PIPE:
        def stderr_reader():
            errs = []
            while child.poll() is None:
                try:
                    v = child.stderr.readline()
                except OSError:
                    log("stderr_reader()", exc_info=True)
                    break
                if not v:
                    log("SSH EOF on stderr of %s", cmd)
                    break
                s = bytestostr(v.rstrip(b"\n\r"))
                if s:
                    errs.append(s)
            if errs:
                log.warn("remote SSH stderr:")
                for e in errs:
                    log.warn(" %s", e)
        start_thread(stderr_reader, "ssh-stderr-reader", daemon=True)
    return conn