def set_key_exchange(self, key_exchange=None, server_host_key_type=None): """set_key_exchange(self, key_exchange=None, server_host_key_type=None) -> None Sets the key exchange algorithm to use. <key_exchange> - A string. The key exchange algorithm to use. Must be one of those in supported_key_exchanges. Set to None to default to the preferred algorithm. <server_host_key_type> - A string. The server host key type to use. Must be one of thos in supported_server_keys. Set to None to default to the preferred algorithm. The key_exchange algorithm MUST support this type of key. """ kex = pick_from_list(key_exchange, self.self2remote.supported_key_exchanges) if kex is None: raise ValueError, 'Unknown key exchange algorithm: %s' % key_exchange key = pick_from_list(server_host_key_type, self.self2remote.supported_server_keys) if key is None: raise ValueError, 'Unknown server key type: %s' % server_host_key_type self.key_exchange = kex self.server_key = key if self.is_server: self.key_exchange.register_server_callbacks() else: self.key_exchange.register_client_callbacks()
def set_key_exchange(self, key_exchange=None, server_host_key_type=None): """set_key_exchange(self, key_exchange=None, server_host_key_type=None) -> None Sets the key exchange algorithm to use. <key_exchange> - A string. The key exchange algorithm to use. Must be one of those in supported_key_exchanges. Set to None to default to the preferred algorithm. <server_host_key_type> - A string. The server host key type to use. Must be one of thos in supported_server_keys. Set to None to default to the preferred algorithm. The key_exchange algorithm MUST support this type of key. """ kex = pick_from_list(key_exchange, self.self2remote.supported_key_exchanges) if kex is None: raise ValueError('Unknown key exchange algorithm: %s' % key_exchange) key = pick_from_list(server_host_key_type, self.self2remote.supported_server_keys) if key is None: raise ValueError('Unknown server key type: %s' % server_host_key_type) self.key_exchange = kex self.server_key = key if self.is_server: self.key_exchange.register_server_callbacks() else: self.key_exchange.register_client_callbacks()
def _matchup_kex_and_key(self): """_matchup_kex_and_key(self) -> None This sets self.key_exchange and self.server_key to the appropriate value. It checks that both us and the remote end support the same key exchange and we both support a key type that has the appropriate features required by the key exchange algorithm. """ self.remote2self.set_preferred('key_exchange') self.remote2self.set_preferred('server_key') self.self2remote.set_preferred('key_exchange') self.self2remote.set_preferred('server_key') if self.remote2self.key_exchange is None or self.self2remote.key_exchange is None: self.send_disconnect(SSH_DISCONNECT_KEY_EXCHANGE_FAILED, 'Could not find matching key exchange algorithm.') if self.remote2self.server_key is None or self.self2remote.server_key is None: self.send_disconnect(SSH_DISCONNECT_KEY_EXCHANGE_FAILED, 'Could not find matching server key type.') if self.remote2self.key_exchange.name != self.self2remote.key_exchange.name: # iterate over client's kex algorithms, # one at a time. Choose the first algorithm that satisfies # the following conditions: # + the server also supports the algorithm, # + if the algorithm requires an encryption-capable host key, # there is an encryption-capable algorithm on the server's # server_host_key_algorithms that is also supported by the # client, and # + if the algorithm requires a signature-capable host key, # there is a signature-capable algorithm on the server's # server_host_key_algorithms that is also supported by the # client. # + If no algorithm satisfying all these conditions can be # found, the connection fails, and both sides MUST # disconnect. for client_kex_algorithm in self.c2s.supported_key_exchanges: server_kex_algorithm = pick_from_list(client_kex_algorithm.name, self.s2c.supported_key_exchanges) if server_kex_algorithm is not None: # We both support this kex algorithm. # See if we both have key types that match the requirements of this kex algorithm. for server_host_key_type in self.s2c.supported_server_keys: if (server_kex_algorithm.wants_encryption_host_key and not server_host_key_type.supports_encryption) or \ (server_kex_algorithm.wants_signature_host_key and not server_host_key_type.supports_signature): # This host key is not appropriate. continue else: # This key meets our requirements. break else: # None of the host key types worked, try next kex algorithm. continue # If we got here, then this is the kex to use. self.set_key_exchange(client_kex_algorithm.name, server_host_key_type.name) break else: # None of the kex algorithms worked. self.send_disconnect(SSH_DISCONNECT_KEY_EXCHANGE_FAILED, 'Could not find matching key exchange algorithm.') else: # We have agreement on the kex algorithm to use. # See if we have agreement on the server host key type. self.debug.write (ssh_debug.DEBUG_3, 'msg_kexinit: agreement on %r' % (self.self2remote.key_exchange.name,)) if self.remote2self.server_key.name != self.self2remote.server_key.name: # See if we share a server host key type that also works with our chosen kex algorithm. for client_server_key_type in self.c2s.supported_server_keys: server_server_key_type = pick_from_list(client_server_key_type.name, self.s2c.supported_server_keys) if server_server_key_type is not None: # We both support this server key algorithm. # See if it matches our kex algorithm requirements. if (self.remote2self.key_exchange.wants_encryption_host_key and not server_server_key_type.supports_encryption) or \ (self.remote2self.key_exchange.wants_signature_host_key and not server_server_key_type.supports_signature): # This server key type is not appropriate. continue else: # This meets our requirements. break else: # None of the server key types worked. self.send_disconnect(SSH_DISCONNECT_KEY_EXCHANGE_FAILED, 'Could not find matching server key type for %s key exchange.' % self.remote2self.key_exchange.name) self.debug.write (ssh_debug.DEBUG_3, 'msg_kexinit: set_key_exchange: %r' % (self.remote2self.server_key.name,)) self.set_key_exchange(self.remote2self.key_exchange.name, self.remote2self.server_key.name)
def _matchup_kex_and_key(self): """_matchup_kex_and_key(self) -> None This sets self.key_exchange and self.server_key to the appropriate value. It checks that both us and the remote end support the same key exchange and we both support a key type that has the appropriate features required by the key exchange algorithm. """ self.remote2self.set_preferred('key_exchange') self.remote2self.set_preferred('server_key') self.self2remote.set_preferred('key_exchange') self.self2remote.set_preferred('server_key') if self.remote2self.key_exchange is None or self.self2remote.key_exchange is None: self.send_disconnect( SSH_DISCONNECT_KEY_EXCHANGE_FAILED, 'Could not find matching key exchange algorithm.') if self.remote2self.server_key is None or self.self2remote.server_key is None: self.send_disconnect(SSH_DISCONNECT_KEY_EXCHANGE_FAILED, 'Could not find matching server key type.') if self.remote2self.key_exchange.name != self.self2remote.key_exchange.name: # iterate over client's kex algorithms, # one at a time. Choose the first algorithm that satisfies # the following conditions: # + the server also supports the algorithm, # + if the algorithm requires an encryption-capable host key, # there is an encryption-capable algorithm on the server's # server_host_key_algorithms that is also supported by the # client, and # + if the algorithm requires a signature-capable host key, # there is a signature-capable algorithm on the server's # server_host_key_algorithms that is also supported by the # client. # + If no algorithm satisfying all these conditions can be # found, the connection fails, and both sides MUST # disconnect. for client_kex_algorithm in self.c2s.supported_key_exchanges: server_kex_algorithm = pick_from_list( client_kex_algorithm.name, self.s2c.supported_key_exchanges) if server_kex_algorithm is not None: # We both support this kex algorithm. # See if we both have key types that match the requirements of this kex algorithm. for server_host_key_type in self.s2c.supported_server_keys: if (server_kex_algorithm.wants_encryption_host_key and not server_host_key_type.supports_encryption) or \ (server_kex_algorithm.wants_signature_host_key and not server_host_key_type.supports_signature): # noqa # This host key is not appropriate. continue else: # This key meets our requirements. break else: # None of the host key types worked, try next kex algorithm. continue # If we got here, then this is the kex to use. self.set_key_exchange(client_kex_algorithm.name, server_host_key_type.name) break else: # None of the kex algorithms worked. self.send_disconnect( SSH_DISCONNECT_KEY_EXCHANGE_FAILED, 'Could not find matching key exchange algorithm.') else: # We have agreement on the kex algorithm to use. # See if we have agreement on the server host key type. self.debug.write( ssh_debug.DEBUG_3, 'msg_kexinit: agreement on %r' % (self.self2remote.key_exchange.name, )) if self.remote2self.server_key.name != self.self2remote.server_key.name: # See if we share a server host key type that also works with our chosen kex algorithm. for client_server_key_type in self.c2s.supported_server_keys: server_server_key_type = pick_from_list( client_server_key_type.name, self.s2c.supported_server_keys) if server_server_key_type is not None: # We both support this server key algorithm. # See if it matches our kex algorithm requirements. if (self.remote2self.key_exchange.wants_encryption_host_key and not server_server_key_type.supports_encryption) or \ (self.remote2self.key_exchange.wants_signature_host_key and not server_server_key_type.supports_signature): # noqa # This server key type is not appropriate. continue else: # This meets our requirements. break else: # None of the server key types worked. self.send_disconnect( SSH_DISCONNECT_KEY_EXCHANGE_FAILED, 'Could not find matching server key type for %s key exchange.' % self.remote2self.key_exchange.name) self.debug.write( ssh_debug.DEBUG_3, 'msg_kexinit: set_key_exchange: %r' % (self.remote2self.server_key.name, )) self.set_key_exchange(self.remote2self.key_exchange.name, self.remote2self.server_key.name)