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
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()
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))
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)
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 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
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
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
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
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 __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
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)
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
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 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
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
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')
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)
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')
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')
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
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?")
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
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
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))
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
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, )
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)
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
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
# 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)
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()
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
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)
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, )