From 004799e2c5854d236bbc5cd20282f7c8b8f6a2f9 Mon Sep 17 00:00:00 2001 From: Ron Frederick Date: Sat, 6 Aug 2022 11:45:53 -0700 Subject: [PATCH] Ignore encrypted keys in config by default when no passphrase is given This commit changes the default of the ignore_encrypted option to be True when keys are being loaded from config files, automatically ignoring encrypted keys when no passphrase is specified. For keys set via client_keys, the default is to still give an error in this case unless ignore_encrypted is explicitly set. When loading keys from their default locations, encrypted keys were already ignored when no passphrase is given, and this behavior isn't changing. --- asyncssh/connection.py | 13 +++++++++---- tests/test_connection.py | 20 ++++++++++++++++++++ 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/asyncssh/connection.py b/asyncssh/connection.py index 89a82b2..4656f4a 100644 --- a/asyncssh/connection.py +++ b/asyncssh/connection.py @@ -6491,9 +6491,9 @@ class SSHClientConnectionOptions(SSHConnectionOptions): are already loaded, this argument is ignored. :param ignore_encrypted: (optional) Whether or not to ignore encrypted keys when no passphrase is - provided. This is intended to allow encrypted keys specified via - the IdentityFile config option to be ignored if a passphrase - is not specified, loading only unencrypted local keys. Note + specified. This defaults to `True` for keys specified via + the IdentityFile config option, causing encrypted keys in the + config to be ignored when no passphrase is specified. Note that encrypted keys loaded into an SSH agent can still be used when this option is set. :param host_based_auth: (optional) @@ -6870,7 +6870,7 @@ def prepare(self, last_config: Optional[SSHConfig] = None, # type: ignore client_keys: _ClientKeysArg = (), client_certs: Sequence[FilePath] = (), passphrase: Optional[BytesOrStr] = None, - ignore_encrypted: bool = False, + ignore_encrypted: DefTuple[bool] = (), gss_host: DefTuple[Optional[str]] = (), gss_kex: DefTuple[bool] = (), gss_auth: DefTuple[bool] = (), gss_delegate_creds: DefTuple[bool] = (), @@ -7038,6 +7038,11 @@ def prepare(self, last_config: Optional[SSHConfig] = None, # type: ignore pkcs11_provider: Optional[FilePath] + if ignore_encrypted == (): + ignore_encrypted = client_keys == () + + ignore_encrypted: bool + if client_keys == (): client_keys = cast(_ClientKeysArg, config.get('IdentityFile', ())) diff --git a/tests/test_connection.py b/tests/test_connection.py index 9caa1c9..fe451a2 100644 --- a/tests/test_connection.py +++ b/tests/test_connection.py @@ -408,6 +408,26 @@ async def test_connect_sock(self): async with asyncssh.connect(sock=sock): pass + @asynctest + async def test_connect_encrypted_key(self): + """Test connecting with encrytped client key and no passphrase""" + + async with self.connect(client_keys='ckey_encrypted', + ignore_encrypted=True): + pass + + with self.assertRaises(asyncssh.KeyImportError): + await self.connect(client_keys='ckey_encrypted') + + with open('config', 'w') as f: + f.write('IdentityFile ckey_encrypted') + + async with self.connect(config='config'): + pass + + with self.assertRaises(asyncssh.KeyImportError): + await self.connect(config='config', ignore_encrypted=False) + @asynctest async def test_connect_invalid_options_type(self): """Test connecting using options using incorrect type of options"""