Esempio n. 1
0
 def __enter__(self):
     assert self.sftp_clients is None, 'the context is already started'
     sftp_clients = {}
     for server in self.servers:
         try:
             transport = Transport((server.host, server.port))
             transport.connect(username=server.user, pkey=self.old_key)
         except (OSError, SSHException) as e:
             for t, _, __ in sftp_clients.values():
                 t.close()
             l = logging.getLogger(__name__ + '.TwoPhaseRenewal.__enter__')
             l.exception(
                 'An exception rise during master key renewal '
                 '(%s -> %s, server: %s@%s:%d): %s',
                 get_key_fingerprint(self.old_key),
                 get_key_fingerprint(self.new_key),
                 server.user, server.host, server.port, str(e)
             )
             raise
         except socket.gaierror as e:
             raise ConnectionError(
                 'failed to connect: {0!s}\n{1!s}'.format(server, e)
             ) from e
         sftp_client = SFTPClient.from_transport(transport)
         authorized_keys = AuthorizedKeyList(sftp_client)
         sftp_clients[server] = transport, sftp_client, authorized_keys
         authorized_keys.append(self.new_key)
     self.sftp_clients = sftp_clients
     return self.servers
Esempio n. 2
0
class RepoWriteLock:
    def __init__(self, url):
        self.url = url
        self.transport = None
        self.client = None
        self.socket = socket()

    def __enter__(self):
        self.socket.connect((interpret_urlish(self.url)[1], 22))
        self.transport = Transport(self.socket)
        self.transport.start_client()
        authenticate_transport(self.transport)
        self.client = self.transport.open_sftp_client()
        self.client.chdir(interpret_urlish(self.url)[2])

        self._lock()

    def _lock(self):
        target_locks = self.client.listdir("locks")
        target_locks.sort()

        if target_locks:
            raise RuntimeError("repo is locked; try again later")
        else:
            self.client.mkdir("locks/write_lock")

    def _unlock(self):
        self.client.rmdir("locks/write_lock")

    def __exit__(self, *args):
        self._unlock()

        self.client.close()
        self.transport.close()
        self.socket.close()
Esempio n. 3
0
def check_ssh_up(host, port):
    """
    Return True if SSH connectivity exists.

    First checks if port is open, then tries to see if it response to SSH connectivity.
    """
    try:
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.settimeout(2)
        try:
            s.connect((host, port))
        except socket.error as e:
            if e.errno in (61,):
                return False
            else:
                raise
        else:
            # Basic connectivity works, try SSH
            t = Transport(s)
            # Shut up paramiko logging
            plog = logging.getLogger('paramiko.transport')
            plog.disabled = True
            try:
                t.start_client()
                return True
            except paramiko.SSHException as e:
                return False
            finally:
                t.close()
                s.close()
                plog.disabled = False
    except Exception as e:
        raise SshError('Error while checking %s:%d for SSH: %s' % (host, port, e))
Esempio n. 4
0
    def __init__(self, server, client, rules):
        Transport.__init__(self, client)

        self.server = server
        self.encoding = "ascii"
        self.rules = rules
        self.add_server_key(self.DEFAULT_KEY)
        self.start_server(server=self)
Esempio n. 5
0
    def __enter__(self):
        self.socket.connect((interpret_urlish(self.url)[1], 22))
        self.transport = Transport(self.socket)
        self.transport.start_client()
        authenticate_transport(self.transport)
        self.client = self.transport.open_sftp_client()
        self.client.chdir(interpret_urlish(self.url)[2])

        self._lock()
Esempio n. 6
0
def get_sftp_client():
    global _sftp_client, _identity_file, _repository_server, _repository_port, _repository_user
    try:
        if not _sftp_client:
            key = RSAKey.from_private_key_file(_identity_file)
            t = Transport((_repository_server, _repository_port))
            t.connect(username=_repository_user, pkey=key)
            _sftp_client = DistSFTPClient.from_transport(t)
    except Exception, e:
        print e
Esempio n. 7
0
 def accept(server_socket, mask):
     conn, addr = server_socket.accept()
     transport = Transport(conn)
     transport.add_server_key(host_key)
     transport.set_subsystem_handler('sftp', SFTPServer, stub_cls)
     server = StubServer(path)
     transport.start_server(server=server)
     while not terminated.is_set():
         channel = transport.accept(1)
         if channel is not None and not terminated.is_set():
             while transport.is_active() and not terminated.is_set():
                 terminated.wait(1)
             break
Esempio n. 8
0
    def _collect(self, server, start, host):
        try:
            sock = create_connection((host, self.get_setting('port', opt_type=int)))

            transport = Transport(sock)
            transport.logger.setLevel(logging.WARNING)
            transport.packetizer.write_all(transport.local_version + '\r\n')
            transport._check_banner()
            transport.packetizer.close()

            lag = time() - start
        except SSHException, e:
            logger.info('ssh exception: %s for server %s for the %s run' % (e, server['fqdn'], start))
            lag = -1
Esempio n. 9
0
    def _collect(self, server, start, host):
        try:
            sock = create_connection(
                (host, self.get_setting('port', opt_type=int)))

            transport = Transport(sock)
            transport.logger.setLevel(logging.WARNING)
            transport.packetizer.write_all(transport.local_version + '\r\n')
            transport._check_banner()
            transport.packetizer.close()

            lag = time() - start
        except SSHException, e:
            logger.info('ssh exception: %s for server %s for the %s run' %
                        (e, server['fqdn'], start))
            lag = -1
Esempio n. 10
0
 def accept(server_socket, mask):
     conn, addr = server_socket.accept()
     transport = Transport(conn)
     transport.add_server_key(host_key)
     transport.set_subsystem_handler('sftp', SFTPServer, stub_cls)
     server = StubServer(path)
     transport.start_server(server=server)
     while not terminated.is_set():
         channel = transport.accept(1)
         if channel is not None and not terminated.is_set():
             while transport.is_active() and not terminated.is_set():
                 terminated.wait(1)
             break
Esempio n. 11
0
    def open(self):
        """
        Opens the connection
        """

        self.socket.connect((interpret_urlish(self.url)[1], 22))
        self.transport = Transport(self.socket)
        self.transport.start_client()
        authenticate_transport(self.transport)
        self.client = self.transport.open_sftp_client()
        target_path = interpret_urlish(self.url)[2]
        try:
            self.client.stat(target_path)
        except IOError:
            self.client.mkdir(target_path)
        self.client.chdir(target_path)
        self.opened = True
Esempio n. 12
0
 def __enter__(self):
     assert self.sftp_clients is None, "the context is already started"
     sftp_clients = {}
     for server in self.servers:
         try:
             transport = Transport((server.host, server.port))
             transport.connect(pkey=self.old_key)
         except SSHException:
             for t, _, __ in sftp_clients.values():
                 t.close()
             raise
         sftp_client = SFTPClient.from_transport(transport)
         authorized_keys = AuthorizedKeyList(sftp_client)
         sftp_clients[server] = transport, sftp_client, authorized_keys
         authorized_keys.append(self.new_key)
     self.sftp_clients = sftp_clients
     return self.servers
Esempio n. 13
0
    def handle(self):
        transport = Transport(self.request)
        #transport.set_hexdump(True)
        transport.add_server_key(self.host_key)
        transport.set_subsystem_handler(
            'sftp',
            sftp_server.SFTPServer,
            VirtualSFTPServerInterface,
            content_provider=self.server.content_provider)

        transport.start_server(server=AllowAllAuthHandler())
        # Keep a reference to channel to avoid it getting GCed immediately
        channel = transport.accept()

        # Keep the thread alive until the client is done
        while transport.is_active():
            sleep(.01)
Esempio n. 14
0
 def __enter__(self):
     assert self.sftp_clients is None, 'the context is already started'
     sftp_clients = {}
     for server in self.servers:
         try:
             transport = Transport((server.host, server.port))
             transport.connect(pkey=self.old_key)
         except SSHException:
             for t, _, __ in sftp_clients.values():
                 t.close()
             raise
         sftp_client = SFTPClient.from_transport(transport)
         authorized_keys = AuthorizedKeyList(sftp_client)
         sftp_clients[server] = transport, sftp_client, authorized_keys
         authorized_keys.append(self.new_key)
     self.sftp_clients = sftp_clients
     return self.servers
Esempio n. 15
0
    def __connect(self):
        hostKey = self.__getHostKey()

        if self.__transport:
            self.__transport.close()
        self.__transport = Transport( (self.__host, self.__port) )

        if self._usePassword:
            password = self.__password
            if not password:
                password = self.__promptPassword()
            self.__transport.connect(hostKey, self.__username, password)
        else:
            privateKey = self.__loadKey()
            self.__transport.connect(hostKey, self.__username, pkey=privateKey)

        self.__sftp = SFTPClient.from_transport(self.__transport)
        return self
