diff options
Diffstat (limited to 'paramiko/transport.py')
-rw-r--r-- | paramiko/transport.py | 365 |
1 files changed, 250 insertions, 115 deletions
diff --git a/paramiko/transport.py b/paramiko/transport.py index eed00bc7..96bd4a07 100644 --- a/paramiko/transport.py +++ b/paramiko/transport.py @@ -16,7 +16,6 @@ # along with Paramiko; if not, write to the Free Software Foundation, Inc., # 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. -# flake8: noqa """ Core protocol implementation """ @@ -57,7 +56,7 @@ from paramiko.dsskey import DSSKey from paramiko.kex_gex import KexGex, KexGexSHA256 from paramiko.kex_group1 import KexGroup1 from paramiko.kex_group14 import KexGroup14 -from paramiko.kex_gss import KexGSSGex, KexGSSGroup1, KexGSSGroup14, NullHostKey +from paramiko.kex_gss import KexGSSGex, KexGSSGroup1, KexGSSGroup14 from paramiko.message import Message from paramiko.packet import Packetizer, NeedRekeyException from paramiko.primes import ModulusPack @@ -66,8 +65,9 @@ from paramiko.rsakey import RSAKey from paramiko.ecdsakey import ECDSAKey from paramiko.server import ServerInterface from paramiko.sftp_client import SFTPClient -from paramiko.ssh_exception import (SSHException, BadAuthenticationType, - ChannelException, ProxyCommandFailure) +from paramiko.ssh_exception import ( + SSHException, BadAuthenticationType, ChannelException, ProxyCommandFailure, +) from paramiko.util import retry_on_signal, ClosingContextManager, clamp_value @@ -125,7 +125,7 @@ class Transport (threading.Thread, ClosingContextManager): 'ssh-rsa', 'ssh-dss', ) + tuple(ECDSAKey.supported_key_format_identifiers()) - _preferred_kex = ( + _preferred_kex = ( 'diffie-hellman-group1-sha1', 'diffie-hellman-group14-sha1', 'diffie-hellman-group-exchange-sha1', @@ -242,8 +242,8 @@ class Transport (threading.Thread, ClosingContextManager): gss_deleg_creds=True): """ Create a new SSH session over an existing socket, or socket-like - object. This only creates the `.Transport` object; it doesn't begin the - SSH session yet. Use `connect` or `start_client` to begin a client + object. This only creates the `.Transport` object; it doesn't begin + the SSH session yet. Use `connect` or `start_client` to begin a client session, or `start_server` to begin a server session. If the object is not actually a socket, it must have the following @@ -298,10 +298,13 @@ class Transport (threading.Thread, ClosingContextManager): # connect to the given (host, port) hostname, port = sock reason = 'No suitable address family' - for (family, socktype, proto, canonname, sockaddr) in socket.getaddrinfo(hostname, port, socket.AF_UNSPEC, socket.SOCK_STREAM): + addrinfos = socket.getaddrinfo( + hostname, port, socket.AF_UNSPEC, socket.SOCK_STREAM + ) + for family, socktype, proto, canonname, sockaddr in addrinfos: if socktype == socket.SOCK_STREAM: af = family - addr = sockaddr + # addr = sockaddr sock = socket.socket(af, socket.SOCK_STREAM) try: retry_on_signal(lambda: sock.connect((hostname, port))) @@ -361,7 +364,8 @@ class Transport (threading.Thread, ClosingContextManager): self.in_kex = False self.authenticated = False self._expected_packet = tuple() - self.lock = threading.Lock() # synchronization (always higher level than write_lock) + # synchronization (always higher level than write_lock) + self.lock = threading.Lock() # tracking open channels self._channels = ChannelMap() @@ -382,11 +386,15 @@ class Transport (threading.Thread, ClosingContextManager): self.logger = util.get_logger(self.log_name) self.packetizer.set_log(self.logger) self.auth_handler = None - self.global_response = None # response Message from an arbitrary global request - self.completion_event = None # user-defined event callbacks - self.banner_timeout = 15 # how long (seconds) to wait for the SSH banner - self.handshake_timeout = 15 # how long (seconds) to wait for the handshake to finish after SSH banner sent. - + # response Message from an arbitrary global request + self.global_response = None + # user-defined event callbacks + self.completion_event = None + # how long (seconds) to wait for the SSH banner + self.banner_timeout = 15 + # how long (seconds) to wait for the handshake to finish after SSH + # banner sent. + self.handshake_timeout = 15 # server mode: self.server_mode = False @@ -405,8 +413,10 @@ class Transport (threading.Thread, ClosingContextManager): out += ' (unconnected)' else: if self.local_cipher != '': - out += ' (cipher %s, %d bits)' % (self.local_cipher, - self._cipher_info[self.local_cipher]['key-size'] * 8) + out += ' (cipher %s, %d bits)' % ( + self.local_cipher, + self._cipher_info[self.local_cipher]['key-size'] * 8 + ) if self.is_authenticated(): out += ' (active; %d open channel(s))' % len(self._channels) elif self.initial_kex_done: @@ -683,7 +693,12 @@ class Transport (threading.Thread, ClosingContextManager): """ return self.active - def open_session(self, window_size=None, max_packet_size=None, timeout=None): + def open_session( + self, + window_size=None, + max_packet_size=None, + timeout=None, + ): """ Request a new channel to the server, of type ``"session"``. This is just an alias for calling `open_channel` with an argument of @@ -744,7 +759,8 @@ class Transport (threading.Thread, ClosingContextManager): def open_forwarded_tcpip_channel(self, src_addr, dest_addr): """ - Request a new channel back to the client, of type ``"forwarded-tcpip"``. + Request a new channel back to the client, of type ``forwarded-tcpip``. + This is used after a client has requested port forwarding, for sending incoming connections back to the client. @@ -853,7 +869,11 @@ class Transport (threading.Thread, ClosingContextManager): If a handler is given, that handler is called from a different thread whenever a forwarded connection arrives. The handler parameters are:: - handler(channel, (origin_addr, origin_port), (server_addr, server_port)) + handler( + channel, + (origin_addr, origin_port), + (server_addr, server_port), + ) where ``server_addr`` and ``server_port`` are the address and port that the server was listening on. @@ -876,15 +896,17 @@ class Transport (threading.Thread, ClosingContextManager): if not self.active: raise SSHException('SSH session not active') port = int(port) - response = self.global_request('tcpip-forward', (address, port), wait=True) + response = self.global_request( + 'tcpip-forward', (address, port), wait=True + ) if response is None: raise SSHException('TCP forwarding request denied') if port == 0: port = response.get_int() if handler is None: def default_handler(channel, src_addr, dest_addr_port): - #src_addr, src_port = src_addr_port - #dest_addr, dest_port = dest_addr_port + # src_addr, src_port = src_addr_port + # dest_addr, dest_port = dest_addr_port self._queue_incoming_channel(channel) handler = default_handler self._tcp_handler = handler @@ -970,8 +992,9 @@ class Transport (threading.Thread, ClosingContextManager): seconds to wait before sending a keepalive packet (or 0 to disable keepalives). """ - self.packetizer.set_keepalive(interval, - lambda x=weakref.proxy(self): x.global_request('keepalive@lag.net', wait=False)) + def _request(x=weakref.proxy(self)): + return x.global_request('keepalive@lag.net', wait=False) + self.packetizer.set_keepalive(interval, _request) def global_request(self, kind, data=None, wait=True): """ @@ -1013,8 +1036,8 @@ class Transport (threading.Thread, ClosingContextManager): def accept(self, timeout=None): """ Return the next channel opened by the client over this transport, in - server mode. If no channel is opened before the given timeout, ``None`` - is returned. + server mode. If no channel is opened before the given timeout, + ``None`` is returned. :param int timeout: seconds to wait for a channel, or ``None`` to wait forever @@ -1035,8 +1058,17 @@ class Transport (threading.Thread, ClosingContextManager): self.lock.release() return chan - def connect(self, hostkey=None, username='', password=None, pkey=None, - gss_host=None, gss_auth=False, gss_kex=False, gss_deleg_creds=True): + def connect( + self, + hostkey=None, + username='', + password=None, + pkey=None, + gss_host=None, + gss_auth=False, + gss_kex=False, + gss_deleg_creds=True, + ): """ Negotiate an SSH2 session, and optionally verify the server's host key and authenticate using a password or private key. This is a shortcut @@ -1088,16 +1120,23 @@ class Transport (threading.Thread, ClosingContextManager): # the host key. if (hostkey is not None) and not gss_kex: key = self.get_remote_server_key() - if (key.get_name() != hostkey.get_name()) or (key.asbytes() != hostkey.asbytes()): + if ( + key.get_name() != hostkey.get_name() or + key.asbytes() != hostkey.asbytes() + ): self._log(DEBUG, 'Bad host key from server') - self._log(DEBUG, 'Expected: %s: %s' % (hostkey.get_name(), repr(hostkey.asbytes()))) - self._log(DEBUG, 'Got : %s: %s' % (key.get_name(), repr(key.asbytes()))) + self._log(DEBUG, 'Expected: %s: %s' % ( + hostkey.get_name(), repr(hostkey.asbytes())) + ) + self._log(DEBUG, 'Got : %s: %s' % ( + key.get_name(), repr(key.asbytes())) + ) raise SSHException('Bad host key from server') self._log(DEBUG, 'Host key verified (%s)' % hostkey.get_name()) if (pkey is not None) or (password is not None) or gss_auth or gss_kex: if gss_auth: - self._log(DEBUG, 'Attempting GSS-API auth... (gssapi-with-mic)') + self._log(DEBUG, 'Attempting GSS-API auth... (gssapi-with-mic)') # noqa self.auth_gssapi_with_mic(username, gss_host, gss_deleg_creds) elif gss_kex: self._log(DEBUG, 'Attempting GSS-API auth... (gssapi-keyex)') @@ -1160,7 +1199,11 @@ class Transport (threading.Thread, ClosingContextManager): successfully; False if authentication failed and/or the session is closed. """ - return self.active and (self.auth_handler is not None) and self.auth_handler.is_authenticated() + return ( + self.active and + self.auth_handler is not None and + self.auth_handler.is_authenticated() + ) def get_username(self): """ @@ -1259,7 +1302,8 @@ class Transport (threading.Thread, ClosingContextManager): :raises SSHException: if there was a network error """ if (not self.active) or (not self.initial_kex_done): - # we should never try to send the password unless we're on a secure link + # we should never try to send the password unless we're on a secure + # link raise SSHException('No existing session') if event is None: my_event = threading.Event() @@ -1273,7 +1317,8 @@ class Transport (threading.Thread, ClosingContextManager): try: return self.auth_handler.wait_for_response(my_event) except BadAuthenticationType as e: - # if password auth isn't allowed, but keyboard-interactive *is*, try to fudge it + # if password auth isn't allowed, but keyboard-interactive *is*, + # try to fudge it if not fallback or ('keyboard-interactive' not in e.allowed_types): raise try: @@ -1387,7 +1432,9 @@ class Transport (threading.Thread, ClosingContextManager): raise SSHException('No existing session') my_event = threading.Event() self.auth_handler = AuthHandler(self) - self.auth_handler.auth_interactive(username, handler, my_event, submethods) + self.auth_handler.auth_interactive( + username, handler, my_event, submethods + ) return self.auth_handler.wait_for_response(my_event) def auth_interactive_dumb(self, username, handler=None, submethods=''): @@ -1405,8 +1452,8 @@ class Transport (threading.Thread, ClosingContextManager): print(title.strip()) if instructions: print(instructions.strip()) - for prompt,show_input in prompt_list: - print(prompt.strip(),end=' ') + for prompt, show_input in prompt_list: + print(prompt.strip(), end=' ') answers.append(input()) return answers return self.auth_interactive(username, handler, submethods) @@ -1432,7 +1479,9 @@ class Transport (threading.Thread, ClosingContextManager): raise SSHException('No existing session') my_event = threading.Event() self.auth_handler = AuthHandler(self) - self.auth_handler.auth_gssapi_with_mic(username, gss_host, gss_deleg_creds, my_event) + self.auth_handler.auth_gssapi_with_mic( + username, gss_host, gss_deleg_creds, my_event + ) return self.auth_handler.wait_for_response(my_event) def auth_gssapi_keyex(self, username): @@ -1526,9 +1575,10 @@ class Transport (threading.Thread, ClosingContextManager): def getpeername(self): """ Return the address of the remote side of this Transport, if possible. - This is effectively a wrapper around ``'getpeername'`` on the underlying - socket. If the socket-like object has no ``'getpeername'`` method, - then ``("unknown", 0)`` is returned. + + This is effectively a wrapper around ``getpeername`` on the underlying + socket. If the socket-like object has no ``getpeername`` method, then + ``("unknown", 0)`` is returned. :return: the address of the remote host, if known, as a ``(str, int)`` @@ -1555,12 +1605,14 @@ class Transport (threading.Thread, ClosingContextManager): # our socket and packetizer are both closed (but where we'd # otherwise be sitting forever on that recv()). while ( - self.is_alive() and self is not threading.current_thread() - and not self.sock._closed and not self.packetizer.closed + self.is_alive() and + self is not threading.current_thread() and + not self.sock._closed and + not self.packetizer.closed ): self.join(0.1) - ### internals... + # internals... def _log(self, level, msg, *args): if issubclass(type(msg), list): @@ -1598,28 +1650,32 @@ class Transport (threading.Thread, ClosingContextManager): while True: self.clear_to_send.wait(0.1) if not self.active: - self._log(DEBUG, 'Dropping user packet because connection is dead.') + self._log(DEBUG, 'Dropping user packet because connection is dead.') # noqa return self.clear_to_send_lock.acquire() if self.clear_to_send.is_set(): break self.clear_to_send_lock.release() if time.time() > start + self.clear_to_send_timeout: - raise SSHException('Key-exchange timed out waiting for key negotiation') + raise SSHException('Key-exchange timed out waiting for key negotiation') # noqa try: self._send_message(data) finally: self.clear_to_send_lock.release() def _set_K_H(self, k, h): - """used by a kex object to set the K (root key) and H (exchange hash)""" + """ + Used by a kex obj to set the K (root key) and H (exchange hash). + """ self.K = k self.H = h if self.session_id is None: self.session_id = h def _expect_packet(self, *ptypes): - """used by a kex object to register the next packet type it expects to see""" + """ + Used by a kex obj to register the next packet type it expects to see. + """ self._expected_packet = tuple(ptypes) def _verify_key(self, host_key, sig): @@ -1627,7 +1683,7 @@ class Transport (threading.Thread, ClosingContextManager): if key is None: raise SSHException('Unknown host key type') if not key.verify_ssh_sig(self.H, Message(sig)): - raise SSHException('Signature verification (%s) failed.' % self.host_key_type) + raise SSHException('Signature verification (%s) failed.' % self.host_key_type) # noqa self.host_key = key def _compute_key(self, id, nbytes): @@ -1640,7 +1696,9 @@ class Transport (threading.Thread, ClosingContextManager): # Fallback to SHA1 for kex engines that fail to specify a hex # algorithm, or for e.g. transport tests that don't run kexinit. hash_algo = getattr(self.kex_engine, 'hash_algo', None) - hash_select_msg = "kex engine %s specified hash_algo %r" % (self.kex_engine.__class__.__name__, hash_algo) + hash_select_msg = "kex engine %s specified hash_algo %r" % ( + self.kex_engine.__class__.__name__, hash_algo + ) if hash_algo is None: hash_algo = sha1 hash_select_msg += ", falling back to sha1" @@ -1736,14 +1794,15 @@ class Transport (threading.Thread, ClosingContextManager): # active=True occurs before the thread is launched, to avoid a race _active_threads.append(self) + tid = hex(long(id(self)) & xffffffff) if self.server_mode: - self._log(DEBUG, 'starting thread (server mode): %s' % hex(long(id(self)) & xffffffff)) + self._log(DEBUG, 'starting thread (server mode): %s' % tid) else: - self._log(DEBUG, 'starting thread (client mode): %s' % hex(long(id(self)) & xffffffff)) + self._log(DEBUG, 'starting thread (client mode): %s' % tid) try: try: self.packetizer.write_all(b(self.local_version + '\r\n')) - self._log(DEBUG, 'Local version/idstring: %s' % self.local_version) + self._log(DEBUG, 'Local version/idstring: %s' % self.local_version) # noqa self._check_banner() # The above is actually very much part of the handshake, but # sometimes the banner can be read but the machine is not @@ -1775,7 +1834,7 @@ class Transport (threading.Thread, ClosingContextManager): continue if len(self._expected_packet) > 0: if ptype not in self._expected_packet: - raise SSHException('Expecting packet from %r, got %d' % (self._expected_packet, ptype)) + raise SSHException('Expecting packet from %r, got %d' % (self._expected_packet, ptype)) # noqa self._expected_packet = tuple() if (ptype >= 30) and (ptype <= 41): self.kex_engine.parse_next(ptype, m) @@ -1789,13 +1848,17 @@ class Transport (threading.Thread, ClosingContextManager): if chan is not None: self._channel_handler_table[ptype](chan, m) elif chanid in self.channels_seen: - self._log(DEBUG, 'Ignoring message for dead channel %d' % chanid) + self._log(DEBUG, 'Ignoring message for dead channel %d' % chanid) # noqa else: - self._log(ERROR, 'Channel request for unknown channel %d' % chanid) + self._log(ERROR, 'Channel request for unknown channel %d' % chanid) # noqa self.active = False self.packetizer.close() - elif (self.auth_handler is not None) and (ptype in self.auth_handler._handler_table): - self.auth_handler._handler_table[ptype](self.auth_handler, m) + elif ( + self.auth_handler is not None and + ptype in self.auth_handler._handler_table + ): + handler = self.auth_handler._handler_table[ptype] + handler(self.auth_handler, m) else: self._log(WARNING, 'Oops, unhandled type %d' % ptype) msg = Message() @@ -1862,7 +1925,7 @@ class Transport (threading.Thread, ClosingContextManager): msg += "local={0}, remote={1}".format(local, remote) self._log(DEBUG, msg) - ### protocol stages + # protocol stages def _negotiate_keys(self, m): # throws SSHException on anything unusual @@ -1891,7 +1954,9 @@ class Transport (threading.Thread, ClosingContextManager): except ProxyCommandFailure: raise except Exception as e: - raise SSHException('Error reading SSH protocol banner' + str(e)) + raise SSHException( + 'Error reading SSH protocol banner' + str(e) + ) if buf[:4] == 'SSH-': break self._log(DEBUG, 'Banner: ' + buf) @@ -1913,8 +1978,10 @@ class Transport (threading.Thread, ClosingContextManager): version = segs[1] client = segs[2] if version != '1.99' and version != '2.0': - raise SSHException('Incompatible version (%s instead of 2.0)' % (version,)) - self._log(INFO, 'Connected (version %s, client %s)' % (version, client)) + msg = 'Incompatible version ({0} instead of 2.0)' + raise SSHException(msg.format(version)) + msg = 'Connected (version {0}, client {1})'.format(version, client) + self._log(INFO, msg) def _send_kex_init(self): """ @@ -1929,14 +1996,24 @@ class Transport (threading.Thread, ClosingContextManager): self.in_kex = True if self.server_mode: mp_required_prefix = 'diffie-hellman-group-exchange-sha' - kex_mp = [k for k in self._preferred_kex if k.startswith(mp_required_prefix)] + kex_mp = [ + k for k + in self._preferred_kex + if k.startswith(mp_required_prefix) + ] if (self._modulus_pack is None) and (len(kex_mp) > 0): - # can't do group-exchange if we don't have a pack of potential primes - pkex = [k for k in self.get_security_options().kex - if not k.startswith(mp_required_prefix)] + # can't do group-exchange if we don't have a pack of potential + # primes + pkex = [ + k for k + in self.get_security_options().kex + if not k.startswith(mp_required_prefix) + ] self.get_security_options().kex = pkex - available_server_keys = list(filter(list(self.server_key_dict.keys()).__contains__, - self._preferred_keys)) + available_server_keys = list(filter( + list(self.server_key_dict.keys()).__contains__, + self._preferred_keys + )) else: available_server_keys = self._preferred_keys @@ -1960,7 +2037,7 @@ class Transport (threading.Thread, ClosingContextManager): self._send_message(m) def _parse_kex_init(self, m): - cookie = m.get_bytes(16) + m.get_bytes(16) # cookie, discarded kex_algo_list = m.get_list() server_key_algo_list = m.get_list() client_encrypt_algo_list = m.get_list() @@ -1972,18 +2049,21 @@ class Transport (threading.Thread, ClosingContextManager): client_lang_list = m.get_list() server_lang_list = m.get_list() kex_follows = m.get_boolean() - unused = m.get_int() - - self._log(DEBUG, 'kex algos:' + str(kex_algo_list) + ' server key:' + str(server_key_algo_list) + - ' client encrypt:' + str(client_encrypt_algo_list) + - ' server encrypt:' + str(server_encrypt_algo_list) + - ' client mac:' + str(client_mac_algo_list) + - ' server mac:' + str(server_mac_algo_list) + - ' client compress:' + str(client_compress_algo_list) + - ' server compress:' + str(server_compress_algo_list) + - ' client lang:' + str(client_lang_list) + - ' server lang:' + str(server_lang_list) + - ' kex follows?' + str(kex_follows)) + m.get_int() # unused + + self._log(DEBUG, + 'kex algos:' + str(kex_algo_list) + + ' server key:' + str(server_key_algo_list) + + ' client encrypt:' + str(client_encrypt_algo_list) + + ' server encrypt:' + str(server_encrypt_algo_list) + + ' client mac:' + str(client_mac_algo_list) + + ' server mac:' + str(server_mac_algo_list) + + ' client compress:' + str(client_compress_algo_list) + + ' server compress:' + str(server_compress_algo_list) + + ' client lang:' + str(client_lang_list) + + ' server lang:' + str(server_lang_list) + + ' kex follows?' + str(kex_follows) + ) # as a server, we pick the first item in the client's list that we # support. @@ -2000,34 +2080,48 @@ class Transport (threading.Thread, ClosingContextManager): self._preferred_kex )) if len(agreed_kex) == 0: - raise SSHException('Incompatible ssh peer (no acceptable kex algorithm)') + raise SSHException('Incompatible ssh peer (no acceptable kex algorithm)') # noqa self.kex_engine = self._kex_info[agreed_kex[0]](self) self._log(DEBUG, "Kex agreed: %s" % agreed_kex[0]) if self.server_mode: - available_server_keys = list(filter(list(self.server_key_dict.keys()).__contains__, - self._preferred_keys)) - agreed_keys = list(filter(available_server_keys.__contains__, server_key_algo_list)) + available_server_keys = list(filter( + list(self.server_key_dict.keys()).__contains__, + self._preferred_keys + )) + agreed_keys = list(filter( + available_server_keys.__contains__, server_key_algo_list + )) else: - agreed_keys = list(filter(server_key_algo_list.__contains__, self._preferred_keys)) + agreed_keys = list(filter( + server_key_algo_list.__contains__, self._preferred_keys + )) if len(agreed_keys) == 0: - raise SSHException('Incompatible ssh peer (no acceptable host key)') + raise SSHException('Incompatible ssh peer (no acceptable host key)') # noqa self.host_key_type = agreed_keys[0] if self.server_mode and (self.get_server_key() is None): - raise SSHException('Incompatible ssh peer (can\'t match requested host key type)') + raise SSHException('Incompatible ssh peer (can\'t match requested host key type)') # noqa if self.server_mode: - agreed_local_ciphers = list(filter(self._preferred_ciphers.__contains__, - server_encrypt_algo_list)) - agreed_remote_ciphers = list(filter(self._preferred_ciphers.__contains__, - client_encrypt_algo_list)) + agreed_local_ciphers = list(filter( + self._preferred_ciphers.__contains__, + server_encrypt_algo_list + )) + agreed_remote_ciphers = list(filter( + self._preferred_ciphers.__contains__, + client_encrypt_algo_list + )) else: - agreed_local_ciphers = list(filter(client_encrypt_algo_list.__contains__, - self._preferred_ciphers)) - agreed_remote_ciphers = list(filter(server_encrypt_algo_list.__contains__, - self._preferred_ciphers)) - if (len(agreed_local_ciphers) == 0) or (len(agreed_remote_ciphers) == 0): - raise SSHException('Incompatible ssh server (no acceptable ciphers)') + agreed_local_ciphers = list(filter( + client_encrypt_algo_list.__contains__, + self._preferred_ciphers + )) + agreed_remote_ciphers = list(filter( + server_encrypt_algo_list.__contains__, + self._preferred_ciphers + )) + if len(agreed_local_ciphers) == 0 or len(agreed_remote_ciphers) == 0: + raise SSHException('Incompatible ssh server (no acceptable ciphers)') # noqa self.local_cipher = agreed_local_ciphers[0] self.remote_cipher = agreed_remote_ciphers[0] self._log_agreement( @@ -2035,11 +2129,19 @@ class Transport (threading.Thread, ClosingContextManager): ) if self.server_mode: - agreed_remote_macs = list(filter(self._preferred_macs.__contains__, client_mac_algo_list)) - agreed_local_macs = list(filter(self._preferred_macs.__contains__, server_mac_algo_list)) + agreed_remote_macs = list(filter( + self._preferred_macs.__contains__, client_mac_algo_list + )) + agreed_local_macs = list(filter( + self._preferred_macs.__contains__, server_mac_algo_list + )) else: - agreed_local_macs = list(filter(client_mac_algo_list.__contains__, self._preferred_macs)) - agreed_remote_macs = list(filter(server_mac_algo_list.__contains__, self._preferred_macs)) + agreed_local_macs = list(filter( + client_mac_algo_list.__contains__, self._preferred_macs + )) + agreed_remote_macs = list(filter( + server_mac_algo_list.__contains__, self._preferred_macs + )) if (len(agreed_local_macs) == 0) or (len(agreed_remote_macs) == 0): raise SSHException('Incompatible ssh server (no acceptable macs)') self.local_mac = agreed_local_macs[0] @@ -2049,13 +2151,32 @@ class Transport (threading.Thread, ClosingContextManager): ) if self.server_mode: - agreed_remote_compression = list(filter(self._preferred_compression.__contains__, client_compress_algo_list)) - agreed_local_compression = list(filter(self._preferred_compression.__contains__, server_compress_algo_list)) + agreed_remote_compression = list(filter( + self._preferred_compression.__contains__, + client_compress_algo_list + )) + agreed_local_compression = list(filter( + self._preferred_compression.__contains__, + server_compress_algo_list + )) else: - agreed_local_compression = list(filter(client_compress_algo_list.__contains__, self._preferred_compression)) - agreed_remote_compression = list(filter(server_compress_algo_list.__contains__, self._preferred_compression)) - if (len(agreed_local_compression) == 0) or (len(agreed_remote_compression) == 0): - raise SSHException('Incompatible ssh server (no acceptable compression) %r %r %r' % (agreed_local_compression, agreed_remote_compression, self._preferred_compression)) + agreed_local_compression = list(filter( + client_compress_algo_list.__contains__, + self._preferred_compression + )) + agreed_remote_compression = list(filter( + server_compress_algo_list.__contains__, + self._preferred_compression + )) + if ( + len(agreed_local_compression) == 0 or + len(agreed_remote_compression) == 0 + ): + msg = 'Incompatible ssh server (no acceptable compression) {0!r} {1!r} {2!r}' # noqa + raise SSHException(msg.format( + agreed_local_compression, agreed_remote_compression, + self._preferred_compression, + )) self.local_compression = agreed_local_compression[0] self.remote_compression = agreed_remote_compression[0] self._log_agreement( @@ -2077,11 +2198,17 @@ class Transport (threading.Thread, ClosingContextManager): block_size = self._cipher_info[self.remote_cipher]['block-size'] if self.server_mode: IV_in = self._compute_key('A', block_size) - key_in = self._compute_key('C', self._cipher_info[self.remote_cipher]['key-size']) + key_in = self._compute_key( + 'C', self._cipher_info[self.remote_cipher]['key-size'] + ) else: IV_in = self._compute_key('B', block_size) - key_in = self._compute_key('D', self._cipher_info[self.remote_cipher]['key-size']) - engine = self._get_cipher(self.remote_cipher, key_in, IV_in, self._DECRYPT) + key_in = self._compute_key( + 'D', self._cipher_info[self.remote_cipher]['key-size'] + ) + engine = self._get_cipher( + self.remote_cipher, key_in, IV_in, self._DECRYPT + ) mac_size = self._mac_info[self.remote_mac]['size'] mac_engine = self._mac_info[self.remote_mac]['class'] # initial mac keys are done in the hash's natural size (not the @@ -2090,9 +2217,17 @@ class Transport (threading.Thread, ClosingContextManager): mac_key = self._compute_key('E', mac_engine().digest_size) else: mac_key = self._compute_key('F', mac_engine().digest_size) - self.packetizer.set_inbound_cipher(engine, block_size, mac_engine, mac_size, mac_key) + self.packetizer.set_inbound_cipher( + engine, block_size, mac_engine, mac_size, mac_key + ) compress_in = self._compression_info[self.remote_compression][1] - if (compress_in is not None) and ((self.remote_compression != 'zlib@openssh.com') or self.authenticated): + if ( + compress_in is not None and + ( + self.remote_compression != 'zlib@openssh.com' or + self.authenticated + ) + ): self._log(DEBUG, 'Switching on inbound compression ...') self.packetizer.set_inbound_compressor(compress_in()) |