Beispiel #1
0
    def test_errors(self):
        """Test getting error responses from SSH agent"""

        # pylint: disable=bad-whitespace

        key = asyncssh.generate_private_key('ssh-rsa')
        keypair = asyncssh.load_keypairs(key)[0]

        for response in (b'', String(b''), String(Byte(SSH_AGENT_FAILURE)),
                         String(b'\xff')):
            mock_agent = _Agent(response)
            yield from mock_agent.start('mock_agent')

            agent = yield from asyncssh.connect_agent('mock_agent')

            for request in (agent.get_keys(), agent.sign(b'xxx', b'test'),
                            agent.add_keys([key]),
                            agent.add_smartcard_keys('xxx'),
                            agent.remove_keys([keypair]),
                            agent.remove_smartcard_keys('xxx'),
                            agent.remove_all(), agent.lock('passphrase'),
                            agent.unlock('passphrase')):
                with self.assertRaises(ValueError):
                    yield from request

                agent.close()

            yield from mock_agent.stop()
Beispiel #2
0
    def add_keys(self,
                 keylist=(),
                 passphrase=None,
                 lifetime=None,
                 confirm=False):
        """Add keys to the agent

           This method adds a list of local private keys and optional
           matching certificates to the agent.

           :param keylist: (optional)
               The list of keys to add. If not specified, an attempt will
               be made to load keys from the files :file:`.ssh/id_ed25519`,
               :file:`.ssh/id_ecdsa`, :file:`.ssh/id_rsa` and
               :file:`.ssh/id_dsa` in the user's home directory with
               optional matching certificates loaded from the files
               :file:`.ssh/id_ed25519-cert.pub`,
               :file:`.ssh/id_ecdsa-cert.pub`, :file:`.ssh/id_rsa-cert.pub`,
               and :file:`.ssh/id_dsa-cert.pub`.
           :param passphrase: (optional)
               The passphrase to use to decrypt the keys.
           :param lifetime: (optional)
               The time in seconds after which the keys should be
               automatically deleted, or `None` to store these keys
               indefinitely (the default).
           :param confirm: (optional)
               Whether or not to require confirmation for each private
               key operation which uses these keys, defaulting to `False`.
           :type keylist: *see* :ref:`SpecifyingPrivateKeys`
           :type passphrase: `str`
           :type lifetime: `int` or `None`
           :type confirm: `bool`

           :raises: :exc:`ValueError` if the keys cannot be added

        """

        if keylist:
            keypairs = asyncssh.load_keypairs(keylist, passphrase)
        else:
            keypairs = load_default_keypairs(passphrase)

        constraints = self.encode_constraints(lifetime, confirm)
        msgtype = SSH_AGENTC_ADD_ID_CONSTRAINED if constraints else \
                      SSH_AGENTC_ADD_IDENTITY

        for keypair in keypairs:
            comment = keypair.get_comment_bytes()
            resptype, resp = \
                yield from self._make_request(msgtype,
                                              keypair.get_agent_private_key(),
                                              String(comment or b''),
                                              constraints)

            if resptype == SSH_AGENT_SUCCESS:
                resp.check_end()
            elif resptype == SSH_AGENT_FAILURE:
                raise ValueError('Unable to add key')
            else:
                raise ValueError('Unknown SSH agent response: %d' % resptype)
Beispiel #3
0
    def test_errors(self):
        """Test getting error responses from SSH agent"""

        # pylint: disable=bad-whitespace

        key = asyncssh.generate_private_key('ssh-rsa')
        keypair = asyncssh.load_keypairs(key)[0]

        for response in (b'', String(b''),
                         String(Byte(SSH_AGENT_FAILURE)), String(b'\xff')):
            mock_agent = _Agent(response)
            yield from mock_agent.start('mock_agent')

            agent = yield from asyncssh.connect_agent('mock_agent')

            for request in (agent.get_keys(),
                            agent.sign(b'xxx', b'test'),
                            agent.add_keys([key]),
                            agent.add_smartcard_keys('xxx'),
                            agent.remove_keys([keypair]),
                            agent.remove_smartcard_keys('xxx'),
                            agent.remove_all(),
                            agent.lock('passphrase'),
                            agent.unlock('passphrase')):
                with self.assertRaises(ValueError):
                    yield from request

                agent.close()

            yield from mock_agent.stop()