Esempio n. 16
0
def test_isalive(monkeypatch, paramiko_transport):
    def _isalive(cls):
        return True

    monkeypatch.setattr(
        "paramiko.transport.Transport.is_alive",
        _isalive,
    )

    paramiko_transport.session = Transport(socket())
    assert paramiko_transport.isalive() is True
Esempio n. 17
0
def dbbackup(path):
    dbinfo = choicedb(path + '/conf/db_info.yaml')
    s = sshconnect(hostname=dbinfo[0], port=dbinfo[7], username=dbinfo[5], password=dbinfo[6])
    st, std, stde = s.exec_command('cd /home/mysql/backup'+'\n' 'ls')
    filelist = std.read().decode('gbk',errors='ignore').split('\n')
    if 'databackup.sql' in filelist:
        s.exec_command('cd /home/mysql/backup'+'\n' 'rm -rf databackup1.sql')
    stdin, stdout, stderr = s.exec_command('mysqldump -t -u'+dbinfo[2]+' -p'+dbinfo[3]+' '+dbinfo[4]+' >/home/mysql/backup/databackup.sql')
    if 'error' not in stderr.read().decode('gbk', errors='ignore'):
        t1,t2,t3=s.exec_command('du -b /home/mysql/databackup.sql')
        if sys.platform == 'win32':
            t = Transport(dbinfo[0], 22)
            t.connect(username=dbinfo[5], password=dbinfo[6])
            sftp = SFTPClient.from_transport(t)
            src = '/home/mysql/backup/databackup.sql'
            des = path + '/database/databackup.sql'
            sftp.get(src, des)
            t.close()
        else:
            child = spawn(
                'scp ' + dbinfo[5] + '@' + dbinfo[0] + ':/home/mysql/backup/databackup.sql ' + path + '/database/')
            child.expect("password:")
            child.sendline(dbinfo[6])
            child.read()
        with zipfile.ZipFile(path + '/database/backupdatabase.zip', 'w') as z:
            z.write(path + '/database/databackup.sql')
        return t2.read().decode('gbk',errors='ignore').split('\t')[0].strip()
    else:
        return False
    s.close
Esempio n. 18
0
def restore(path):

    dbinfo = choicedb(path+'/conf/db_info.yaml')
    editData(dbinfo, [['reset master;']])
    if sys.platform == 'win32':
        t = Transport(dbinfo[0], 22)
        t.connect(username=dbinfo[5], password=dbinfo[6])
        sftp = SFTPClient.from_transport(t)
        src = '/home/mysql/basedata/initdata.sql'
        des = path + '/database/initdata.sql'
        sftp.put(des,src )
        t.close()
    else:
        child = spawn(
            'scp '+path+'/database/initdata.sql '+ dbinfo[5]+'@'+dbinfo[0]+':/home/mysql/basedata/')
        child.expect("password:"******"'"+dbinfo[3]+"'"' '+dbinfo[4]+' </home/mysql/basedata/initdata.sql')
    return stderr.read().decode('gbk', errors='ignore')
Esempio n. 19
0
    def handle(self):
        transport = Transport(self.request)
        #transport.set_hexdump(True)
        transport.add_server_key(self.host_key)
        transport.set_subsystem_handler(
            'sftp',
            sftp_server.SFTPServer,
            VirtualSFTPServerInterface,
            content_provider=self.server.content_provider
        )

        transport.start_server(server=AllowAllAuthHandler())
        # Keep a reference to channel to avoid it getting GCed immediately
        channel = transport.accept()

        # Keep the thread alive until the client is done
        while transport.is_active():
            sleep(.01)
Esempio n. 20
0
def ssh_connect(host, user, pkey, window_size = (2 << 15) - 1):
    """
    Creates a :py:class:`paramiko.Transport` object and adds it to
    ``SSHSession``.

    :param str host: remote host
    :param str user: username at remote host
    :param str pkey: path to private RSA key
    :param int window_size: TCP window size
    :note: if command execution times out and output is truncated, it is likely that the TCP window is too small
    """
    from paramiko.transport import Transport
    from paramiko import RSAKey

    global SSHSession
    try:
        SSHSession[host] = Transport((host, 22))
        SSHSession[host].window_size = window_size
        pkey = RSAKey.from_private_key_file(pkey, '')
        SSHSession[host].connect(username = user, pkey = pkey)
        SSHSession[host].__del__ = SSHSession[host].close
    except Exception as e:
        raise ArcError('Failed to connect to %s:\n%s' % (host, str(e)), 'common.ssh')
Esempio n. 21
0
File: ssh.py Progetto: maikenp/arc-1
def ssh_connect(host, user, pkey, window_size=(2 << 15) - 1):
    """
    Creates a :py:class:`paramiko.Transport` object and adds it to
    ``SSHSession``.

    :param str host: remote host
    :param str user: username at remote host
    :param str pkey: path to private RSA key
    :param int window_size: TCP window size
    :note: if command execution times out and output is truncated, it is likely that the TCP window is too small
    """
    from paramiko.transport import Transport
    from paramiko import RSAKey

    global SSHSession
    try:
        SSHSession[host] = Transport((host, 22))
        SSHSession[host].window_size = window_size
        pkey = RSAKey.from_private_key_file(pkey, '')
        SSHSession[host].connect(username=user, pkey=pkey)
        SSHSession[host].__del__ = SSHSession[host].close
    except Exception as e:
        raise ArcError('Failed to connect to host %s:\n%s' % (host, str(e)),
                       'common.ssh')
Esempio n. 22
0
def test_close(monkeypatch, paramiko_transport):
    _close_called = False

    def _close(cls):
        nonlocal _close_called
        _close_called = True

    monkeypatch.setattr(
        "paramiko.channel.Channel.close",
        _close,
    )

    paramiko_transport.session = Transport(socket())
    paramiko_transport.session_channel = Channel(0)
    paramiko_transport.close()

    assert paramiko_transport.session is None
    assert paramiko_transport.session_channel is None
    assert _close_called is True
Esempio n. 23
0
def fx_authorized_sftp(fx_sftpd, fx_authorized_keys):
    port, (thread, path, ev) = fx_sftpd.popitem()
    thread.start()
    key = RSAKey.generate(1024)
    dot_ssh = path.mkdir('.ssh')
    with dot_ssh.join('authorized_keys').open('w') as f:
        print(format_openssh_pubkey(key), file=f)
        for authorized_key in fx_authorized_keys:
            print(format_openssh_pubkey(authorized_key), file=f)
    transport = Transport(('127.0.0.1', port))
    transport.connect(username='******', pkey=key)
    sftp_client = SFTPClient.from_transport(transport)
    yield sftp_client, path, [key] + fx_authorized_keys
    sftp_client.close()
    transport.close()
    def authenticate_sftp_user(user_name, password, otc, hostname, port):

        def sftp_auth_handler(title, instructions, prompt_list):
            if len(prompt_list) == 0:
                return []
            if 'Password' in prompt_list[0][0]:
                return [password]
            else:
                return [otc]

        transport = Transport((hostname, int(port)))

        if otc != '':
            transport.start_client()
            transport.auth_interactive(user_name, sftp_auth_handler)
        else:
            transport.connect(None, user_name, password)

        return transport
 def checkUsername(self, username, tried=0):
     sock = socket.socket()
     sock.connect((self.hostname, self.port))
     # instantiate transport
     transport = Transport(sock)
     try:
         transport.start_client()
     except paramiko.ssh_exception.SSHException:
         # server was likely flooded, retry up to 3 times
         transport.close()
         if tried < 4:
             tried += 1
             return self.checkUsername(username, tried)
         else:
             print("[-] Failed to negotiate SSH transport")
     try:
         transport.auth_publickey(username, paramiko.RSAKey.generate(1024))
     except BadUsername:
         return (username, False)
     except paramiko.ssh_exception.AuthenticationException:
         return (username, True)
     #Successful auth(?)
     raise Exception(
         "There was an error. Is this the correct version of OpenSSH?")
Esempio n. 26
0
def get_host_keys(address, port=22, types=None):
    if types is None:
        types = Transport._preferred_keys

    af, sock_type, proto, name, addr = socket.getaddrinfo(
        address, port, 0,0, socket.IPPROTO_TCP)[0]

    keys = []
    for key_type in types:
        try:
            sock = socket.socket(af, sock_type, proto)
            sock.connect(addr)

            t = Transport(sock)
            t.get_security_options().key_types = [key_type]
            t.start_client()
            keys.append(t.get_remote_server_key())
        except Exception:
            pass
        finally:
            t.close()
            sock.close()

    return keys
