예제 #1
0
    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()
예제 #2
0
    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()
예제 #3
0
    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)
예제 #4
0
    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)