Beispiel #4
0
    async def test_errors(self):
        """Test getting error responses from SSH agent"""

        key = asyncssh.generate_private_key('ssh-rsa')
        keypair = asyncssh.load_keypairs(key)[0]

        for response in (None, b'', Byte(SSH_AGENT_FAILURE), b'\xff'):
            mock_agent = _Agent(response)
            await mock_agent.start('mock_agent')

            async with asyncssh.connect_agent('mock_agent') as agent:
                for request in (agent.get_keys(),
                                agent.sign(b'xxx', b'test'),
                                agent.add_keys([key]),
                                agent.add_smartcard_keys('xxx'),
                                agent.remove_keys([keypair]),
                                agent.remove_smartcard_keys('xxx'),
                                agent.remove_all(),
                                agent.lock('passphrase'),
                                agent.unlock('passphrase')):
                    async with agent:
                        with self.assertRaises(ValueError):
                            await request

            await mock_agent.stop()
Beispiel #5
0
    async def public_key_auth_requested(self):
        """Return key to use for public key authentication"""

        if self._client_key:
            return asyncssh.load_keypairs(
                (self._client_key, self._client_cert))[0]
        else:
            return None
Beispiel #6
0
    def __init__(self, alg, gss_host, peer):
        gss = GSSServer(gss_host) if gss_host else None
        super().__init__(alg, gss, peer, True)

        if gss_host and 'no_host_key' in gss_host:
            self._server_host_key = None
        else:
            priv_key = asyncssh.generate_private_key('ssh-rsa')
            self._server_host_key = asyncssh.load_keypairs(priv_key)[0]
Beispiel #7
0
    def add_keys(self, keylist=(), passphrase=None,
                 lifetime=None, confirm=False):
        """Add keys to the agent

           This method adds a list of local private keys and optional
           matching certificates to the agent.

           :param keylist: (optional)
               The list of keys to add. If not specified, an attempt will
               be made to load keys from the files :file:`.ssh/id_ed25519`,
               :file:`.ssh/id_ecdsa`, :file:`.ssh/id_rsa` and
               :file:`.ssh/id_dsa` in the user's home directory with
               optional matching certificates loaded from the files
               :file:`.ssh/id_ed25519-cert.pub`,
               :file:`.ssh/id_ecdsa-cert.pub`, :file:`.ssh/id_rsa-cert.pub`,
               and :file:`.ssh/id_dsa-cert.pub`.
           :param passphrase: (optional)
               The passphrase to use to decrypt the keys.
           :param lifetime: (optional)
               The time in seconds after which the keys should be
               automatically deleted, or `None` to store these keys
               indefinitely (the default).
           :param confirm: (optional)
               Whether or not to require confirmation for each private
               key operation which uses these keys, defaulting to `False`.
           :type keylist: *see* :ref:`SpecifyingPrivateKeys`
           :type passphrase: `str`
           :type lifetime: `int` or `None`
           :type confirm: `bool`

           :raises: :exc:`ValueError` if the keys cannot be added

        """

        if keylist:
            keypairs = asyncssh.load_keypairs(keylist, passphrase)
        else:
            keypairs = load_default_keypairs(passphrase)

        constraints = self.encode_constraints(lifetime, confirm)
        msgtype = SSH_AGENTC_ADD_ID_CONSTRAINED if constraints else \
                      SSH_AGENTC_ADD_IDENTITY

        for keypair in keypairs:
            comment = keypair.get_comment_bytes()
            resptype, resp = \
                yield from self._make_request(msgtype,
                                              keypair.get_agent_private_key(),
                                              String(comment or b''),
                                              constraints)

            if resptype == SSH_AGENT_SUCCESS:
                resp.check_end()
            elif resptype == SSH_AGENT_FAILURE:
                raise ValueError('Unable to add key')
            else:
                raise ValueError('Unknown SSH agent response: %d' % resptype)
    def test_client_key_keypairs(self):
        """Test client keys passed in as a list of SSHKeyPairs"""

        keys = asyncssh.load_keypairs('ckey')

        with (yield from self.connect(username='******',
                                      client_keys=keys)) as conn:
            pass

        yield from conn.wait_closed()
Beispiel #9
0
    def test_client_key_keypairs(self):
        """Test client keys passed in as a list of SSHKeyPairs"""

        keys = asyncssh.load_keypairs('ckey')

        with (yield from self.connect(username='******',
                                      client_keys=keys)) as conn:
            pass

        yield from conn.wait_closed()
