Beispiel #1
0
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")
Beispiel #2
0
Datei: ssh.py Projekt: chewi/xpra
def make_ssh_server_connection(conn,
                               socket_options,
                               none_auth=False,
                               password_auth=None):
    log("make_ssh_server_connection%s",
        (conn, socket_options, none_auth, password_auth))
    ssh_server = SSHServer(none_auth=none_auth,
                           password_auth=password_auth,
                           options=socket_options)
    DoGSSAPIKeyExchange = parse_bool(
        "ssh-gss-key-exchange",
        socket_options.get("ssh-gss-key-exchange", False), False)
    sock = conn._socket
    t = None

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

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

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

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