diff options
author | Jeff Forcier <jeff@bitprophet.org> | 2017-06-06 13:26:43 -0700 |
---|---|---|
committer | Jeff Forcier <jeff@bitprophet.org> | 2017-06-06 13:26:43 -0700 |
commit | 63dd0e2c2aa2413dd1032de5b2be5b9cc46dac2b (patch) | |
tree | 5dd1b9bd36792759d412ed8a2780681cf1b952c8 | |
parent | c1233679c448b445ec991710d259eec0a9f64b61 (diff) | |
parent | 1c88acaac8afd7d0dbf0062bcabff1795a4a729f (diff) |
Merge branch 'master' into 983-int
-rw-r--r-- | paramiko/client.py | 17 | ||||
-rw-r--r-- | paramiko/transport.py | 30 | ||||
-rw-r--r-- | sites/www/changelog.rst | 12 | ||||
-rw-r--r-- | tests/test_client.py | 17 |
4 files changed, 36 insertions, 40 deletions
diff --git a/paramiko/client.py b/paramiko/client.py index 689f84b1..08fe69d4 100644 --- a/paramiko/client.py +++ b/paramiko/client.py @@ -22,6 +22,7 @@ SSH client & key policies from binascii import hexlify import getpass +import inspect import os import socket import warnings @@ -170,16 +171,10 @@ class SSHClient (ClosingContextManager): Specifically: - * A **policy** is an instance of a "policy class", namely some subclass - of `.MissingHostKeyPolicy` such as `.RejectPolicy` (the default), - `.AutoAddPolicy`, `.WarningPolicy`, or a user-created subclass. - - .. note:: - This method takes class **instances**, not **classes** themselves. - Thus it must be called as e.g. - ``.set_missing_host_key_policy(WarningPolicy())`` and *not* - ``.set_missing_host_key_policy(WarningPolicy)``. - + * A **policy** is a "policy class" (or instance thereof), namely some + subclass of `.MissingHostKeyPolicy` such as `.RejectPolicy` (the + default), `.AutoAddPolicy`, `.WarningPolicy`, or a user-created + subclass. * A host key is **known** when it appears in the client object's cached host keys structures (those manipulated by `load_system_host_keys` and/or `load_host_keys`). @@ -188,6 +183,8 @@ class SSHClient (ClosingContextManager): the policy to use when receiving a host key from a previously-unknown server """ + if inspect.isclass(policy): + policy = policy() self._policy = policy def _families_and_addresses(self, hostname, port): diff --git a/paramiko/transport.py b/paramiko/transport.py index b6200933..688e09e7 100644 --- a/paramiko/transport.py +++ b/paramiko/transport.py @@ -74,7 +74,6 @@ from paramiko.ssh_exception import ( from paramiko.util import retry_on_signal, ClosingContextManager, clamp_value - # for thread cleanup _active_threads = [] @@ -114,8 +113,6 @@ class Transport(threading.Thread, ClosingContextManager): 'aes192-cbc', 'aes256-cbc', '3des-cbc', - 'arcfour128', - 'arcfour256', ) _preferred_macs = ( 'hmac-sha2-256', @@ -193,18 +190,6 @@ class Transport(threading.Thread, ClosingContextManager): 'block-size': 8, 'key-size': 24 }, - 'arcfour128': { - 'class': algorithms.ARC4, - 'mode': None, - 'block-size': 8, - 'key-size': 16 - }, - 'arcfour256': { - 'class': algorithms.ARC4, - 'mode': None, - 'block-size': 8, - 'key-size': 32 - }, } @@ -1756,21 +1741,6 @@ class Transport(threading.Thread, ClosingContextManager): def _get_cipher(self, name, key, iv, operation): if name not in self._cipher_info: raise SSHException('Unknown client cipher ' + name) - if name in ('arcfour128', 'arcfour256'): - # arcfour cipher - cipher = Cipher( - self._cipher_info[name]['class'](key), - None, - backend=default_backend() - ) - if operation is self._ENCRYPT: - engine = cipher.encryptor() - else: - engine = cipher.decryptor() - # as per RFC 4345, the first 1536 bytes of keystream - # generated by the cipher MUST be discarded - engine.encrypt(" " * 1536) - return engine else: cipher = Cipher( self._cipher_info[name]['class'](key), diff --git a/sites/www/changelog.rst b/sites/www/changelog.rst index 3f45334d..2e09a5c3 100644 --- a/sites/www/changelog.rst +++ b/sites/www/changelog.rst @@ -2,6 +2,18 @@ Changelog ========= +* :bug:`-` (partial application of :issue:`983`) Move ``sha1`` above the + now-arguably-broken ``md5`` in the list of preferred MAC algorithms, as an + incremental security improvement for users whose target systems offer both. + Credit: Pierce Lopez. +* :bug:`667` The RC4/arcfour family of ciphers has been broken since version + 2.0; but since the algorithm is now known to be completely insecure, we are + opting to remove support outright instead of fixing it. Thanks to Alex Gaynor + for catch & patch. +* :feature:`857` Allow `SSHClient.set_missing_host_key_policy + <paramiko.client.SSHClient.set_missing_host_key_policy>` to accept policy + classes _or_ instances, instead of only instances, thus fixing a + long-standing gotcha for unaware users. * :feature:`951` Add support for ECDH key exchange (kex), specifically the algorithms ``ecdh-sha2-nistp256``, ``ecdh-sha2-nistp384``, and ``ecdh-sha2-nistp521``. Thanks to Shashank Veerapaneni for the patch. diff --git a/tests/test_client.py b/tests/test_client.py index a340be00..3a9001e2 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -418,3 +418,20 @@ class SSHClientTest (unittest.TestCase): 'Expected original SSHException in exception') else: self.assertFalse(False, 'SSHException was not thrown.') + + + def test_missing_key_policy_accepts_classes_or_instances(self): + """ + Client.missing_host_key_policy() can take classes or instances. + """ + # AN ACTUAL UNIT TEST?! GOOD LORD + # (But then we have to test a private API...meh.) + client = paramiko.SSHClient() + # Default + assert isinstance(client._policy, paramiko.RejectPolicy) + # Hand in an instance (classic behavior) + client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + assert isinstance(client._policy, paramiko.AutoAddPolicy) + # Hand in just the class (new behavior) + client.set_missing_host_key_policy(paramiko.AutoAddPolicy) + assert isinstance(client._policy, paramiko.AutoAddPolicy) |