def make_ssh_server_connection(conn, password_auth=None): log("make_ssh_server_connection(%s)", conn) ssh_server = SSHServer(password_auth=password_auth) DoGSSAPIKeyExchange = False t = None def close(): if t: log("close() closing %s", t) try: t.close() except Exception: log("%s.close()", t, exc_info=True) log("close() closing %s", conn) try: conn.close() except Exception: log("%s.close()", conn) ssh_key_dirs = get_ssh_conf_dirs() log("ssh key dirs=%s", ssh_key_dirs) try: t = paramiko.Transport(conn._socket, gss_kex=DoGSSAPIKeyExchange) t.set_gss_host(socket.getfqdn("")) host_keys = {} log("trying to load ssh host keys from: %s", csv(ssh_key_dirs)) for d in ssh_key_dirs: fd = osexpand(d) log("osexpand(%s)=%s", d, fd) if not os.path.exists(fd) or not os.path.isdir(fd): log("ssh host key directory '%s' is invalid", fd) continue for f in os.listdir(fd): PREFIX = "ssh_host_" SUFFIX = "_key" if f.startswith(PREFIX) and f.endswith(SUFFIX): ff = os.path.join(fd, f) keytype = f[len(PREFIX):-len(SUFFIX)] if keytype: keyclass = getattr(paramiko, "%sKey" % keytype.upper(), None) if keyclass is None: #Ed25519Key keyclass = getattr( paramiko, "%s%sKey" % (keytype[:1].upper(), keytype[1:]), None) if keyclass is None: log( "key type %s is not supported, cannot load '%s'", keytype, ff) continue log("loading %s key from '%s' using %s", keytype, ff, keyclass) try: host_key = keyclass(filename=ff) if host_key not in host_keys: host_keys[host_key] = ff t.add_server_key(host_key) except IOError as e: log("cannot add host key '%s'", ff, exc_info=True) except paramiko.SSHException as e: log("error adding host key '%s'", ff, exc_info=True) log.error("Error: cannot add %s host key '%s':", keytype, ff) log.error(" %s", e) if not host_keys: log.error("Error: cannot start SSH server,") log.error(" no readable SSH host keys found in:") log.error(" %s", csv(ssh_key_dirs)) close() return None log("loaded host keys: %s", tuple(host_keys.values())) t.start_server(server=ssh_server) except (paramiko.SSHException, EOFError) as e: log("failed to start ssh server", exc_info=True) log.error("Error handling SSH connection:") log.error(" %s", e) close() return None try: chan = t.accept(SERVER_WAIT) if chan is None: log.warn("Warning: SSH channel setup failed") #prevent errors trying to access this connection, now likely dead: conn.set_active(False) close() return None except paramiko.SSHException as e: log("failed to open ssh channel", exc_info=True) log.error("Error opening channel:") log.error(" %s", e) close() return None log("client authenticated, channel=%s", chan) ssh_server.event.wait(SERVER_WAIT) log("proxy channel=%s", ssh_server.proxy_channel) if not ssh_server.event.is_set() or not ssh_server.proxy_channel: from xpra.net.bytestreams import pretty_socket log.warn("Warning: timeout waiting for xpra SSH subcommand,") log.warn(" closing connection from %s", pretty_socket(conn.target)) close() return None #log("client authenticated, channel=%s", chan) return SSHSocketConnection(ssh_server.proxy_channel, conn._socket, target="ssh client")
def make_ssh_server_connection(conn, socket_options, none_auth=False, password_auth=None): log("make_ssh_server_connection%s", (conn, socket_options, none_auth, password_auth)) ssh_server = SSHServer(none_auth=none_auth, password_auth=password_auth, options=socket_options) DoGSSAPIKeyExchange = parse_bool( "ssh-gss-key-exchange", socket_options.get("ssh-gss-key-exchange", False), False) sock = conn._socket t = None def close(): if t: log("close() closing %s", t) try: t.close() except Exception: log("%s.close()", t, exc_info=True) log("close() closing %s", conn) try: conn.close() except Exception: log("%s.close()", conn) try: t = paramiko.Transport(sock, gss_kex=DoGSSAPIKeyExchange) gss_host = socket_options.get("ssh-gss-host", socket.getfqdn("")) t.set_gss_host(gss_host) #load host keys: PREFIX = "ssh_host_" SUFFIX = "_key" host_keys = {} def add_host_key(fd, f): ff = os.path.join(fd, f) keytype = f[len(PREFIX):-len(SUFFIX)] if not keytype: log.warn("Warning: unknown host key format '%s'", f) return False keyclass = getattr(paramiko, "%sKey" % keytype.upper(), None) if keyclass is None: #Ed25519Key keyclass = getattr( paramiko, "%s%sKey" % (keytype[:1].upper(), keytype[1:]), None) if keyclass is None: log("key type %s is not supported, cannot load '%s'", keytype, ff) return False log("loading %s key from '%s' using %s", keytype, ff, keyclass) try: host_key = keyclass(filename=ff) if host_key not in host_keys: host_keys[host_key] = ff t.add_server_key(host_key) return True except IOError as e: log("cannot add host key '%s'", ff, exc_info=True) except paramiko.SSHException as e: log("error adding host key '%s'", ff, exc_info=True) log.error("Error: cannot add %s host key '%s':", keytype, ff) log.error(" %s", e) return False host_key = socket_options.get("ssh-host-key") if host_key: d, f = os.path.split(host_key) if f.startswith(PREFIX) and f.endswith(SUFFIX): add_host_key(d, f) if not host_keys: log.error("Error: failed to load host key '%s'", host_key) close() return None else: ssh_key_dirs = get_ssh_conf_dirs() log("trying to load ssh host keys from: %s", csv(ssh_key_dirs)) for d in ssh_key_dirs: fd = osexpand(d) log("osexpand(%s)=%s", d, fd) if not os.path.exists(fd) or not os.path.isdir(fd): log("ssh host key directory '%s' is invalid", fd) continue for f in os.listdir(fd): if f.startswith(PREFIX) and f.endswith(SUFFIX): add_host_key(fd, f) if not host_keys: log.error("Error: cannot start SSH server,") log.error(" no readable SSH host keys found in:") log.error(" %s", csv(ssh_key_dirs)) close() return None log("loaded host keys: %s", tuple(host_keys.values())) t.start_server(server=ssh_server) except (paramiko.SSHException, EOFError) as e: log("failed to start ssh server", exc_info=True) log.error("Error handling SSH connection:") log.error(" %s", e) close() return None try: chan = t.accept(SERVER_WAIT) if chan is None: log.warn("Warning: SSH channel setup failed") #prevent errors trying to access this connection, now likely dead: conn.set_active(False) close() return None except paramiko.SSHException as e: log("failed to open ssh channel", exc_info=True) log.error("Error opening channel:") log.error(" %s", e) close() return None log("client authenticated, channel=%s", chan) timedout = not ssh_server.event.wait(SERVER_WAIT) proxy_channel = ssh_server.proxy_channel log("proxy channel=%s, timedout=%s", proxy_channel, timedout) if not ssh_server.event.is_set() or not proxy_channel: if timedout: log.warn("Warning: timeout waiting for xpra SSH subcommand,") log.warn(" closing connection from %s", pretty_socket(conn.target)) close() return None if getattr(proxy_channel, "proxy_process", None): log("proxy channel is handled using a subprocess") return None log("client authenticated, channel=%s", chan) return SSHSocketConnection(proxy_channel, sock, conn.local, conn.endpoint, conn.target, socket_options=socket_options)