Esempio n. 27
0
def authorize(public_keys: collections.abc.Set,
              master_key: PKey,
              remote: Remote,
              timeout: datetime.timedelta) -> datetime.datetime:
    """Make an one-time authorization to the ``remote``, and then revokes
    it when ``timeout`` reaches soon.

    :param public_keys: the set of public keys (:class:`paramiko.pkey.PKey`)
                        to authorize
    :type public_keys: :class:`collections.abc.Set`
    :param master_key: the master key (*not owner's key*)
    :type master_key: :class:`paramiko.pkey.PKey`
    :param remote: a remote to grant access permission
    :type remote: :class:`~.remote.Remote`
    :param timeout: the time an authorization keeps alive
    :type timeout: :class:`datetime.timedelta`
    :return: the expiration time
    :rtype: :class:`datetime.datetime`

    """
    transport = Transport((remote.host, remote.port))
    transport.connect(username=remote.user, pkey=master_key)
    try:
        sftp_client = SFTPClient.from_transport(transport)
        try:
            authorized_keys = AuthorizedKeyList(sftp_client)
            authorized_keys.extend(public_keys)
        except:
            sftp_client.close()
            raise
    except:
        transport.close()
        raise

    def rollback():
        time.sleep(timeout.total_seconds())
        authorized_keys[:] = [master_key]
        sftp_client.close()
        transport.close()
    timer = threading.Thread(target=rollback)
    expires_at = datetime.datetime.now(datetime.timezone.utc) + timeout
    timer.start()
    return expires_at
Esempio n. 28
0
def get_host_key(host, port=22):
    logger.debug("Connecting to host %s to get ssh public host key" % host)
    INTERVAL = 15
    MAX_RETRY = 60 / INTERVAL * 5
    c = 0
    while 1:
        try:
            sock = create_connection((host, port))

            transport = Transport(sock)
            transport.start_client()
            key = transport.get_remote_server_key()
            transport.close()
            break
        except error, e:
            if type(e) is timeout:
                log = logger.warn
            else:
                log = logger.error
            log('socket %s: errno=%r, error msg=%s for server %s' % (e.__class__.__name__, e.errno, e.strerror, host))
        except SSHException, e:
            logger.exception("attempt %s - error while attempting to connect to %s" % (c, host))
Esempio n. 29
0
def sftp_push_file(host, user, password, to_, from_):
    """
    上传文件,注意:不支持文件夹
    :param host: 主机名
    :param user: 用户名
    :param password: 密码
    :param from_: 远程路径,比如:/home/sdn/tmp.txt
    :param to_: 本地路径,比如:D:/text.txt
    :param timeout: 超时时间(默认),必须是int类型
    :return: bool
    """
    logging.debug('SSH FILE PUSH')
    try:
        t = Transport((host, 22))
        t.connect(username=user, password=password)
        sftp = paramiko.SFTPClient.from_transport(t)
        sftp.put(to_, from_)
        t.close()
        logging.info('SSH FILE PUSH SUCCESS')
        return True
    except Exception as e:
        logging.error(str(type(e)) + ' ' + e.strerror)
        logging.error('SSH FILE PUSH FAIL')
        return False
Esempio n. 30
0
    def connect(
        self,
        hostname,
        port=SSH_PORT,
        username=None,
        password=None,
        pkey=None,
        key_filename=None,
        timeout=None,
        allow_agent=True,
        look_for_keys=True,
        compress=False,
        sock=None,
        gss_auth=False,
        gss_kex=False,
        gss_deleg_creds=True,
        gss_host=None,
        banner_timeout=None,
        auth_timeout=None,
        gss_trust_dns=True,
    ):
        """
        Connect to an SSH server and authenticate to it.  The server's host key
        is checked against the system host keys (see `load_system_host_keys`)
        and any local host keys (`load_host_keys`).  If the server's hostname
        is not found in either set of host keys, the missing host key policy
        is used (see `set_missing_host_key_policy`).  The default policy is
        to reject the key and raise an `.SSHException`.

        Authentication is attempted in the following order of priority:

            - The ``pkey`` or ``key_filename`` passed in (if any)

              - ``key_filename`` may contain OpenSSH public certificate paths
                as well as regular private-key paths; when files ending in
                ``-cert.pub`` are found, they are assumed to match a private
                key, and both components will be loaded. (The private key
                itself does *not* need to be listed in ``key_filename`` for
                this to occur - *just* the certificate.)

            - Any key we can find through an SSH agent
            - Any "id_rsa", "id_dsa" or "id_ecdsa" key discoverable in
              ``~/.ssh/``

              - When OpenSSH-style public certificates exist that match an
                existing such private key (so e.g. one has ``id_rsa`` and
                ``id_rsa-cert.pub``) the certificate will be loaded alongside
                the private key and used for authentication.

            - Plain username/password auth, if a password was given

        If a private key requires a password to unlock it, and a password is
        passed in, that password will be used to attempt to unlock the key.

        :param str hostname: the server to connect to
        :param int port: the server port to connect to
        :param str username:
            the username to authenticate as (defaults to the current local
            username)
        :param str password:
            a password to use for authentication or for unlocking a private key
        :param .PKey pkey: an optional private key to use for authentication
        :param str key_filename:
            the filename, or list of filenames, of optional private key(s)
            and/or certs to try for authentication
        :param float timeout:
            an optional timeout (in seconds) for the TCP connect
        :param bool allow_agent:
            set to False to disable connecting to the SSH agent
        :param bool look_for_keys:
            set to False to disable searching for discoverable private key
            files in ``~/.ssh/``
        :param bool compress: set to True to turn on compression
        :param socket sock:
            an open socket or socket-like object (such as a `.Channel`) to use
            for communication to the target host
        :param bool gss_auth:
            ``True`` if you want to use GSS-API authentication
        :param bool gss_kex:
            Perform GSS-API Key Exchange and user authentication
        :param bool gss_deleg_creds: Delegate GSS-API client credentials or not
        :param str gss_host:
            The targets name in the kerberos database. default: hostname
        :param bool gss_trust_dns:
            Indicates whether or not the DNS is trusted to securely
            canonicalize the name of the host being connected to (default
            ``True``).
        :param float banner_timeout: an optional timeout (in seconds) to wait
            for the SSH banner to be presented.
        :param float auth_timeout: an optional timeout (in seconds) to wait for
            an authentication response.

        :raises:
            `.BadHostKeyException` -- if the server's host key could not be
            verified
        :raises: `.AuthenticationException` -- if authentication failed
        :raises:
            `.SSHException` -- if there was any other error connecting or
            establishing an SSH session
        :raises socket.error: if a socket error occurred while connecting

        .. versionchanged:: 1.15
            Added the ``banner_timeout``, ``gss_auth``, ``gss_kex``,
            ``gss_deleg_creds`` and ``gss_host`` arguments.
        .. versionchanged:: 2.3
            Added the ``gss_trust_dns`` argument.
        """
        if not sock:
            errors = {}
            # Try multiple possible address families (e.g. IPv4 vs IPv6)
            to_try = list(self._families_and_addresses(hostname, port))
            for af, addr in to_try:
                try:
                    sock = socket.socket(af, socket.SOCK_STREAM)
                    if timeout is not None:
                        try:
                            sock.settimeout(timeout)
                        except:
                            pass
                    retry_on_signal(lambda: sock.connect(addr))
                    # Break out of the loop on success
                    break
                except socket.error as e:
                    # Raise anything that isn't a straight up connection error
                    # (such as a resolution error)
                    if e.errno not in (ECONNREFUSED, EHOSTUNREACH):
                        raise
                    # Capture anything else so we know how the run looks once
                    # iteration is complete. Retain info about which attempt
                    # this was.
                    errors[addr] = e

            # Make sure we explode usefully if no address family attempts
            # succeeded. We've no way of knowing which error is the "right"
            # one, so we construct a hybrid exception containing all the real
            # ones, of a subclass that client code should still be watching for
            # (socket.error)
            if len(errors) == len(to_try):
                raise NoValidConnectionsError(errors)

        t = self._transport = Transport(sock,
                                        gss_kex=gss_kex,
                                        gss_deleg_creds=gss_deleg_creds)
        t.use_compression(compress=compress)
        t.set_gss_host(
            # t.hostname may be None, but GSS-API requires a target name.
            # Therefore use hostname as fallback.
            gss_host=gss_host or hostname,
            trust_dns=gss_trust_dns,
            gssapi_requested=gss_auth or gss_kex,
        )
        if self._log_channel is not None:
            t.set_log_channel(self._log_channel)
        if banner_timeout is not None:
            t.banner_timeout = banner_timeout
        if auth_timeout is not None:
            t.auth_timeout = auth_timeout

        if port == SSH_PORT:
            server_hostkey_name = hostname
        else:
            server_hostkey_name = "[%s]:%d" % (hostname, port)
        our_server_keys = None

        our_server_keys = self._system_host_keys.get(server_hostkey_name)
        if our_server_keys is None:
            our_server_keys = self._host_keys.get(server_hostkey_name)
        if our_server_keys is not None:
            keytype = our_server_keys.keys()[0]
            sec_opts = t.get_security_options()
            other_types = [x for x in sec_opts.key_types if x != keytype]
            sec_opts.key_types = [keytype] + other_types

        t.start_client(timeout=timeout)

        # If GSS-API Key Exchange is performed we are not required to check the
        # host key, because the host is authenticated via GSS-API / SSPI as
        # well as our client.
        if not self._transport.gss_kex_used:
            server_key = t.get_remote_server_key()
            if our_server_keys is None:
                # will raise exception if the key is rejected
                self._policy.missing_host_key(self, server_hostkey_name,
                                              server_key)
            else:
                our_key = our_server_keys.get(server_key.get_name())
                if our_key != server_key:
                    if our_key is None:
                        our_key = list(our_server_keys.values())[0]
                    raise BadHostKeyException(hostname, server_key, our_key)

        if username is None:
            username = getpass.getuser()

        if key_filename is None:
            key_filenames = []
        elif isinstance(key_filename, string_types):
            key_filenames = [key_filename]
        else:
            key_filenames = key_filename

        self._auth(
            username,
            password,
            pkey,
            key_filenames,
            allow_agent,
            look_for_keys,
            gss_auth,
            gss_kex,
            gss_deleg_creds,
            t.gss_host,
        )