Beispiel #10
0
    async def host_based_auth_requested(self):
        """Return a host key pair, host, and user to authenticate with"""

        if self._client_host_key:
            keypair = asyncssh.load_keypairs(
                (self._client_host_key, self._client_host_cert))[0]
        else:
            keypair = None

        return keypair, 'host', 'user'
Beispiel #11
0
def load_default_keypairs(passphrase=None):
    """Return a list of default keys from the user's home directory"""

    result = []

    for file in _DEFAULT_KEY_FILES:
        try:
            file = os.path.join(os.path.expanduser('~'), '.ssh', file)
            result.extend(asyncssh.load_keypairs(file, passphrase))
        except OSError:
            pass

    return result
Beispiel #12
0
    async def test_set_certificate(self, agent):
        """Test setting certificate on an existing keypair"""

        key = asyncssh.generate_private_key('ssh-rsa')
        cert = key.generate_user_certificate(key, 'name')

        key2 = asyncssh.generate_private_key('ssh-rsa')
        cert2 = key.generate_user_certificate(key2, 'name')

        await agent.add_keys([key])
        agent_key = (await agent.get_keys())[0]

        agent_key.set_certificate(cert)
        self.assertEqual(agent_key.public_data, cert.public_data)

        with self.assertRaises(ValueError):
            asyncssh.load_keypairs([(agent_key, cert2)])

        agent_key = (await agent.get_keys())[0]
        agent_key = asyncssh.load_keypairs([(agent_key, cert)])[0]
        self.assertEqual(agent_key.public_data, cert.public_data)

        with self.assertRaises(ValueError):
            asyncssh.load_keypairs([(agent_key, cert2)])
Beispiel #13
0
def load_default_keypairs(passphrase=None):
    """Return a list of default keys from the user's home directory"""

    result = []

    for file in _DEFAULT_KEY_FILES:
        try:
            file = os.path.join(os.path.expanduser('~'), '.ssh', file)
            result.extend(asyncssh.load_keypairs(file, passphrase))
        except asyncssh.KeyImportError as exc:
            # Ignore encrypted default keys if a passphrase isn't provided
            if not str(exc).startswith('Passphrase'):
                raise
        except OSError:
            pass

    return result
Beispiel #14
0
    async def test_add_sk_keys(self):
        """Test adding U2F security keys"""

        key = asyncssh.generate_private_key(
            '*****@*****.**')
        cert = key.generate_user_certificate(key, 'test')

        mock_agent = _Agent(Byte(SSH_AGENT_SUCCESS))
        await mock_agent.start('mock_agent')

        async with asyncssh.connect_agent('mock_agent') as agent:
            for keypair in asyncssh.load_keypairs([key, (key, cert)]):
                async with agent:
                    self.assertIsNone(await agent.add_keys([keypair]))

            async with agent:
                with self.assertRaises(asyncssh.KeyExportError):
                    await agent.add_keys([key.convert_to_public()])

        await mock_agent.stop()
Beispiel #15
0
    def communicate(self, request):
        """Process SSH key signing request"""

        # pylint: disable=no-self-use

        packet = SSHPacket(request)
        request = packet.get_string()
        packet.check_end()

        packet = SSHPacket(request)
        version = packet.get_byte()
        _ = packet.get_uint32()     # sock_fd
        data = packet.get_string()
        packet.check_end()

        if version == 0:
            return b'', b''
        elif version == 1:
            return b'', b'invalid request'
        else:
            skey = asyncssh.load_keypairs('skey')[0]
            sig = skey.sign(data)
            return String(Byte(KEYSIGN_VERSION) + String(sig)), b''
Beispiel #16
0
    def communicate(self, request):
        """Process SSH key signing request"""

        # pylint: disable=no-self-use

        packet = SSHPacket(request)
        request = packet.get_string()
        packet.check_end()

        packet = SSHPacket(request)
        version = packet.get_byte()
        _ = packet.get_uint32()  # sock_fd
        data = packet.get_string()
        packet.check_end()

        if version == 0:
            return b'', b''
        elif version == 1:
            return b'', b'invalid request'
        else:
            skey = asyncssh.load_keypairs('skey')[0]
            sig = skey.sign(data)
            return String(Byte(KEYSIGN_VERSION) + String(sig)), b''