Esempio n. 31
0
    def connect(self,
                hostname,
                port=SSH_PORT,
                username=None,
                password=None,
                pkey=None,
                key_filename=None,
                timeout=None,
                allow_agent=True,
                look_for_keys=True,
                compress=False,
                sock=None,
                gss_auth=False,
                gss_kex=False,
                gss_deleg_creds=True,
                gss_host=None,
                banner_timeout=None):
        """
        Connect to an SSH server and authenticate to it.  The server's host key
        is checked against the system host keys (see `load_system_host_keys`)
        and any local host keys (`load_host_keys`).  If the server's hostname
        is not found in either set of host keys, the missing host key policy
        is used (see `set_missing_host_key_policy`).  The default policy is
        to reject the key and raise an `.SSHException`.

        Authentication is attempted in the following order of priority:

            - The ``pkey`` or ``key_filename`` passed in (if any)
            - Any key we can find through an SSH agent
            - Any "id_rsa", "id_dsa" or "id_ecdsa" key discoverable in
              ``~/.ssh/``
            - Plain username/password auth, if a password was given

        If a private key requires a password to unlock it, and a password is
        passed in, that password will be used to attempt to unlock the key.

        :param str hostname: the server to connect to
        :param int port: the server port to connect to
        :param str username:
            the username to authenticate as (defaults to the current local
            username)
        :param str password:
            a password to use for authentication or for unlocking a private key
        :param .PKey pkey: an optional private key to use for authentication
        :param str key_filename:
            the filename, or list of filenames, of optional private key(s) to
            try for authentication
        :param float timeout: an optional timeout (in seconds) for the TCP connect
        :param bool allow_agent: set to False to disable connecting to the SSH agent
        :param bool look_for_keys:
            set to False to disable searching for discoverable private key
            files in ``~/.ssh/``
        :param bool compress: set to True to turn on compression
        :param socket sock:
            an open socket or socket-like object (such as a `.Channel`) to use
            for communication to the target host
        :param bool gss_auth: ``True`` if you want to use GSS-API authentication
        :param bool gss_kex: Perform GSS-API Key Exchange and user authentication
        :param bool gss_deleg_creds: Delegate GSS-API client credentials or not
        :param str gss_host: The targets name in the kerberos database. default: hostname
        :param float banner_timeout: an optional timeout (in seconds) to wait
            for the SSH banner to be presented.

        :raises BadHostKeyException: if the server's host key could not be
            verified
        :raises AuthenticationException: if authentication failed
        :raises SSHException: if there was any other error connecting or
            establishing an SSH session
        :raises socket.error: if a socket error occurred while connecting

        .. versionchanged:: 1.15
            Added the ``banner_timeout``, ``gss_auth``, ``gss_kex``,
            ``gss_deleg_creds`` and ``gss_host`` arguments.
        """
        if not sock:
            for (family, socktype, proto, canonname,
                 sockaddr) in socket.getaddrinfo(hostname, port,
                                                 socket.AF_UNSPEC,
                                                 socket.SOCK_STREAM):
                if socktype == socket.SOCK_STREAM:
                    af = family
                    addr = sockaddr
                    break
            else:
                # some OS like AIX don't indicate SOCK_STREAM support, so just guess. :(
                af, _, _, _, addr = socket.getaddrinfo(hostname, port,
                                                       socket.AF_UNSPEC,
                                                       socket.SOCK_STREAM)
            sock = socket.socket(af, socket.SOCK_STREAM)
            if timeout is not None:
                try:
                    sock.settimeout(timeout)
                except:
                    pass
            retry_on_signal(lambda: sock.connect(addr))

        t = self._transport = Transport(sock,
                                        gss_kex=gss_kex,
                                        gss_deleg_creds=gss_deleg_creds)
        t.use_compression(compress=compress)
        if gss_kex and gss_host is None:
            t.set_gss_host(hostname)
        elif gss_kex and gss_host is not None:
            t.set_gss_host(gss_host)
        else:
            pass
        if self._log_channel is not None:
            t.set_log_channel(self._log_channel)
        if banner_timeout is not None:
            t.banner_timeout = banner_timeout
        t.start_client()
        ResourceManager.register(self, t)

        server_key = t.get_remote_server_key()
        keytype = server_key.get_name()

        if port == SSH_PORT:
            server_hostkey_name = hostname
        else:
            server_hostkey_name = "[%s]:%d" % (hostname, port)

        # If GSS-API Key Exchange is performed we are not required to check the
        # host key, because the host is authenticated via GSS-API / SSPI as
        # well as our client.
        if not self._transport.use_gss_kex:
            our_server_key = self._system_host_keys.get(
                server_hostkey_name, {}).get(keytype, None)
            if our_server_key is None:
                our_server_key = self._host_keys.get(server_hostkey_name,
                                                     {}).get(keytype, None)
            if our_server_key is None:
                # will raise exception if the key is rejected; let that fall out
                self._policy.missing_host_key(self, server_hostkey_name,
                                              server_key)
                # if the callback returns, assume the key is ok
                our_server_key = server_key

            if server_key != our_server_key:
                raise BadHostKeyException(hostname, server_key, our_server_key)

        if username is None:
            username = getpass.getuser()

        if key_filename is None:
            key_filenames = []
        elif isinstance(key_filename, string_types):
            key_filenames = [key_filename]
        else:
            key_filenames = key_filename
        if gss_host is None:
            gss_host = hostname
        self._auth(username, password, pkey, key_filenames, allow_agent,
                   look_for_keys, gss_auth, gss_kex, gss_deleg_creds, gss_host)
Esempio n. 32
0
def ssh_paramiko_connect_to(display_desc):
    #plain socket attributes:
    dtype = display_desc["type"]
    host = display_desc["host"]
    port = display_desc.get("ssh-port", 22)
    #ssh and command attributes:
    username = display_desc.get("username") or get_username()
    if "proxy_host" in display_desc:
        display_desc.setdefault("proxy_username", get_username())
    password = display_desc.get("password")
    remote_xpra = display_desc["remote_xpra"]
    proxy_command = display_desc["proxy_command"]       #ie: "_proxy_start"
    socket_dir = display_desc.get("socket_dir")
    display = display_desc.get("display")
    display_as_args = display_desc["display_as_args"]   #ie: "--start=xterm :10"
    paramiko_config = display_desc.copy()
    paramiko_config.update(display_desc.get("paramiko-config", {}))
    socket_info = {
            "host"  : host,
            "port"  : port,
            }
    def get_keyfiles(host_config, config_name="key"):
        keyfiles = (host_config or {}).get("identityfile") or get_default_keyfiles()
        keyfile = paramiko_config.get(config_name)
        if keyfile:
            keyfiles.insert(0, keyfile)
        return keyfiles

    with nogssapi_context():
        from paramiko import SSHConfig, ProxyCommand
        ssh_config = SSHConfig()
        user_config_file = os.path.expanduser("~/.ssh/config")
        sock = None
        host_config = None
        if os.path.exists(user_config_file):
            with open(user_config_file) as f:
                ssh_config.parse(f)
            log("parsed user config '%s': %i hosts found", user_config_file, len(ssh_config.get_hostnames()))
            host_config = ssh_config.lookup(host)
            if host_config:
                log("got host config for '%s': %s", host, host_config)
                chost = host_config.get("hostname", host)
                cusername = host_config.get("user", username)
                cport = host_config.get("port", port)
                try:
                    port = int(cport)
                except (TypeError, ValueError):
                    raise InitExit(EXIT_SSH_FAILURE, "invalid ssh port specified: '%s'" % cport) from None
                proxycommand = host_config.get("proxycommand")
                if proxycommand:
                    log("found proxycommand='%s' for host '%s'", proxycommand, chost)
                    sock = ProxyCommand(proxycommand)
                    log("ProxyCommand(%s)=%s", proxycommand, sock)
                    from xpra.child_reaper import getChildReaper
                    cmd = getattr(sock, "cmd", [])
                    def proxycommand_ended(proc):
                        log("proxycommand_ended(%s) exit code=%s", proc, proc.poll())
                    getChildReaper().add_process(sock.process, "paramiko-ssh-client", cmd, True, True,
                                                 callback=proxycommand_ended)
                    proxy_keys = get_keyfiles(host_config, "proxy_key")
                    log("proxy keys=%s", proxy_keys)
                    from paramiko.client import SSHClient
                    ssh_client = SSHClient()
                    ssh_client.load_system_host_keys()
                    log("ssh proxy command connect to %s", (chost, cport, sock))
                    ssh_client.connect(chost, cport, sock=sock)
                    transport = ssh_client.get_transport()
                    do_ssh_paramiko_connect_to(transport, chost,
                                               cusername, password,
                                               host_config or ssh_config.lookup("*"),
                                               proxy_keys,
                                               paramiko_config)
                    chan = paramiko_run_remote_xpra(transport, proxy_command, remote_xpra, socket_dir, display_as_args)
                    peername = (chost, cport)
                    conn = SSHProxyCommandConnection(chan, peername, peername, socket_info)
                    conn.target = host_target_string("ssh", cusername, chost, port, display)
                    conn.timeout = SOCKET_TIMEOUT
                    conn.start_stderr_reader()
                    conn.process = (sock.process, "ssh", cmd)
                    from xpra.net import bytestreams
                    from paramiko.ssh_exception import ProxyCommandFailure
                    bytestreams.CLOSED_EXCEPTIONS = tuple(list(bytestreams.CLOSED_EXCEPTIONS)+[ProxyCommandFailure])
                    return conn

        keys = get_keyfiles(host_config)
        from xpra.scripts.main import socket_connect
        from paramiko.transport import Transport
        from paramiko import SSHException
        if "proxy_host" in display_desc:
            proxy_host = display_desc["proxy_host"]
            proxy_port = display_desc.get("proxy_port", 22)
            proxy_username = display_desc.get("proxy_username", username)
            proxy_password = display_desc.get("proxy_password", password)
            proxy_keys = get_keyfiles(host_config, "proxy_key")
            sock = socket_connect(dtype, proxy_host, proxy_port)
            middle_transport = Transport(sock)
            middle_transport.use_compression(False)
            try:
                middle_transport.start_client()
            except SSHException as e:
                log("start_client()", exc_info=True)
                raise InitExit(EXIT_SSH_FAILURE, "SSH negotiation failed: %s" % e) from None
            proxy_host_config = ssh_config.lookup(host)
            do_ssh_paramiko_connect_to(middle_transport, proxy_host,
                                       proxy_username, proxy_password,
                                       proxy_host_config or ssh_config.lookup("*"),
                                       proxy_keys,
                                       paramiko_config)
            log("Opening proxy channel")
            chan_to_middle = middle_transport.open_channel("direct-tcpip", (host, port), ('localhost', 0))

            transport = Transport(chan_to_middle)
            transport.use_compression(False)
            try:
                transport.start_client()
            except SSHException as e:
                log("start_client()", exc_info=True)
                raise InitExit(EXIT_SSH_FAILURE, "SSH negotiation failed: %s" % e)
            do_ssh_paramiko_connect_to(transport, host,
                                       username, password,
                                       host_config or ssh_config.lookup("*"),
                                       keys,
                                       paramiko_config)
            chan = paramiko_run_remote_xpra(transport, proxy_command, remote_xpra, socket_dir, display_as_args)
            peername = (host, port)
            conn = SSHProxyCommandConnection(chan, peername, peername, socket_info)
            conn.target = "%s via %s" % (
                host_target_string("ssh", username, host, port, display),
                host_target_string("ssh", proxy_username, proxy_host, proxy_port, None),
                )
            conn.timeout = SOCKET_TIMEOUT
            conn.start_stderr_reader()
            return conn

        #plain TCP connection to the server,
        #we open it then give the socket to paramiko:
        sock = socket_connect(dtype, host, port)
        sockname = sock.getsockname()
        peername = sock.getpeername()
        log("paramiko socket_connect: sockname=%s, peername=%s", sockname, peername)
        transport = Transport(sock)
        transport.use_compression(False)
        try:
            transport.start_client()
        except SSHException as e:
            log("start_client()", exc_info=True)
            raise InitExit(EXIT_SSH_FAILURE, "SSH negotiation failed: %s" % e) from None
        do_ssh_paramiko_connect_to(transport, host, username, password,
                                   host_config or ssh_config.lookup("*"),
                                   keys,
                                   paramiko_config)
        chan = paramiko_run_remote_xpra(transport, proxy_command, remote_xpra, socket_dir, display_as_args)
        conn = SSHSocketConnection(chan, sock, sockname, peername, (host, port), socket_info)
        conn.target = host_target_string("ssh", username, host, port, display)
        conn.timeout = SOCKET_TIMEOUT
        conn.start_stderr_reader()
        return conn
Esempio n. 33
0
class HetznerStorage:
    def __init__(self):
        self.__host = os.environ.get('HETZNER_STORAGEBOX')
        self.__port = int(os.environ.get('HETZNER_PORT', '22'))
        self.__username = os.environ.get('HETZNER_USER')
        self.__password = os.environ.get('HETZNER_PASSWORD')
        self.__path = os.environ.get('HETNZER_PATH', '/backups')
        self.__hostKey = os.environ.get('HETZNER_HOSTKEY')
        self.__transport = None
        defaultSSHKeyFilePath = os.environ.get('HOME')+"/.ssh/id_rsa"
        self.__keyFilePath = os.environ.get('HETZNER_SSHKEY', defaultSSHKeyFilePath)
        self.__keyFileChoose = os.environ.get('HETZNER_SSHKEY_CHOOSE', 'first')
        self._usePassword = False
        self.uploadChunkSize = int(os.environ.get('UPLOAD_CHUNK_SIZE', '2097152'))
        self.downloadChunkSize = int(os.environ.get('DOWLOAD_CHUNK_SIZE', '2097152'))

    def load(self):
        self.__connect()
        pass

    def __connect(self):
        hostKey = self.__getHostKey()

        if self.__transport:
            self.__transport.close()
        self.__transport = Transport( (self.__host, self.__port) )

        if self._usePassword:
            password = self.__password
            if not password:
                password = self.__promptPassword()
            self.__transport.connect(hostKey, self.__username, password)
        else:
            privateKey = self.__loadKey()
            self.__transport.connect(hostKey, self.__username, pkey=privateKey)

        self.__sftp = SFTPClient.from_transport(self.__transport)
        return self

    def __promptPassword(self):
        return getpass.getpass('Storagebox password:'******'any':
            return None

        hostKeyEntry = HostKeyEntry.from_line(self.__hostKey)
            
        return hostKeyEntry.key
            
    def createResort(self, resortName):
        self.__sftp.mkdir( self.__path+'/'+resortName, 0o755)

    def removeResort(self, resortName):
        self.__rmdir(self.__path+'/'+resortName, True)

    def __rmdir(self, directory, verbose=False):
        print(directory)
        for entry in self.__sftp.listdir_attr( directory ):
            if stat.S_ISDIR(entry.st_mode):
                subdir = directory+'/'+entry.filename
                if verbose:
                    print("Recursing into "+subdir)
                self.__rmdir(subdir)
            else:
                filePath = directory+'/'+entry.filename
                if verbose:
                    print("Removing into "+filePath)
                self.__sftp.remove(filePath)
                
        if verbose:
            print("Removing "+directory)
            
        self.__sftp.rmdir(directory)

    def findResort(self, resortName):
        directories = self.__sftp.listdir( self.__path )

        if resortName not in directories:
            raise NoSuchResortError(resortName)

        return self.buildResort(resortName)

    def getResorts(self):
        directories = self.__sftp.listdir( self.__path )

        resorts = []
        for directory in directories:
            resorts.append( self.buildResort(directory) )

        return resorts
    
    def buildResort(self, resortName):
        resort = Resort().name(resortName).storage(self)
        return self.rebuildResort(resort)

    def rebuildResort(self, resort):
        resortPath = resort.appendName(self.__path+'/')

        resortDirectories = self.__sftp.listdir( resortPath )
        if 'mysql' in resortDirectories:
            resort.withMySQL( 
                    MySQL()
                    .resort(resort)
                    )

        if 'postgres' in resortDirectories:
            resort.withPostgres()

        if 'files' in resortDirectories:
            path = '/'.join([
                resortPath,
                'files'
                ])
            resort.withBorg(
                    Borg()
                    .host(self.__host)
                    .port(23)
                    .path(path)
                    .user(self.__username)
                    .keyFilePath(self.__keyFilePath)
                    )

        return resort

    def resort(self, resortName):
        self._currentResort = resortName
        return self

    def adapter(self, adapterName):
        self.currentAdapter = adapterName
        return self

    def createAdapter(self, adapterName):
        self.__sftp.mkdir( self.__path+'/'+self._currentResort+'/'+adapterName, 0o755)
        return self

    def usePassword(self):
        self._usePassword = True
        return self
    
    def createFolder(self, folderName):
        path = '/'.join([
            self.__path,
            self._currentResort,
            self.currentAdapter,
            folderName
            ]) 
        self.__sftp.mkdir( path, 0o755)

    def listFolder(self, path):
        pathParts = [
            self.__path,
            self._currentResort,
            self.currentAdapter,
            ]
        if path is not None:
            pathParts.append(path)
        path = '/'.join(pathParts) 
        return self.__sftp.listdir( path )

    def fileContent(self, path):
        pathParts = [
            self.__path,
            self._currentResort,
            self.currentAdapter,
            path,
            ]
        path = '/'.join(pathParts) 
        with self.__sftp.file( path ) as file:
            return file.read()

    def remove(self, remotePath, verbose=False):
        fullRemotePath = '/'.join([
            self.__path,
            self._currentResort,
            self.currentAdapter,
            remotePath,
            ])

        self.__rmdir(fullRemotePath, verbose)

    def upload(self, localPath, remotePath, verbose=False):
        fullRemotePath = '/'.join([
            self.__path,
            self._currentResort,
            self.currentAdapter,
            remotePath,
            ])

        if os.path.isdir(localPath):
            self.__uploadDirectory(localPath, fullRemotePath, verbose)
        else:
            self.__uploadFile(localPath, fullRemotePath, verbose)

    def __uploadDirectory(self, localPath, remotePath, verbose=False):
        mustMake = True
        try:
            remotePathStatus = self.__sftp.stat(remotePath)
            if not stat.S_ISDIR(remotePathStatus.st_mode):
                mustMake = False
        except FileNotFoundError:
            pass
                
        if mustMake:
            self.__sftp.mkdir(remotePath)

        for localFileName in os.listdir( localPath ):
            localFilePath = localPath + '/' + localFileName
            remoteFilePath = remotePath + '/' + localFileName
            if os.path.isdir(localFilePath):
                if verbose:
                    print("Recursing into "+localFilePath+" as "+remoteFilePath)
                self.__uploadDirectory(localFilePath, remoteFilePath, verbose)
            else:
                self.__uploadFile(localFilePath, remoteFilePath, verbose)
        pass

    def __uploadFile(self, localPath, remotePath, verbose=False):
        if verbose:
            print("Uploading "+localPath+" as "+remotePath)
        with open(localPath, 'rb') as localFile:
            with self.__sftp.file(remotePath, 'w') as remoteFile:
                while True:
                    data = localFile.read(self.uploadChunkSize)
                    if not data:
                        break
                    remoteFile.write(data)

    def download(self, remotePath, localPath, verbose=False):
        fullRemotePath = '/'.join([
            self.__path,
            self._currentResort,
            self.currentAdapter,
            remotePath,
            ])
        pathStat = self.__sftp.stat(fullRemotePath)
        if stat.S_ISDIR(pathStat.st_mode):
            self.__downloadDirectory(fullRemotePath, localPath,  verbose)
        else:
            self.__downloadFile(fullRemotePath, localPath, verbose)

    def __downloadDirectory(self, remotePath, localPath, verbose=False):
        mustMake = True
        try:
            if os.path.isdir(localPath):
                mustMake = False
        except FileNotFoundError:
            pass
                
        if mustMake:
            os.mkdir(localPath)

        for remoteFileAttribute in self.__sftp.listdir_attr( remotePath ):
            fileName = remoteFileAttribute.filename
            localFilePath = localPath + '/' + fileName
            remoteFilePath = remotePath + '/' + fileName

            if stat.S_ISDIR(remoteFileAttribute.st_mode):
                if verbose:
                    print("Recursing into "+localFilePath+" as "+remoteFilePath)
                self.__downloadDirectory(remoteFilePath, localFilePath, verbose)
            else:
                self.__downloadFile(remoteFilePath, localFilePath, verbose)
        pass

    def __downloadFile(self, remotePath, localPath, verbose=False):
        if verbose:
            print("Downloading "+remotePath+" as "+localPath)
        with self.__sftp.file(remotePath, 'rb') as remoteFile:
            with open(localPath, 'wb') as localFile:
                while True:
                    data = remoteFile.read(self.downloadChunkSize)
                    if not data:
                        break
                    localFile.write(data)

    def generateId(self):
        return RSAKey.generate(4096)

    def copyId(self, privateKey = None):
        if '.ssh' not in self.__sftp.listdir('/'):
            self.__sftp.mkdir('/.ssh', 0o700)

        if not privateKey:
            privateKey = self.__loadKey()

        with self.__sftp.open('/.ssh/authorized_keys', 'r') as f:
            authorizedKeys = f.read()
        fileContent = authorizedKeys.decode('utf-8')

        if fileContent[ -1 ] != '\n':
            print("File does not end in newline - adding")
            with self.__sftp.open('/.ssh/authorized_keys', 'a+') as f:
                f.write('\n')

        rfcPublicKey = self.__publicRFC4716(privateKey)
        publicKey = self.__publicKey(privateKey)

        if rfcPublicKey not in fileContent:
            print("public key in rfc format not in authorized keys - inserting")
            with self.__sftp.open('/.ssh/authorized_keys', 'a+') as f:
                f.write(rfcPublicKey+'\n')
        else:
            print('public key in rfc format already present')

        if publicKey not in fileContent:
            print("public key not in authorized keys - inserting")
            with self.__sftp.open('/.ssh/authorized_keys', 'a+') as f:
                f.write(publicKey+'\n')
        else:
            print('public key already present')
            

    def __loadKey(self):
        if self.__keyFilePath == 'agent':
            return self.__loadFromAgent()

        try:
            return RSAKey.from_private_key_file(self.__keyFilePath)
        except FileNotFoundError:
            print("Failed to load "+self.__keyFilePath+" trying the ssh-agent.")
            return self.__loadFromAgent()

    def __loadFromAgent(self):
        agent = Agent()
        keys = agent.get_keys()
        if len(keys) == 0:
            raise KeyError("No keys found in the ssh agent. Did you add them with ssh-add?")
            
        return self.__pick_key(keys)

    def __pick_key(self,keys):
        if len(keys) == 0:
            raise KeyError("No ssh keys received from ssh agent")

        if self.__keyFileChoose == 'first':
            return keys[0]

        for key in keys:
            if key.get_base64() == self.__keyFileChoose:
                return key

        raise KeyError("No ssh key matching the given public key received from the ssh-agent")
    
    def __publicRFC4716(self, privateKey):
        # NOte: rfc4716 says 72 bytes at most but ssh-keygen into rfc4716
        # creates 70 character lines
        publicKeyPart = '\n'.join(list(self.chunkstring(privateKey.get_base64(), 70)))

        key = '\n'.join([
            '---- BEGIN SSH2 PUBLIC KEY ----',
            publicKeyPart,
            '---- END SSH2 PUBLIC KEY ----'
        ])
        return key

    def chunkstring(self, string, length):
        return (string[0+i:length+i] for i in range(0, len(string), length))

    def __publicKey(self, privateKey):
        key = privateKey.get_name()
        key += ' '
        key += privateKey.get_base64()
        return key
Esempio n. 34
0
# config = configparser.ConfigParser()
# config.read("config.ini", encoding='utf-8')
# print(config.get("BMC", "userid"))
# print(config.get("ipmitool", "path"))

import paramiko
from paramiko.transport import Channel
from paramiko.transport import Transport
import socket
import threading
import time

socket1 = socket.socket()
socket1.bind(("127.0.0.1", 99))
socket1.listen(5)
print(socket1)
transport1 = Transport(socket1)
t1 = threading.Thread(target=transport1.start_server)
t1.start()
print(68)
print(transport1)
with Channel(chanid=transport1) as c1:
    c1.recv_ready()
    print(c1)
    # sftp = paramiko.SFTPServer(channel=chanel1, name="", server="")

    while True:
        print(c1.active)

print(55)
Esempio n. 35
0
class Repository:
    def __init__(self, url):
        self.url = url
        self.index = {}

        self.read_lock = RepoReadLock(url)
        self.write_lock = RepoWriteLock(url)

        self.client = None
        self.transport = None
        self.socket = socket()

        self.opened = False

    def open(self):
        """
        Opens the connection
        """

        self.socket.connect((interpret_urlish(self.url)[1], 22))
        self.transport = Transport(self.socket)
        self.transport.start_client()
        authenticate_transport(self.transport)
        self.client = self.transport.open_sftp_client()
        target_path = interpret_urlish(self.url)[2]
        try:
            self.client.stat(target_path)
        except IOError:
            self.client.mkdir(target_path)
        self.client.chdir(target_path)
        self.opened = True

    def close(self):
        """
        Closes the connection
        """

        if not self.opened:
            return
        self.client.close()
        self.transport.close()
        self.socket.close()
        self.opened = False

    def update(self):
        """
        Update the information in this class to match that of the remote.

        Raises exceptions if remote is invalid or in an invalid state
        """

        if not self.opened:
            self.open()

        with self.read_lock:
            with self.client.open("index.json") as f:
                self.index = json.load(f)

    def get_script(self, hname=None):
        """
        Get the script object
        """
        if hname is None:
            hname = self.index["start"]
        return self.index["scripts"][hname]

    def download_script(self, hname=None):
        if hname is None:
            hname = self.index["start"]
        with self.read_lock:
            with self.client.open("scripts/" + hname + ".py", "r") as f:
                return f.read()

    def get_revision(self):
        return self.index["revision"]

    def append_script(self, script_obj, script_contents):
        h = sha512()
        h.update(script_contents.encode("utf-7"))
        hname = h.hexdigest()
        script_obj["prev"] = self.index["end"]

        with self.write_lock:
            self.index["revision"] += 1
            if self.index["end"]:
                self.index["scripts"][self.index["end"]]["next"] = hname
            self.index["end"] = hname
            self.index["scripts"][hname] = script_obj

            if self.index["start"] == "":
                self.index["start"] = hname

            self._write()
            with self.client.open("scripts/" + hname + ".py", "w") as f:
                f.write(script_contents)

    def _write(self):
        with self.client.open("index.json", "w") as f:
            json.dump(self.index, f)

    def write(self):
        with self.write_lock:
            self._write()

    def __iter__(self):
        return FollowChainIterator(self, self.index["start"])

    def iterate_from(self, pos):
        return FollowChainIterator(self, pos)

    def new(self):
        if not self.opened:
            self.open()

        try:
            self.client.stat("index.json")
            raise RuntimeError(
                "already init-ed, manually delete the folder to re-init")
        except IOError:
            pass

        # create the skeleton fs
        self.client.mkdir("locks")
        self.client.mkdir("scripts")

        # create a basic index.json
        self.index = {
            "version": 1,
            "revision": 0,
            "start": "",
            "end": "",
            "scripts": {}
        }

        self.write()
Esempio n. 36
0
def ssh_paramiko_connect_to(display_desc):
    #plain socket attributes:
    dtype = display_desc["type"]
    host = display_desc["host"]
    port = display_desc.get("ssh-port", 22)
    #ssh and command attributes:
    username = display_desc.get("username") or get_username()
    if "proxy_host" in display_desc:
        display_desc.setdefault("proxy_username", get_username())
    password = display_desc.get("password")
    target = ssh_target_string(display_desc)
    remote_xpra = display_desc["remote_xpra"]
    proxy_command = display_desc["proxy_command"]  #ie: "_proxy_start"
    socket_dir = display_desc.get("socket_dir")
    display_as_args = display_desc["display_as_args"]  #ie: "--start=xterm :10"
    socket_info = {
        "host": host,
        "port": port,
    }
    with nogssapi_context():
        from paramiko import SSHConfig, ProxyCommand
        ssh_config = SSHConfig()
        user_config_file = os.path.expanduser("~/.ssh/config")
        sock = None
        host_config = None
        if os.path.exists(user_config_file):
            with open(user_config_file) as f:
                ssh_config.parse(f)
            host_config = ssh_config.lookup(host)
            if host_config:
                host = host_config.get("hostname", host)
                username = host_config.get("username", username)
                port = host_config.get("port", port)
                proxycommand = host_config.get("proxycommand")
                if proxycommand:
                    sock = ProxyCommand(proxycommand)
                    from xpra.child_reaper import getChildReaper
                    cmd = getattr(sock, "cmd", [])
                    getChildReaper().add_process(sock.process,
                                                 "paramiko-ssh-client", cmd,
                                                 True, True)
                    log("found proxycommand='%s' for host '%s'", proxycommand,
                        host)
                    from paramiko.client import SSHClient
                    ssh_client = SSHClient()
                    ssh_client.load_system_host_keys()
                    ssh_client.connect(host, port, sock=sock)
                    transport = ssh_client.get_transport()
                    do_ssh_paramiko_connect_to(
                        transport, host, username, password, host_config
                        or ssh_config.lookup("*"))
                    chan = paramiko_run_remote_xpra(transport, proxy_command,
                                                    remote_xpra, socket_dir,
                                                    display_as_args)
                    peername = (host, port)
                    conn = SSHProxyCommandConnection(chan, peername, target,
                                                     socket_info)
                    conn.timeout = SOCKET_TIMEOUT
                    conn.start_stderr_reader()
                    conn.process = (sock.process, "ssh", cmd)
                    from xpra.net import bytestreams
                    from paramiko.ssh_exception import ProxyCommandFailure
                    bytestreams.CLOSED_EXCEPTIONS = tuple(
                        list(bytestreams.CLOSED_EXCEPTIONS) +
                        [ProxyCommandFailure])
                    return conn
        from xpra.scripts.main import socket_connect
        from paramiko.transport import Transport
        from paramiko import SSHException
        if "proxy_host" in display_desc:
            proxy_host = display_desc["proxy_host"]
            proxy_port = display_desc.get("proxy_port", 22)
            proxy_username = display_desc.get("proxy_username", username)
            proxy_password = display_desc.get("proxy_password", password)
            sock = socket_connect(dtype, proxy_host, proxy_port)
            middle_transport = Transport(sock)
            middle_transport.use_compression(False)
            try:
                middle_transport.start_client()
            except SSHException as e:
                log("start_client()", exc_info=True)
                raise InitException("SSH negotiation failed: %s" % e)
            proxy_host_config = ssh_config.lookup(host)
            do_ssh_paramiko_connect_to(
                middle_transport, proxy_host, proxy_username, proxy_password,
                proxy_host_config or ssh_config.lookup("*"))
            log("Opening proxy channel")
            chan_to_middle = middle_transport.open_channel(
                "direct-tcpip", (host, port), ('localhost', 0))

            transport = Transport(chan_to_middle)
            transport.use_compression(False)
            try:
                transport.start_client()
            except SSHException as e:
                log("start_client()", exc_info=True)
                raise InitException("SSH negotiation failed: %s" % e)
            do_ssh_paramiko_connect_to(transport, host, username, password,
                                       host_config or ssh_config.lookup("*"))
            chan = paramiko_run_remote_xpra(transport, proxy_command,
                                            remote_xpra, socket_dir,
                                            display_as_args)

            peername = (host, port)
            conn = SSHProxyCommandConnection(chan, peername, target,
                                             socket_info)
            conn.timeout = SOCKET_TIMEOUT
            conn.start_stderr_reader()
            return conn

        #plain TCP connection to the server,
        #we open it then give the socket to paramiko:
        sock = socket_connect(dtype, host, port)
        sockname = sock.getsockname()
        peername = sock.getpeername()
        log("paramiko socket_connect: sockname=%s, peername=%s", sockname,
            peername)
        transport = Transport(sock)
        transport.use_compression(False)
        try:
            transport.start_client()
        except SSHException as e:
            log("start_client()", exc_info=True)
            raise InitException("SSH negotiation failed: %s" % e)
        do_ssh_paramiko_connect_to(transport, host, username, password,
                                   host_config or ssh_config.lookup("*"))
        chan = paramiko_run_remote_xpra(transport, proxy_command, remote_xpra,
                                        socket_dir, display_as_args)
        conn = SSHSocketConnection(chan, sock, sockname, peername, target,
                                   socket_info)
        conn.timeout = SOCKET_TIMEOUT
        conn.start_stderr_reader()
        return conn
Esempio n. 37
0
    def connect(self,
                hostname,
                port=SSH_PORT,
                username=None,
                password=None,
                pkey=None,
                key_filename=None,
                timeout=None,
                allow_agent=True,
                look_for_keys=True):
        """
        Connect to an SSH server and authenticate to it.  The server's host key
        is checked against the system host keys (see L{load_system_host_keys})
        and any local host keys (L{load_host_keys}).  If the server's hostname
        is not found in either set of host keys, the missing host key policy
        is used (see L{set_missing_host_key_policy}).  The default policy is
        to reject the key and raise an L{SSHException}.

        Authentication is attempted in the following order of priority:

            - The C{pkey} or C{key_filename} passed in (if any)
            - Any key we can find through an SSH agent
            - Any "id_rsa" or "id_dsa" key discoverable in C{~/.ssh/}
            - Plain username/password auth, if a password was given

        If a private key requires a password to unlock it, and a password is
        passed in, that password will be used to attempt to unlock the key.

        @param hostname: the server to connect to
        @type hostname: str
        @param port: the server port to connect to
        @type port: int
        @param username: the username to authenticate as (defaults to the
            current local username)
        @type username: str
        @param password: a password to use for authentication or for unlocking
            a private key
        @type password: str
        @param pkey: an optional private key to use for authentication
        @type pkey: L{PKey}
        @param key_filename: the filename, or list of filenames, of optional
            private key(s) to try for authentication
        @type key_filename: str or list(str)
        @param timeout: an optional timeout (in seconds) for the TCP connect
        @type timeout: float
        @param allow_agent: set to False to disable connecting to the SSH agent
        @type allow_agent: bool
        @param look_for_keys: set to False to disable searching for discoverable
            private key files in C{~/.ssh/}
        @type look_for_keys: bool

        @raise BadHostKeyException: if the server's host key could not be
            verified
        @raise AuthenticationException: if authentication failed
        @raise SSHException: if there was any other error connecting or
            establishing an SSH session
        @raise socket.error: if a socket error occurred while connecting
        """
        for (family, socktype, proto, canonname,
             sockaddr) in socket.getaddrinfo(hostname, port, socket.AF_UNSPEC,
                                             socket.SOCK_STREAM):
            if socktype == socket.SOCK_STREAM:
                af = family
                addr = sockaddr
                break
        else:
            raise SSHException('No suitable address family for %s' % hostname)
        sock = socket.socket(af, socket.SOCK_STREAM)
        if timeout is not None:
            try:
                sock.settimeout(timeout)
            except:
                pass
        sock.connect(addr)
        t = self._transport = Transport(sock)

        if self._log_channel is not None:
            t.set_log_channel(self._log_channel)
        t.start_client()
        ResourceManager.register(self, t)

        server_key = t.get_remote_server_key()
        keytype = server_key.get_name()

        if port == SSH_PORT:
            server_hostkey_name = hostname
        else:
            server_hostkey_name = "[%s]:%d" % (hostname, port)
        our_server_key = self._system_host_keys.get(server_hostkey_name,
                                                    {}).get(keytype, None)
        if our_server_key is None:
            our_server_key = self._host_keys.get(server_hostkey_name,
                                                 {}).get(keytype, None)
        if our_server_key is None:
            # will raise exception if the key is rejected; let that fall out
            self._policy.missing_host_key(self, server_hostkey_name,
                                          server_key)
            # if the callback returns, assume the key is ok
            our_server_key = server_key

        if server_key != our_server_key:
            raise BadHostKeyException(hostname, server_key, our_server_key)

        if username is None:
            username = getpass.getuser()

        if key_filename is None:
            key_filenames = []
        elif isinstance(key_filename, (str, unicode)):
            key_filenames = [key_filename]
        else:
            key_filenames = key_filename
        self._auth(username, password, pkey, key_filenames, allow_agent,
                   look_for_keys)
Esempio n. 38
0
    def connect(
        self,
        hostname,
        port=SSH_PORT,
        username=None,
        password=None,
        pkey=None,
        key_filename=None,
        timeout=None,
        allow_agent=True,
        look_for_keys=True,
        compress=False,
        sock=None,
        gss_auth=False,
        gss_kex=False,
        gss_deleg_creds=True,
        gss_host=None,
        banner_timeout=None,
        auth_timeout=None,
        gss_trust_dns=True,
        passphrase=None,
    ):
        """
        Connect to an SSH server and authenticate to it.  The server's host key
        is checked against the system host keys (see `load_system_host_keys`)
        and any local host keys (`load_host_keys`).  If the server's hostname
        is not found in either set of host keys, the missing host key policy
        is used (see `set_missing_host_key_policy`).  The default policy is
        to reject the key and raise an `.SSHException`.

        Authentication is attempted in the following order of priority:

            - The ``pkey`` or ``key_filename`` passed in (if any)

              - ``key_filename`` may contain OpenSSH public certificate paths
                as well as regular private-key paths; when files ending in
                ``-cert.pub`` are found, they are assumed to match a private
                key, and both components will be loaded. (The private key
                itself does *not* need to be listed in ``key_filename`` for
                this to occur - *just* the certificate.)

            - Any key we can find through an SSH agent
            - Any "id_rsa", "id_dsa", "id_ecdsa", or "id_ed25519" key
              discoverable in ``~/.ssh/``

              - When OpenSSH-style public certificates exist that match an
                existing such private key (so e.g. one has ``id_rsa`` and
                ``id_rsa-cert.pub``) the certificate will be loaded alongside
                the private key and used for authentication.

            - Plain username/password auth, if a password was given

        If a private key requires a password to unlock it, and a password is
        passed in, that password will be used to attempt to unlock the key.

        :param str hostname: the server to connect to
        :param int port: the server port to connect to
        :param str username:
            the username to authenticate as (defaults to the current local
            username)
        :param str password:
            Used for password authentication; is also used for private key
            decryption if ``passphrase`` is not given.
        :param str passphrase:
            Used for decrypting private keys.
        :param .PKey pkey: an optional private key to use for authentication
        :param str key_filename:
            the filename, or list of filenames, of optional private key(s)
            and/or certs to try for authentication
        :param float timeout:
            an optional timeout (in seconds) for the TCP connect
        :param bool allow_agent:
            set to False to disable connecting to the SSH agent
        :param bool look_for_keys:
            set to False to disable searching for discoverable private key
            files in ``~/.ssh/``
        :param bool compress: set to True to turn on compression
        :param socket sock:
            an open socket or socket-like object (such as a `.Channel`) to use
            for communication to the target host
        :param bool gss_auth:
            ``True`` if you want to use GSS-API authentication
        :param bool gss_kex:
            Perform GSS-API Key Exchange and user authentication
        :param bool gss_deleg_creds: Delegate GSS-API client credentials or not
        :param str gss_host:
            The targets name in the kerberos database. default: hostname
        :param bool gss_trust_dns:
            Indicates whether or not the DNS is trusted to securely
            canonicalize the name of the host being connected to (default
            ``True``).
        :param float banner_timeout: an optional timeout (in seconds) to wait
            for the SSH banner to be presented.
        :param float auth_timeout: an optional timeout (in seconds) to wait for
            an authentication response.

        :raises:
            `.BadHostKeyException` -- if the server's host key could not be
            verified
        :raises: `.AuthenticationException` -- if authentication failed
        :raises:
            `.SSHException` -- if there was any other error connecting or
            establishing an SSH session
        :raises socket.error: if a socket error occurred while connecting

        .. versionchanged:: 1.15
            Added the ``banner_timeout``, ``gss_auth``, ``gss_kex``,
            ``gss_deleg_creds`` and ``gss_host`` arguments.
        .. versionchanged:: 2.3
            Added the ``gss_trust_dns`` argument.
        .. versionchanged:: 2.4
            Added the ``passphrase`` argument.
        """
        if not sock:
            sock = retry_on_signal(lambda: socket.create_connection(
                (hostname, port), timeout))

        t = self._transport = Transport(sock,
                                        gss_kex=gss_kex,
                                        gss_deleg_creds=gss_deleg_creds)
        t.use_compression(compress=compress)
        t.set_gss_host(
            # t.hostname may be None, but GSS-API requires a target name.
            # Therefore use hostname as fallback.
            gss_host=gss_host or hostname,
            trust_dns=gss_trust_dns,
            gssapi_requested=gss_auth or gss_kex,
        )
        if self._log_channel is not None:
            t.set_log_channel(self._log_channel)
        if banner_timeout is not None:
            t.banner_timeout = banner_timeout
        if auth_timeout is not None:
            t.auth_timeout = auth_timeout

        if port == SSH_PORT:
            server_hostkey_name = hostname
        else:
            server_hostkey_name = "[{}]:{}".format(hostname, port)
        our_server_keys = None

        our_server_keys = self._system_host_keys.get(server_hostkey_name)
        if our_server_keys is None:
            our_server_keys = self._host_keys.get(server_hostkey_name)
        if our_server_keys is not None:
            keytype = our_server_keys.keys()[0]
            sec_opts = t.get_security_options()
            other_types = [x for x in sec_opts.key_types if x != keytype]
            sec_opts.key_types = [keytype] + other_types

        t.start_client(timeout=timeout)

        # If GSS-API Key Exchange is performed we are not required to check the
        # host key, because the host is authenticated via GSS-API / SSPI as
        # well as our client.
        if not self._transport.gss_kex_used:
            server_key = t.get_remote_server_key()
            if our_server_keys is None:
                # will raise exception if the key is rejected
                self._policy.missing_host_key(self, server_hostkey_name,
                                              server_key)
            else:
                our_key = our_server_keys.get(server_key.get_name())
                if our_key != server_key:
                    if our_key is None:
                        our_key = list(our_server_keys.values())[0]
                    raise BadHostKeyException(hostname, server_key, our_key)

        if username is None:
            username = getpass.getuser()

        if key_filename is None:
            key_filenames = []
        elif isinstance(key_filename, string_types):
            key_filenames = [key_filename]
        else:
            key_filenames = key_filename

        self._auth(
            username,
            password,
            pkey,
            key_filenames,
            allow_agent,
            look_for_keys,
            gss_auth,
            gss_kex,
            gss_deleg_creds,
            t.gss_host,
            passphrase,
        )