diff --git a/1311.patch b/1311.patch index 77cbae1..a35b135 100644 --- a/1311.patch +++ b/1311.patch @@ -1,8 +1,8 @@ -diff --git a/paramiko/ssh_gss.py b/paramiko/ssh_gss.py -index eb8826e01..4c2454712 100644 ---- a/paramiko/ssh_gss.py -+++ b/paramiko/ssh_gss.py -@@ -47,12 +47,18 @@ +Index: paramiko-2.5.0/paramiko/ssh_gss.py +=================================================================== +--- paramiko-2.5.0.orig/paramiko/ssh_gss.py ++++ paramiko-2.5.0/paramiko/ssh_gss.py +@@ -43,12 +43,21 @@ GSS_EXCEPTIONS = () #: :var str _API: Constraint for the used API @@ -11,20 +11,22 @@ index eb8826e01..4c2454712 100644 try: import gssapi -- + - GSS_EXCEPTIONS = (gssapi.GSSException,) -+ if hasattr(gssapi, '__title__') and gssapi.__title__ == 'python-gssapi': ++ if hasattr(gssapi, "__title__") and gssapi.__title__ == "python-gssapi": + # old, unmaintained python-gssapi package + _API = "MIT" # keep this for compatibility + GSS_EXCEPTIONS = (gssapi.GSSException,) + else: + _API = "PYTHON-GSSAPI-NEW" -+ GSS_EXCEPTIONS = (gssapi.exceptions.GeneralError, -+ gssapi.raw.misc.GSSError,) ++ GSS_EXCEPTIONS = ( ++ gssapi.exceptions.GeneralError, ++ gssapi.raw.misc.GSSError, ++ ) except (ImportError, OSError): try: import pywintypes -@@ -67,6 +73,7 @@ +@@ -63,6 +72,7 @@ except (ImportError, OSError): from paramiko.common import MSG_USERAUTH_REQUEST from paramiko.ssh_exception import SSHException @@ -32,7 +34,7 @@ index eb8826e01..4c2454712 100644 def GSSAuth(auth_method, gss_deleg_creds=True): -@@ -77,21 +84,24 @@ def GSSAuth(auth_method, gss_deleg_creds=True): +@@ -73,21 +83,24 @@ def GSSAuth(auth_method, gss_deleg_creds (gssapi-with-mic or gss-keyex) :param bool gss_deleg_creds: Delegate client credentials or not. We delegate credentials by default. @@ -40,7 +42,7 @@ index eb8826e01..4c2454712 100644 - `_SSH_SSPI` (Windows) object + :return: Either an `._SSH_GSSAPI_OLD` or `._SSH_GSSAPI_NEW` (Unix) + object or an `_SSH_SSPI` (Windows) object -+ :rtype: Object ++ :rtype: object :raises: ``ImportError`` -- If no GSS-API / SSPI module could be imported. @@ -50,8 +52,8 @@ index eb8826e01..4c2454712 100644 - get python-gssapi working on Windows, python-gssapi - will be used and a `._SSH_GSSAPI` object will be returned. + :note: Check for the available API and return either an `._SSH_GSSAPI_OLD` -+ (MIT GSSAPI using python-gssapi package) object, an `._SSH_GSSAPI_NEW` -+ (MIT GSSAPI using gssapi package) object ++ (MIT GSSAPI using python-gssapi package) object, an ++ `._SSH_GSSAPI_NEW` (MIT GSSAPI using gssapi package) object + or an `._SSH_SSPI` (MS SSPI) object. If there is no supported API available, ``None`` will be returned. @@ -64,16 +66,18 @@ index eb8826e01..4c2454712 100644 elif _API == "SSPI" and os.name == "nt": return _SSH_SSPI(auth_method, gss_deleg_creds) else: -@@ -100,7 +110,7 @@ def GSSAuth(auth_method, gss_deleg_creds=True): +@@ -96,8 +109,8 @@ def GSSAuth(auth_method, gss_deleg_creds class _SSH_GSSAuth(object): """ - Contains the shared variables and methods of `._SSH_GSSAPI` and -+ Contains the shared variables and methods of `._SSH_GSSAPI_*` and - `._SSH_SSPI`. +- `._SSH_SSPI`. ++ Contains the shared variables and methods of `._SSH_GSSAPI_OLD`, ++ `._SSH_GSSAPI_NEW` and `._SSH_SSPI`. """ -@@ -222,9 +232,10 @@ def _ssh_build_mic(self, session_id, username, service, auth_method): + def __init__(self, auth_method, gss_deleg_creds): +@@ -223,9 +236,10 @@ class _SSH_GSSAuth(object): return mic @@ -86,10 +90,11 @@ index eb8826e01..4c2454712 100644 :see: `.GSSAuth` """ -@@ -399,6 +410,174 @@ def save_client_creds(self, client_token): +@@ -401,6 +415,184 @@ class _SSH_GSSAPI(_SSH_GSSAuth): + """ raise NotImplementedError - ++ +if __version_info__[0] == 2 and __version_info__[0] <= 4: + # provide the old name for strict backward compatibility + _SSH_GSSAPI = _SSH_GSSAPI_OLD @@ -102,6 +107,7 @@ index eb8826e01..4c2454712 100644 + + :see: `.GSSAuth` + """ ++ + def __init__(self, auth_method, gss_deleg_creds): + """ + :param str auth_method: The name of the SSH authentication mechanism @@ -111,17 +117,22 @@ index eb8826e01..4c2454712 100644 + _SSH_GSSAuth.__init__(self, auth_method, gss_deleg_creds) + + if self._gss_deleg_creds: -+ self._gss_flags = (gssapi.RequirementFlag.protection_ready, -+ gssapi.RequirementFlag.integrity, -+ gssapi.RequirementFlag.mutual_authentication, -+ gssapi.RequirementFlag.delegate_to_peer) ++ self._gss_flags = ( ++ gssapi.RequirementFlag.protection_ready, ++ gssapi.RequirementFlag.integrity, ++ gssapi.RequirementFlag.mutual_authentication, ++ gssapi.RequirementFlag.delegate_to_peer, ++ ) + else: -+ self._gss_flags = (gssapi.RequirementFlag.protection_ready, -+ gssapi.RequirementFlag.integrity, -+ gssapi.RequirementFlag.mutual_authentication) ++ self._gss_flags = ( ++ gssapi.RequirementFlag.protection_ready, ++ gssapi.RequirementFlag.integrity, ++ gssapi.RequirementFlag.mutual_authentication, ++ ) + -+ def ssh_init_sec_context(self, target, desired_mech=None, -+ username=None, recv_token=None): ++ def ssh_init_sec_context( ++ self, target, desired_mech=None, username=None, recv_token=None ++ ): + """ + Initialize a GSS-API context. + @@ -131,18 +142,19 @@ index eb8826e01..4c2454712 100644 + ("pseudo negotiated" mechanism, because we + support just the krb5 mechanism :-)) + :param str recv_token: The GSS-API token received from the Server -+ :raise SSHException: Is raised if the desired mechanism of the client -+ is not supported -+ :raise gssapi.exceptions.GSSError: if there is an error signaled by the -+ GSS-API implementation -+ :return: A ``String`` if the GSS-API has returned a token or ``None`` if -+ no token was returned -+ :rtype: String or None ++ :raises: `.SSHException` -- Is raised if the desired mechanism of the ++ client is not supported ++ :raises: ``gssapi.exceptions.GSSError`` if there is an error signaled ++ by the GSS-API implementation ++ :return: A ``String`` if the GSS-API has returned a token or ``None`` ++ if no token was returned + """ + self._username = username + self._gss_host = target -+ targ_name = gssapi.Name("host@" + self._gss_host, -+ name_type=gssapi.NameType.hostbased_service) ++ targ_name = gssapi.Name( ++ "host@" + self._gss_host, ++ name_type=gssapi.NameType.hostbased_service, ++ ) + if desired_mech is not None: + mech, __ = decoder.decode(desired_mech) + if mech.__str__() != self._krb5_mech: @@ -150,10 +162,12 @@ index eb8826e01..4c2454712 100644 + krb5_mech = gssapi.MechType.kerberos + token = None + if recv_token is None: -+ self._gss_ctxt = gssapi.SecurityContext(name=targ_name, -+ flags=self._gss_flags, -+ mech=krb5_mech, -+ usage='initiate') ++ self._gss_ctxt = gssapi.SecurityContext( ++ name=targ_name, ++ flags=self._gss_flags, ++ mech=krb5_mech, ++ usage="initiate", ++ ) + token = self._gss_ctxt.step(token) + else: + token = self._gss_ctxt.step(recv_token) @@ -172,15 +186,16 @@ index eb8826e01..4c2454712 100644 + gssapi-keyex: + Returns the MIC token from GSS-API with the SSH session ID as + message. -+ :rtype: String -+ :see: `._ssh_build_mic` ++ :rtype: str + """ + self._session_id = session_id + if not gss_kex: -+ mic_field = self._ssh_build_mic(self._session_id, -+ self._username, -+ self._service, -+ self._auth_method) ++ mic_field = self._ssh_build_mic( ++ self._session_id, ++ self._username, ++ self._service, ++ self._auth_method, ++ ) + mic_token = self._gss_ctxt.get_signature(mic_field) + else: + # for key exchange with gssapi-keyex @@ -197,13 +212,12 @@ index eb8826e01..4c2454712 100644 + if it's not the initial call. + :return: A ``String`` if the GSS-API has returned a token or ``None`` + if no token was returned -+ :rtype: String or None + """ + # hostname and username are not required for GSSAPI, but for SSPI + self._gss_host = hostname + self._username = username + if self._gss_srv_ctxt is None: -+ self._gss_srv_ctxt = gssapi.SecurityContext(usage='accept') ++ self._gss_srv_ctxt = gssapi.SecurityContext(usage="accept") + token = self._gss_srv_ctxt.step(recv_token) + self._gss_srv_ctxt_status = self._gss_srv_ctxt.complete + return token @@ -216,22 +230,23 @@ index eb8826e01..4c2454712 100644 + :param str session_id: The SSH session ID + :param str username: The name of the user who attempts to login + :return: None if the MIC check was successful -+ :raises gssapi.exceptions.GSSError: if the MIC check failed ++ :raises: ``gssapi.exceptions.GSSError`` -- if the MIC check failed + """ + self._session_id = session_id + self._username = username + if self._username is not None: + # server mode -+ mic_field = self._ssh_build_mic(self._session_id, -+ self._username, -+ self._service, -+ self._auth_method) ++ mic_field = self._ssh_build_mic( ++ self._session_id, ++ self._username, ++ self._service, ++ self._auth_method, ++ ) + self._gss_srv_ctxt.verify_signature(mic_field, mic_token) + else: + # for key exchange with gssapi-keyex + # client mode -+ self._gss_ctxt.verify_signature(self._session_id, -+ mic_token) ++ self._gss_ctxt.verify_signature(self._session_id, mic_token) + + @property + def credentials_delegated(self): @@ -252,29 +267,51 @@ index eb8826e01..4c2454712 100644 + (server mode). + + :param str client_token: The GSS-API token received form the client -+ :raise NotImplementedError: Credential delegation is currently not -+ supported in server mode ++ :raises: ``NotImplementedError`` -- Credential delegation is currently ++ not supported in server mode + """ + raise NotImplementedError + -+ + class _SSH_SSPI(_SSH_GSSAuth): """ - Implementation of the Microsoft SSPI Kerberos Authentication for SSH2. -From a20936e18c0336476f8f4976257699a52e9a996e Mon Sep 17 00:00:00 2001 -From: Hugh Cole-Baker -Date: Sat, 10 Dec 2016 15:31:22 +0000 -Subject: [PATCH 2/8] Test the new and old Python GSSAPI packages - ---- - tests/test_gssapi.py | 49 ++++++++++++++++++++++++++++++++++++++++++-- - 1 file changed, 47 insertions(+), 2 deletions(-) - -diff --git a/tests/test_gssapi.py b/tests/test_gssapi.py -index 3e8c39e80..04304c0f2 100644 ---- a/tests/test_gssapi.py -+++ b/tests/test_gssapi.py -@@ -52,9 +52,12 @@ def test_2_gssapi_sspi(self): +Index: paramiko-2.5.0/tests/test_gssapi.py +=================================================================== +--- paramiko-2.5.0.orig/tests/test_gssapi.py ++++ paramiko-2.5.0/tests/test_gssapi.py +@@ -22,20 +22,20 @@ + Test the used APIs for GSS-API / SSPI authentication + """ + +-import unittest + import socket + +-from .util import needs_gssapi +- ++from .util import needs_gssapi, KerberosTestCase, update_env + + @needs_gssapi +-class GSSAPITest(unittest.TestCase): +- def setup(self): ++class GSSAPITest(KerberosTestCase): ++ def setUp(self): ++ super(GSSAPITest, self).setUp() + # TODO: these vars should all come from os.environ or whatever the + # approved pytest method is for runtime-configuring test data. + self.krb5_mech = "1.2.840.113554.1.2.2" +- self.targ_name = "hostname" ++ self.targ_name = self.realm.hostname + self.server_mode = False ++ update_env(self, self.realm.env) + + def test_pyasn1(self): + """ +@@ -48,13 +48,16 @@ class GSSAPITest(unittest.TestCase): + mech, __ = decoder.decode(oid) + self.assertEquals(self.krb5_mech, mech.__str__()) + +- def test_gssapi_sspi(self): ++ def _gssapi_sspi_test(self): """ Test the used methods of python-gssapi or sspi, sspicon from pywin32. """ @@ -288,7 +325,7 @@ index 3e8c39e80..04304c0f2 100644 except ImportError: import sspicon import sspi -@@ -65,7 +68,7 @@ def test_2_gssapi_sspi(self): +@@ -65,7 +68,7 @@ class GSSAPITest(unittest.TestCase): gss_ctxt_status = False mic_msg = b"G'day Mate!" @@ -297,34 +334,42 @@ index 3e8c39e80..04304c0f2 100644 if self.server_mode: gss_flags = ( gssapi.C_PROT_READY_FLAG, -@@ -113,6 +116,48 @@ def test_2_gssapi_sspi(self): +@@ -113,6 +116,56 @@ class GSSAPITest(unittest.TestCase): # Check MIC status = gss_srv_ctxt.verify_mic(mic_msg, mic_token) self.assertEquals(0, status) + elif _API == "PYTHON-GSSAPI-NEW": -+ if server_mode: -+ gss_flags = (gssapi.RequirementFlag.protection_ready, -+ gssapi.RequirementFlag.integrity, -+ gssapi.RequirementFlag.mutual_authentication, -+ gssapi.RequirementFlag.delegate_to_peer) ++ if self.server_mode: ++ gss_flags = ( ++ gssapi.RequirementFlag.protection_ready, ++ gssapi.RequirementFlag.integrity, ++ gssapi.RequirementFlag.mutual_authentication, ++ gssapi.RequirementFlag.delegate_to_peer, ++ ) + else: -+ gss_flags = (gssapi.RequirementFlag.protection_ready, -+ gssapi.RequirementFlag.integrity, -+ gssapi.RequirementFlag.delegate_to_peer) ++ gss_flags = ( ++ gssapi.RequirementFlag.protection_ready, ++ gssapi.RequirementFlag.integrity, ++ gssapi.RequirementFlag.delegate_to_peer, ++ ) + # Initialize a GSS-API context. + krb5_oid = gssapi.MechType.kerberos -+ target_name = gssapi.Name("host@" + targ_name, -+ name_type=gssapi.NameType.hostbased_service) -+ gss_ctxt = gssapi.SecurityContext(name=target_name, -+ flags=gss_flags, -+ mech=krb5_oid, -+ usage='initiate') -+ if server_mode: ++ target_name = gssapi.Name( ++ "host@" + self.targ_name, ++ name_type=gssapi.NameType.hostbased_service, ++ ) ++ gss_ctxt = gssapi.SecurityContext( ++ name=target_name, ++ flags=gss_flags, ++ mech=krb5_oid, ++ usage="initiate", ++ ) ++ if self.server_mode: + c_token = gss_ctxt.step(c_token) + gss_ctxt_status = gss_ctxt.complete + self.assertEquals(False, gss_ctxt_status) + # Accept a GSS-API context. -+ gss_srv_ctxt = gssapi.SecurityContext(usage='accept') ++ gss_srv_ctxt = gssapi.SecurityContext(usage="accept") + s_token = gss_srv_ctxt.step(c_token) + gss_ctxt_status = gss_srv_ctxt.complete + self.assertNotEquals(None, s_token) @@ -339,221 +384,14 @@ index 3e8c39e80..04304c0f2 100644 + # Build MIC + mic_token = gss_ctxt.get_signature(mic_msg) + -+ if server_mode: ++ if self.server_mode: + # Check MIC + status = gss_srv_ctxt.verify_signature(mic_msg, mic_token) + self.assertEquals(0, status) else: gss_flags = ( sspicon.ISC_REQ_INTEGRITY - -From db358dc149f7549c147e520bbe5c26b571d899d4 Mon Sep 17 00:00:00 2001 -From: Anselm Kruis -Date: Fri, 9 Feb 2018 23:48:47 +0100 -Subject: [PATCH 3/8] Fix Sphinx and PEP 8 warnings - ---- - paramiko/ssh_gss.py | 33 +++++++++++++++------------------ - 1 file changed, 15 insertions(+), 18 deletions(-) - -diff --git a/paramiko/ssh_gss.py b/paramiko/ssh_gss.py -index 4c2454712..ff2fa065b 100644 ---- a/paramiko/ssh_gss.py -+++ b/paramiko/ssh_gss.py -@@ -86,14 +86,14 @@ def GSSAuth(auth_method, gss_deleg_creds=True): - We delegate credentials by default. - :return: Either an `._SSH_GSSAPI_OLD` or `._SSH_GSSAPI_NEW` (Unix) - object or an `_SSH_SSPI` (Windows) object -- :rtype: Object -+ :rtype: object - - :raises: ``ImportError`` -- If no GSS-API / SSPI module could be imported. - - :see: `RFC 4462 `_ - :note: Check for the available API and return either an `._SSH_GSSAPI_OLD` -- (MIT GSSAPI using python-gssapi package) object, an `._SSH_GSSAPI_NEW` -- (MIT GSSAPI using gssapi package) object -+ (MIT GSSAPI using python-gssapi package) object, an -+ `._SSH_GSSAPI_NEW` (MIT GSSAPI using gssapi package) object - or an `._SSH_SSPI` (MS SSPI) object. - If there is no supported API available, - ``None`` will be returned. -@@ -110,8 +110,8 @@ def GSSAuth(auth_method, gss_deleg_creds=True): - - class _SSH_GSSAuth(object): - """ -- Contains the shared variables and methods of `._SSH_GSSAPI_*` and -- `._SSH_SSPI`. -+ Contains the shared variables and methods of `._SSH_GSSAPI_OLD`, -+ `._SSH_GSSAPI_NEW` and `._SSH_SSPI`. - """ - - def __init__(self, auth_method, gss_deleg_creds): -@@ -451,13 +451,12 @@ def ssh_init_sec_context(self, target, desired_mech=None, - ("pseudo negotiated" mechanism, because we - support just the krb5 mechanism :-)) - :param str recv_token: The GSS-API token received from the Server -- :raise SSHException: Is raised if the desired mechanism of the client -- is not supported -- :raise gssapi.exceptions.GSSError: if there is an error signaled by the -- GSS-API implementation -- :return: A ``String`` if the GSS-API has returned a token or ``None`` if -- no token was returned -- :rtype: String or None -+ :raises: `.SSHException` -- Is raised if the desired mechanism of the -+ client is not supported -+ :raises: ``gssapi.exceptions.GSSError`` if there is an error signaled -+ by the GSS-API implementation -+ :return: A ``String`` if the GSS-API has returned a token or ``None`` -+ if no token was returned - """ - self._username = username - self._gss_host = target -@@ -492,8 +491,7 @@ def ssh_get_mic(self, session_id, gss_kex=False): - gssapi-keyex: - Returns the MIC token from GSS-API with the SSH session ID as - message. -- :rtype: String -- :see: `._ssh_build_mic` -+ :rtype: str - """ - self._session_id = session_id - if not gss_kex: -@@ -517,7 +515,6 @@ def ssh_accept_sec_context(self, hostname, recv_token, username=None): - if it's not the initial call. - :return: A ``String`` if the GSS-API has returned a token or ``None`` - if no token was returned -- :rtype: String or None - """ - # hostname and username are not required for GSSAPI, but for SSPI - self._gss_host = hostname -@@ -536,7 +533,7 @@ def ssh_check_mic(self, mic_token, session_id, username=None): - :param str session_id: The SSH session ID - :param str username: The name of the user who attempts to login - :return: None if the MIC check was successful -- :raises gssapi.exceptions.GSSError: if the MIC check failed -+ :raises: ``gssapi.exceptions.GSSError`` -- if the MIC check failed - """ - self._session_id = session_id - self._username = username -@@ -572,8 +569,8 @@ def save_client_creds(self, client_token): - (server mode). - - :param str client_token: The GSS-API token received form the client -- :raise NotImplementedError: Credential delegation is currently not -- supported in server mode -+ :raises: ``NotImplementedError`` -- Credential delegation is currently -+ not supported in server mode - """ - raise NotImplementedError - - -From a36499fd8762a19da43ee16429b148cb89f4d39f Mon Sep 17 00:00:00 2001 -From: Anselm Kruis -Date: Fri, 5 Oct 2018 18:15:24 +0200 -Subject: [PATCH 4/8] Use k5test (if available) to execute GSSAPI related tests - -Previously testing of GSSAPI (Kerberos) related functions required an -externally provided Kerberos environment. Therefore all GSSAPI tests were -skipped. - -Now the package k5test is used to setup a self-contained Kerberos environment. -Because k5test requires the new GSSAPI, this commit also merges -pull request #1166 and fixes broken GSSAPI test. If k5test is not available -(i.e. on Windows), the tests still get skipped. - -The test case test_kex_gss.test_2_gsskex_and_auth_rekey is expected to fail. ---- - tests/test_gssapi.py | 41 ++++++++++++------- - tests/test_kex_gss.py | 20 ++++------ - tests/test_ssh_gss.py | 15 +++---- - tests/util.py | 93 ++++++++++++++++++++++++++++++++++++++++--- - 4 files changed, 131 insertions(+), 38 deletions(-) - -diff --git a/tests/test_gssapi.py b/tests/test_gssapi.py -index 04304c0f2..98d4d14ec 100644 ---- a/tests/test_gssapi.py -+++ b/tests/test_gssapi.py -@@ -22,20 +22,19 @@ - Test the used APIs for GSS-API / SSPI authentication - """ - --import unittest - import socket - --from .util import needs_gssapi -+from .util import needs_gssapi, KerberosTestCase, update_env - - - @needs_gssapi --class GSSAPITest(unittest.TestCase): -- def setup(): -- # TODO: these vars should all come from os.environ or whatever the -- # approved pytest method is for runtime-configuring test data. -+class GSSAPITest(KerberosTestCase): -+ def setUp(self): -+ super(GSSAPITest, self).setUp() - self.krb5_mech = "1.2.840.113554.1.2.2" -- self.targ_name = "hostname" -+ self.targ_name = self.realm.hostname - self.server_mode = False -+ update_env(self, self.realm.env) - - def test_1_pyasn1(self): - """ -@@ -48,13 +47,14 @@ def test_1_pyasn1(self): - mech, __ = decoder.decode(oid) - self.assertEquals(self.krb5_mech, mech.__str__()) - -- def test_2_gssapi_sspi(self): -+ def _gssapi_sspi_test(self): - """ - Test the used methods of python-gssapi or sspi, sspicon from pywin32. - """ - try: - import gssapi -- if hasattr(gssapi, '__title__') and gssapi.__title__ == 'python-gssapi': -+ if (hasattr(gssapi, '__title__') and -+ gssapi.__title__ == 'python-gssapi'): - _API = "PYTHON-GSSAPI-OLD" - else: - _API = "PYTHON-GSSAPI-NEW" -@@ -117,7 +117,7 @@ def test_2_gssapi_sspi(self): - status = gss_srv_ctxt.verify_mic(mic_msg, mic_token) - self.assertEquals(0, status) - elif _API == "PYTHON-GSSAPI-NEW": -- if server_mode: -+ if self.server_mode: - gss_flags = (gssapi.RequirementFlag.protection_ready, - gssapi.RequirementFlag.integrity, - gssapi.RequirementFlag.mutual_authentication, -@@ -128,13 +128,13 @@ def test_2_gssapi_sspi(self): - gssapi.RequirementFlag.delegate_to_peer) - # Initialize a GSS-API context. - krb5_oid = gssapi.MechType.kerberos -- target_name = gssapi.Name("host@" + targ_name, -- name_type=gssapi.NameType.hostbased_service) -+ target_name = gssapi.Name("host@" + self.targ_name, -+ name_type=gssapi.NameType.hostbased_service) - gss_ctxt = gssapi.SecurityContext(name=target_name, - flags=gss_flags, - mech=krb5_oid, - usage='initiate') -- if server_mode: -+ if self.server_mode: - c_token = gss_ctxt.step(c_token) - gss_ctxt_status = gss_ctxt.complete - self.assertEquals(False, gss_ctxt_status) -@@ -154,7 +154,7 @@ def test_2_gssapi_sspi(self): - # Build MIC - mic_token = gss_ctxt.get_signature(mic_msg) - -- if server_mode: -+ if self.server_mode: - # Check MIC - status = gss_srv_ctxt.verify_signature(mic_msg, mic_token) - self.assertEquals(0, status) -@@ -190,3 +190,16 @@ def test_2_gssapi_sspi(self): +@@ -145,3 +198,16 @@ class GSSAPITest(unittest.TestCase): error, token = gss_ctxt.authorize(c_token) c_token = token[0].Buffer self.assertNotEquals(0, error) @@ -570,11 +408,11 @@ index 04304c0f2..98d4d14ec 100644 + """ + self.server_mode = True + self._gssapi_sspi_test() -diff --git a/tests/test_kex_gss.py b/tests/test_kex_gss.py -index c71ff91c2..e58be65d9 100644 ---- a/tests/test_kex_gss.py -+++ b/tests/test_kex_gss.py -@@ -31,7 +31,7 @@ +Index: paramiko-2.5.0/tests/test_kex_gss.py +=================================================================== +--- paramiko-2.5.0.orig/tests/test_kex_gss.py ++++ paramiko-2.5.0/tests/test_kex_gss.py +@@ -31,7 +31,7 @@ import unittest import paramiko @@ -583,7 +421,14 @@ index c71ff91c2..e58be65d9 100644 class NullServer(paramiko.ServerInterface): -@@ -59,21 +59,16 @@ def check_channel_exec_request(self, channel, command): +@@ -53,27 +53,22 @@ class NullServer(paramiko.ServerInterfac + return paramiko.OPEN_SUCCEEDED + + def check_channel_exec_request(self, channel, command): +- if command != "yes": ++ if command != b"yes": + return False + return True @needs_gssapi @@ -610,7 +455,7 @@ index c71ff91c2..e58be65d9 100644 thread = threading.Thread(target=self._run) thread.start() -@@ -87,7 +82,7 @@ def _run(self): +@@ -87,7 +82,7 @@ class GSSKexTest(unittest.TestCase): self.ts = paramiko.Transport(self.socks, gss_kex=True) host_key = paramiko.RSAKey.from_private_key_file("tests/test_rsa.key") self.ts.add_server_key(host_key) @@ -619,19 +464,19 @@ index c71ff91c2..e58be65d9 100644 try: self.ts.load_server_moduli() except: -@@ -150,6 +145,7 @@ def test_1_gsskex_and_auth(self): +@@ -150,6 +145,7 @@ class GSSKexTest(unittest.TestCase): """ self._test_gsskex_and_auth(gss_host=None) -+ @unittest.expectedFailure # to be investigated - def test_2_gsskex_and_auth_rekey(self): ++ @unittest.expectedFailure # to be investigated, see https://github.com/paramiko/paramiko/issues/1312 + def test_gsskex_and_auth_rekey(self): """ Verify that Paramiko can rekey. -diff --git a/tests/test_ssh_gss.py b/tests/test_ssh_gss.py -index b6b501528..d326f522e 100644 ---- a/tests/test_ssh_gss.py -+++ b/tests/test_ssh_gss.py -@@ -25,11 +25,10 @@ +Index: paramiko-2.5.0/tests/test_ssh_gss.py +=================================================================== +--- paramiko-2.5.0.orig/tests/test_ssh_gss.py ++++ paramiko-2.5.0/tests/test_ssh_gss.py +@@ -25,11 +25,10 @@ Unit Tests for the GSS-API / SSPI SSHv2 import socket import threading @@ -644,7 +489,14 @@ index b6b501528..d326f522e 100644 from .test_client import FINGERPRINTS -@@ -67,17 +66,18 @@ def check_channel_exec_request(self, channel, command): +@@ -61,23 +60,24 @@ class NullServer(paramiko.ServerInterfac + return paramiko.OPEN_SUCCEEDED + + def check_channel_exec_request(self, channel, command): +- if command != "yes": ++ if command != b"yes": + return False + return True @needs_gssapi @@ -667,21 +519,11 @@ index b6b501528..d326f522e 100644 thread = threading.Thread(target=self._run) thread.start() -@@ -148,7 +148,8 @@ def test_1_gss_auth(self): - - def test_2_auth_trickledown(self): - """ -- Failed gssapi-with-mic auth doesn't prevent subsequent key auth from succeeding -+ Failed gssapi-with-mic auth doesn't prevent subsequent key auth from -+ succeeding - """ - self.hostname = ( - "this_host_does_not_exists_and_causes_a_GSSAPI-exception" -diff --git a/tests/util.py b/tests/util.py -index 4ca023743..be56b37dc 100644 ---- a/tests/util.py -+++ b/tests/util.py -@@ -1,19 +1,20 @@ +Index: paramiko-2.5.0/tests/util.py +=================================================================== +--- paramiko-2.5.0.orig/tests/util.py ++++ paramiko-2.5.0/tests/util.py +@@ -1,19 +1,21 @@ from os.path import dirname, realpath, join +import os +import sys @@ -702,12 +544,13 @@ index 4ca023743..be56b37dc 100644 -# JUST key off presence of GSSAPI optional dependency... -# TODO: anyway, s/True/os.environ.get('RUN_GSSAPI', False)/ or something. -needs_gssapi = pytest.mark.skipif(True, reason="No GSSAPI to test") -+needs_gssapi = pytest.mark.skipif(not GSS_AUTH_AVAILABLE, -+ reason="No GSSAPI to test") ++needs_gssapi = pytest.mark.skipif( ++ not GSS_AUTH_AVAILABLE, reason="No GSSAPI to test" ++) def needs_builtin(name): -@@ -25,3 +26,85 @@ def needs_builtin(name): +@@ -25,3 +27,96 @@ def needs_builtin(name): slow = pytest.mark.slow @@ -726,9 +569,11 @@ index 4ca023743..be56b37dc 100644 +# +# ToDo: add a Windows specific implementation? + -+if (os.environ.get("K5TEST_USER_PRINC", None) and -+ os.environ.get("K5TEST_HOSTNAME", None) and -+ os.environ.get("KRB5_KTNAME", None)): # add other vars as needed ++if ( ++ os.environ.get("K5TEST_USER_PRINC", None) ++ and os.environ.get("K5TEST_HOSTNAME", None) ++ and os.environ.get("KRB5_KTNAME", None) ++): # add other vars as needed + + # The environment provides the required information + class DummyK5Realm(object): @@ -747,6 +592,8 @@ index 4ca023743..be56b37dc 100644 + @classmethod + def tearDownClass(cls): + del cls.realm ++ ++ +else: + try: + # Try to setup a kerberos environment @@ -756,22 +603,28 @@ index 4ca023743..be56b37dc 100644 + class KerberosTestCase(unittest.TestCase): + @classmethod + def setUpClass(cls): -+ raise unittest.SkipTest('Missing extension package k5test. ' -+ 'Please run "pip install k5test" ' -+ 'to install it.') ++ raise unittest.SkipTest( ++ "Missing extension package k5test. " ++ 'Please run "pip install k5test" ' ++ "to install it." ++ ) ++ + +def update_env(testcase, mapping, env=os.environ): + """Modify os.environ during a test case and restore during cleanup.""" + saved_env = env.copy() ++ + def replace(target, source): + target.update(source) + for k in list(target): + if k not in source: + target.pop(k, None) ++ + testcase.addCleanup(replace, env, saved_env) + env.update(mapping) + return testcase + ++ +def k5shell(args=None): + """Create a shell with an kerberos environment + @@ -782,6 +635,7 @@ index 4ca023743..be56b37dc 100644 + import k5test + import atexit + import subprocess ++ + k5 = k5test.K5Realm() + atexit.register(k5.stop) + os.environ.update(k5.env) @@ -793,369 +647,3 @@ index 4ca023743..be56b37dc 100644 + if not args: + args = [os.environ.get("SHELL", "bash")] + sys.exit(subprocess.call(args)) - -From a8e8f9aa89c2c1fe65e4477d8d553eb5e669c927 Mon Sep 17 00:00:00 2001 -From: Anselm Kruis -Date: Fri, 5 Oct 2018 19:30:48 +0200 -Subject: [PATCH 5/8] Reformatted as proposed by travis.blacken - ---- - paramiko/ssh_gss.py | 74 +++++++++++++++++++++++++++----------------- - tests/test_gssapi.py | 43 +++++++++++++++---------- - tests/util.py | 28 ++++++++++++----- - 3 files changed, 92 insertions(+), 53 deletions(-) - -diff --git a/paramiko/ssh_gss.py b/paramiko/ssh_gss.py -index ff2fa065b..06aac761c 100644 ---- a/paramiko/ssh_gss.py -+++ b/paramiko/ssh_gss.py -@@ -51,14 +51,17 @@ - - try: - import gssapi -- if hasattr(gssapi, '__title__') and gssapi.__title__ == 'python-gssapi': -+ -+ if hasattr(gssapi, "__title__") and gssapi.__title__ == "python-gssapi": - # old, unmaintained python-gssapi package - _API = "MIT" # keep this for compatibility - GSS_EXCEPTIONS = (gssapi.GSSException,) - else: - _API = "PYTHON-GSSAPI-NEW" -- GSS_EXCEPTIONS = (gssapi.exceptions.GeneralError, -- gssapi.raw.misc.GSSError,) -+ GSS_EXCEPTIONS = ( -+ gssapi.exceptions.GeneralError, -+ gssapi.raw.misc.GSSError, -+ ) - except (ImportError, OSError): - try: - import pywintypes -@@ -422,6 +425,7 @@ class _SSH_GSSAPI_NEW(_SSH_GSSAuth): - - :see: `.GSSAuth` - """ -+ - def __init__(self, auth_method, gss_deleg_creds): - """ - :param str auth_method: The name of the SSH authentication mechanism -@@ -431,17 +435,22 @@ def __init__(self, auth_method, gss_deleg_creds): - _SSH_GSSAuth.__init__(self, auth_method, gss_deleg_creds) - - if self._gss_deleg_creds: -- self._gss_flags = (gssapi.RequirementFlag.protection_ready, -- gssapi.RequirementFlag.integrity, -- gssapi.RequirementFlag.mutual_authentication, -- gssapi.RequirementFlag.delegate_to_peer) -+ self._gss_flags = ( -+ gssapi.RequirementFlag.protection_ready, -+ gssapi.RequirementFlag.integrity, -+ gssapi.RequirementFlag.mutual_authentication, -+ gssapi.RequirementFlag.delegate_to_peer, -+ ) - else: -- self._gss_flags = (gssapi.RequirementFlag.protection_ready, -- gssapi.RequirementFlag.integrity, -- gssapi.RequirementFlag.mutual_authentication) -+ self._gss_flags = ( -+ gssapi.RequirementFlag.protection_ready, -+ gssapi.RequirementFlag.integrity, -+ gssapi.RequirementFlag.mutual_authentication, -+ ) - -- def ssh_init_sec_context(self, target, desired_mech=None, -- username=None, recv_token=None): -+ def ssh_init_sec_context( -+ self, target, desired_mech=None, username=None, recv_token=None -+ ): - """ - Initialize a GSS-API context. - -@@ -460,8 +469,10 @@ def ssh_init_sec_context(self, target, desired_mech=None, - """ - self._username = username - self._gss_host = target -- targ_name = gssapi.Name("host@" + self._gss_host, -- name_type=gssapi.NameType.hostbased_service) -+ targ_name = gssapi.Name( -+ "host@" + self._gss_host, -+ name_type=gssapi.NameType.hostbased_service, -+ ) - if desired_mech is not None: - mech, __ = decoder.decode(desired_mech) - if mech.__str__() != self._krb5_mech: -@@ -469,10 +480,12 @@ def ssh_init_sec_context(self, target, desired_mech=None, - krb5_mech = gssapi.MechType.kerberos - token = None - if recv_token is None: -- self._gss_ctxt = gssapi.SecurityContext(name=targ_name, -- flags=self._gss_flags, -- mech=krb5_mech, -- usage='initiate') -+ self._gss_ctxt = gssapi.SecurityContext( -+ name=targ_name, -+ flags=self._gss_flags, -+ mech=krb5_mech, -+ usage="initiate", -+ ) - token = self._gss_ctxt.step(token) - else: - token = self._gss_ctxt.step(recv_token) -@@ -495,10 +508,12 @@ def ssh_get_mic(self, session_id, gss_kex=False): - """ - self._session_id = session_id - if not gss_kex: -- mic_field = self._ssh_build_mic(self._session_id, -- self._username, -- self._service, -- self._auth_method) -+ mic_field = self._ssh_build_mic( -+ self._session_id, -+ self._username, -+ self._service, -+ self._auth_method, -+ ) - mic_token = self._gss_ctxt.get_signature(mic_field) - else: - # for key exchange with gssapi-keyex -@@ -520,7 +535,7 @@ def ssh_accept_sec_context(self, hostname, recv_token, username=None): - self._gss_host = hostname - self._username = username - if self._gss_srv_ctxt is None: -- self._gss_srv_ctxt = gssapi.SecurityContext(usage='accept') -+ self._gss_srv_ctxt = gssapi.SecurityContext(usage="accept") - token = self._gss_srv_ctxt.step(recv_token) - self._gss_srv_ctxt_status = self._gss_srv_ctxt.complete - return token -@@ -539,16 +554,17 @@ def ssh_check_mic(self, mic_token, session_id, username=None): - self._username = username - if self._username is not None: - # server mode -- mic_field = self._ssh_build_mic(self._session_id, -- self._username, -- self._service, -- self._auth_method) -+ mic_field = self._ssh_build_mic( -+ self._session_id, -+ self._username, -+ self._service, -+ self._auth_method, -+ ) - self._gss_srv_ctxt.verify_signature(mic_field, mic_token) - else: - # for key exchange with gssapi-keyex - # client mode -- self._gss_ctxt.verify_signature(self._session_id, -- mic_token) -+ self._gss_ctxt.verify_signature(self._session_id, mic_token) - - @property - def credentials_delegated(self): -diff --git a/tests/test_gssapi.py b/tests/test_gssapi.py -index 98d4d14ec..8e6ec37ab 100644 ---- a/tests/test_gssapi.py -+++ b/tests/test_gssapi.py -@@ -53,8 +53,11 @@ def _gssapi_sspi_test(self): - """ - try: - import gssapi -- if (hasattr(gssapi, '__title__') and -- gssapi.__title__ == 'python-gssapi'): -+ -+ if ( -+ hasattr(gssapi, "__title__") -+ and gssapi.__title__ == "python-gssapi" -+ ): - _API = "PYTHON-GSSAPI-OLD" - else: - _API = "PYTHON-GSSAPI-NEW" -@@ -118,28 +121,36 @@ def _gssapi_sspi_test(self): - self.assertEquals(0, status) - elif _API == "PYTHON-GSSAPI-NEW": - if self.server_mode: -- gss_flags = (gssapi.RequirementFlag.protection_ready, -- gssapi.RequirementFlag.integrity, -- gssapi.RequirementFlag.mutual_authentication, -- gssapi.RequirementFlag.delegate_to_peer) -+ gss_flags = ( -+ gssapi.RequirementFlag.protection_ready, -+ gssapi.RequirementFlag.integrity, -+ gssapi.RequirementFlag.mutual_authentication, -+ gssapi.RequirementFlag.delegate_to_peer, -+ ) - else: -- gss_flags = (gssapi.RequirementFlag.protection_ready, -- gssapi.RequirementFlag.integrity, -- gssapi.RequirementFlag.delegate_to_peer) -+ gss_flags = ( -+ gssapi.RequirementFlag.protection_ready, -+ gssapi.RequirementFlag.integrity, -+ gssapi.RequirementFlag.delegate_to_peer, -+ ) - # Initialize a GSS-API context. - krb5_oid = gssapi.MechType.kerberos -- target_name = gssapi.Name("host@" + self.targ_name, -- name_type=gssapi.NameType.hostbased_service) -- gss_ctxt = gssapi.SecurityContext(name=target_name, -- flags=gss_flags, -- mech=krb5_oid, -- usage='initiate') -+ target_name = gssapi.Name( -+ "host@" + self.targ_name, -+ name_type=gssapi.NameType.hostbased_service, -+ ) -+ gss_ctxt = gssapi.SecurityContext( -+ name=target_name, -+ flags=gss_flags, -+ mech=krb5_oid, -+ usage="initiate", -+ ) - if self.server_mode: - c_token = gss_ctxt.step(c_token) - gss_ctxt_status = gss_ctxt.complete - self.assertEquals(False, gss_ctxt_status) - # Accept a GSS-API context. -- gss_srv_ctxt = gssapi.SecurityContext(usage='accept') -+ gss_srv_ctxt = gssapi.SecurityContext(usage="accept") - s_token = gss_srv_ctxt.step(c_token) - gss_ctxt_status = gss_srv_ctxt.complete - self.assertNotEquals(None, s_token) -diff --git a/tests/util.py b/tests/util.py -index be56b37dc..cdc835c95 100644 ---- a/tests/util.py -+++ b/tests/util.py -@@ -13,8 +13,9 @@ def _support(filename): - return join(dirname(realpath(__file__)), filename) - - --needs_gssapi = pytest.mark.skipif(not GSS_AUTH_AVAILABLE, -- reason="No GSSAPI to test") -+needs_gssapi = pytest.mark.skipif( -+ not GSS_AUTH_AVAILABLE, reason="No GSSAPI to test" -+) - - - def needs_builtin(name): -@@ -41,9 +42,11 @@ def needs_builtin(name): - # - # ToDo: add a Windows specific implementation? - --if (os.environ.get("K5TEST_USER_PRINC", None) and -- os.environ.get("K5TEST_HOSTNAME", None) and -- os.environ.get("KRB5_KTNAME", None)): # add other vars as needed -+if ( -+ os.environ.get("K5TEST_USER_PRINC", None) -+ and os.environ.get("K5TEST_HOSTNAME", None) -+ and os.environ.get("KRB5_KTNAME", None) -+): # add other vars as needed - - # The environment provides the required information - class DummyK5Realm(object): -@@ -62,6 +65,8 @@ def setUpClass(cls): - @classmethod - def tearDownClass(cls): - del cls.realm -+ -+ - else: - try: - # Try to setup a kerberos environment -@@ -71,22 +76,28 @@ def tearDownClass(cls): - class KerberosTestCase(unittest.TestCase): - @classmethod - def setUpClass(cls): -- raise unittest.SkipTest('Missing extension package k5test. ' -- 'Please run "pip install k5test" ' -- 'to install it.') -+ raise unittest.SkipTest( -+ "Missing extension package k5test. " -+ 'Please run "pip install k5test" ' -+ "to install it." -+ ) -+ - - def update_env(testcase, mapping, env=os.environ): - """Modify os.environ during a test case and restore during cleanup.""" - saved_env = env.copy() -+ - def replace(target, source): - target.update(source) - for k in list(target): - if k not in source: - target.pop(k, None) -+ - testcase.addCleanup(replace, env, saved_env) - env.update(mapping) - return testcase - -+ - def k5shell(args=None): - """Create a shell with an kerberos environment - -@@ -97,6 +108,7 @@ def k5shell(args=None): - import k5test - import atexit - import subprocess -+ - k5 = k5test.K5Realm() - atexit.register(k5.stop) - os.environ.update(k5.env) - -From 1694e6e46032c63ab9e1015adedda0cf1cc14912 Mon Sep 17 00:00:00 2001 -From: Anselm Kruis -Date: Sat, 6 Oct 2018 16:09:33 +0200 -Subject: [PATCH 6/8] fix GSSAPI tests for Python3 (trivial) - ---- - tests/test_kex_gss.py | 2 +- - tests/test_ssh_gss.py | 2 +- - 2 files changed, 2 insertions(+), 2 deletions(-) - -diff --git a/tests/test_kex_gss.py b/tests/test_kex_gss.py -index e58be65d9..7e53795f1 100644 ---- a/tests/test_kex_gss.py -+++ b/tests/test_kex_gss.py -@@ -53,7 +53,7 @@ def check_channel_request(self, kind, chanid): - return paramiko.OPEN_SUCCEEDED - - def check_channel_exec_request(self, channel, command): -- if command != "yes": -+ if command != b"yes": - return False - return True - -diff --git a/tests/test_ssh_gss.py b/tests/test_ssh_gss.py -index d326f522e..8e4cb962f 100644 ---- a/tests/test_ssh_gss.py -+++ b/tests/test_ssh_gss.py -@@ -60,7 +60,7 @@ def check_channel_request(self, kind, chanid): - return paramiko.OPEN_SUCCEEDED - - def check_channel_exec_request(self, channel, command): -- if command != "yes": -+ if command != b"yes": - return False - return True - - -From f3af0b3e697adc8902039b21fde93871048160e4 Mon Sep 17 00:00:00 2001 -From: Anselm Kruis -Date: Mon, 8 Oct 2018 09:17:50 +0200 -Subject: [PATCH 8/8] Update a comment - ---- - tests/test_kex_gss.py | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/tests/test_kex_gss.py b/tests/test_kex_gss.py -index 7e53795f1..6bac01201 100644 ---- a/tests/test_kex_gss.py -+++ b/tests/test_kex_gss.py -@@ -145,7 +145,7 @@ def test_1_gsskex_and_auth(self): - """ - self._test_gsskex_and_auth(gss_host=None) - -- @unittest.expectedFailure # to be investigated -+ @unittest.expectedFailure # to be investigated, see https://github.com/paramiko/paramiko/issues/1312 - def test_2_gsskex_and_auth_rekey(self): - """ - Verify that Paramiko can rekey. diff --git a/1379.patch b/1379.patch deleted file mode 100644 index 1d09a89..0000000 --- a/1379.patch +++ /dev/null @@ -1,172 +0,0 @@ -From 36fbe57629cbbb7bf0f4a1e98c43352b82fe181d Mon Sep 17 00:00:00 2001 -From: Andrew Wason -Date: Wed, 6 Feb 2019 10:56:53 -0500 -Subject: [PATCH 1/4] Move to cryptography 2.5 and stop using deprecated APIs. - -Fixes #1369 ---- - paramiko/ecdsakey.py | 4 ++-- - paramiko/kex_ecdh_nist.py | 37 +++++++++++++++++++++++++++++-------- - setup.py | 2 +- - tests/test_kex.py | 12 ++++++------ - 5 files changed, 40 insertions(+), 19 deletions(-) - -Index: paramiko-2.4.2/paramiko/ecdsakey.py -=================================================================== ---- paramiko-2.4.2.orig/paramiko/ecdsakey.py -+++ paramiko-2.4.2/paramiko/ecdsakey.py -@@ -160,12 +160,12 @@ class ECDSAKey(PKey): - - pointinfo = msg.get_binary() - try: -- numbers = ec.EllipticCurvePublicNumbers.from_encoded_point( -+ key = ec.EllipticCurvePublicKey.from_encoded_point( - self.ecdsa_curve.curve_class(), pointinfo - ) -+ self.verifying_key = key - except ValueError: - raise SSHException("Invalid public key") -- self.verifying_key = numbers.public_key(backend=default_backend()) - - @classmethod - def supported_key_format_identifiers(cls): -Index: paramiko-2.4.2/paramiko/kex_ecdh_nist.py -=================================================================== ---- paramiko-2.4.2.orig/paramiko/kex_ecdh_nist.py -+++ paramiko-2.4.2/paramiko/kex_ecdh_nist.py -@@ -9,6 +9,7 @@ from paramiko.py3compat import byte_chr, - from paramiko.ssh_exception import SSHException - from cryptography.hazmat.backends import default_backend - from cryptography.hazmat.primitives.asymmetric import ec -+from cryptography.hazmat.primitives import serialization - from binascii import hexlify - - _MSG_KEXECDH_INIT, _MSG_KEXECDH_REPLY = range(30, 32) -@@ -36,7 +37,12 @@ class KexNistp256: - m = Message() - m.add_byte(c_MSG_KEXECDH_INIT) - # SEC1: V2.0 2.3.3 Elliptic-Curve-Point-to-Octet-String Conversion -- m.add_string(self.Q_C.public_numbers().encode_point()) -+ m.add_string( -+ self.Q_C.public_bytes( -+ serialization.Encoding.X962, -+ serialization.PublicFormat.UncompressedPoint, -+ ) -+ ) - self.transport._send_message(m) - self.transport._expect_packet(_MSG_KEXECDH_REPLY) - -@@ -58,11 +64,11 @@ class KexNistp256: - - def _parse_kexecdh_init(self, m): - Q_C_bytes = m.get_string() -- self.Q_C = ec.EllipticCurvePublicNumbers.from_encoded_point( -+ self.Q_C = ec.EllipticCurvePublicKey.from_encoded_point( - self.curve, Q_C_bytes - ) - K_S = self.transport.get_server_key().asbytes() -- K = self.P.exchange(ec.ECDH(), self.Q_C.public_key(default_backend())) -+ K = self.P.exchange(ec.ECDH(), self.Q_C) - K = long(hexlify(K), 16) - # compute exchange hash - hm = Message() -@@ -75,7 +81,12 @@ class KexNistp256: - hm.add_string(K_S) - hm.add_string(Q_C_bytes) - # SEC1: V2.0 2.3.3 Elliptic-Curve-Point-to-Octet-String Conversion -- hm.add_string(self.Q_S.public_numbers().encode_point()) -+ hm.add_string( -+ self.Q_S.public_bytes( -+ serialization.Encoding.X962, -+ serialization.PublicFormat.UncompressedPoint, -+ ) -+ ) - hm.add_mpint(long(K)) - H = self.hash_algo(hm.asbytes()).digest() - self.transport._set_K_H(K, H) -@@ -84,7 +95,12 @@ class KexNistp256: - m = Message() - m.add_byte(c_MSG_KEXECDH_REPLY) - m.add_string(K_S) -- m.add_string(self.Q_S.public_numbers().encode_point()) -+ m.add_string( -+ self.Q_S.public_bytes( -+ serialization.Encoding.X962, -+ serialization.PublicFormat.UncompressedPoint, -+ ) -+ ) - m.add_string(sig) - self.transport._send_message(m) - self.transport._activate_outbound() -@@ -92,11 +108,11 @@ class KexNistp256: - def _parse_kexecdh_reply(self, m): - K_S = m.get_string() - Q_S_bytes = m.get_string() -- self.Q_S = ec.EllipticCurvePublicNumbers.from_encoded_point( -+ self.Q_S = ec.EllipticCurvePublicKey.from_encoded_point( - self.curve, Q_S_bytes - ) - sig = m.get_binary() -- K = self.P.exchange(ec.ECDH(), self.Q_S.public_key(default_backend())) -+ K = self.P.exchange(ec.ECDH(), self.Q_S) - K = long(hexlify(K), 16) - # compute exchange hash and verify signature - hm = Message() -@@ -108,7 +124,12 @@ class KexNistp256: - ) - hm.add_string(K_S) - # SEC1: V2.0 2.3.3 Elliptic-Curve-Point-to-Octet-String Conversion -- hm.add_string(self.Q_C.public_numbers().encode_point()) -+ hm.add_string( -+ self.Q_C.public_bytes( -+ serialization.Encoding.X962, -+ serialization.PublicFormat.UncompressedPoint, -+ ) -+ ) - hm.add_string(Q_S_bytes) - hm.add_mpint(K) - self.transport._set_K_H(K, self.hash_algo(hm.asbytes()).digest()) -Index: paramiko-2.4.2/setup.py -=================================================================== ---- paramiko-2.4.2.orig/setup.py -+++ paramiko-2.4.2/setup.py -@@ -73,7 +73,7 @@ setup( - ], - install_requires=[ - "bcrypt>=3.1.3", -- "cryptography>=1.5", -+ "cryptography>=2.5", - "pynacl>=1.0.1", - "pyasn1>=0.1.7", - ], -Index: paramiko-2.4.2/tests/test_kex.py -=================================================================== ---- paramiko-2.4.2.orig/tests/test_kex.py -+++ paramiko-2.4.2/tests/test_kex.py -@@ -42,20 +42,20 @@ def dummy_urandom(n): - def dummy_generate_key_pair(obj): - private_key_value = 94761803665136558137557783047955027733968423115106677159790289642479432803037 - public_key_numbers = "042bdab212fa8ba1b7c843301682a4db424d307246c7e1e6083c41d9ca7b098bf30b3d63e2ec6278488c135360456cc054b3444ecc45998c08894cbc1370f5f989" -- public_key_numbers_obj = ec.EllipticCurvePublicNumbers.from_encoded_point( -+ public_key_numbers_obj = ec.EllipticCurvePublicKey.from_encoded_point( - ec.SECP256R1(), unhexlify(public_key_numbers) -- ) -+ ).public_numbers() - obj.P = ec.EllipticCurvePrivateNumbers( - private_value=private_key_value, public_numbers=public_key_numbers_obj - ).private_key(default_backend()) - if obj.transport.server_mode: -- obj.Q_S = ec.EllipticCurvePublicNumbers.from_encoded_point( -+ obj.Q_S = ec.EllipticCurvePublicKey.from_encoded_point( - ec.SECP256R1(), unhexlify(public_key_numbers) -- ).public_key(default_backend()) -+ ) - return -- obj.Q_C = ec.EllipticCurvePublicNumbers.from_encoded_point( -+ obj.Q_C = ec.EllipticCurvePublicKey.from_encoded_point( - ec.SECP256R1(), unhexlify(public_key_numbers) -- ).public_key(default_backend()) -+ ) - - - class FakeKey(object): diff --git a/paramiko-2.4.2.tar.gz b/paramiko-2.4.2.tar.gz deleted file mode 100644 index 63087df..0000000 --- a/paramiko-2.4.2.tar.gz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a8975a7df3560c9f1e2b43dc54ebd40fd00a7017392ca5445ce7df409f900fcb -size 1207299 diff --git a/paramiko-2.5.0.tar.gz b/paramiko-2.5.0.tar.gz new file mode 100644 index 0000000..ca48a23 --- /dev/null +++ b/paramiko-2.5.0.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9f081281064b5180dc0ef60e256224a280ff16f603a99f3dd4ba6334ebb65f7e +size 1224952 diff --git a/paramiko-test_extend_timeout.patch b/paramiko-test_extend_timeout.patch index 47b0b8e..c76e45c 100644 --- a/paramiko-test_extend_timeout.patch +++ b/paramiko-test_extend_timeout.patch @@ -1,8 +1,8 @@ -Index: paramiko-2.4.2/tests/test_buffered_pipe.py +Index: paramiko-2.5.0/tests/test_buffered_pipe.py =================================================================== ---- paramiko-2.4.2.orig/tests/test_buffered_pipe.py -+++ paramiko-2.4.2/tests/test_buffered_pipe.py -@@ -69,7 +69,7 @@ class BufferedPipeTest(unittest.TestCase +--- paramiko-2.5.0.orig/tests/test_buffered_pipe.py ++++ paramiko-2.5.0/tests/test_buffered_pipe.py +@@ -68,7 +68,7 @@ class BufferedPipeTest(unittest.TestCase self.assertTrue(False) except PipeTimeout: pass @@ -10,4 +10,4 @@ Index: paramiko-2.4.2/tests/test_buffered_pipe.py + self.assertEqual(b"b", p.read(1, 3.0)) self.assertEqual(b"", p.read(1)) - def test_3_close_while_reading(self): + def test_close_while_reading(self): diff --git a/python-paramiko.changes b/python-paramiko.changes index ca0e836..b1bb793 100644 --- a/python-paramiko.changes +++ b/python-paramiko.changes @@ -1,3 +1,19 @@ +------------------------------------------------------------------- +Tue Jun 11 11:22:32 UTC 2019 - Ondřej Súkup + +- update to 2.5.0 +- dropped 1379.patch +- refreshed patches: + paramiko-test_extend_timeout.patch + relaxed.patch + 1311.patch + * Add support for encrypt-then-MAC (ETM) schemes (hmac-sha2-256-etm@openssh.com, + hmac-sha2-512-etm@openssh.com) and two newer Diffie-Hellman group key exchange + algorithms (group14, using SHA256; and group16, using SHA512). + * Add support for Curve25519 key exchange. + * Raise Cryptography dependency requirement to version 2.5 + * Add support for the modern (as of Python 3.3) import location of MutableMapping + ------------------------------------------------------------------- Wed Mar 13 14:01:04 UTC 2019 - Tomáš Chvátal diff --git a/python-paramiko.spec b/python-paramiko.spec index d7d408d..e631beb 100644 --- a/python-paramiko.spec +++ b/python-paramiko.spec @@ -18,7 +18,7 @@ %{?!python_module:%define python_module() python-%{**} python3-%{**}} Name: python-paramiko -Version: 2.4.2 +Version: 2.5.0 Release: 0 Summary: SSH2 protocol library License: LGPL-2.1-or-later @@ -28,7 +28,6 @@ Source: https://files.pythonhosted.org/packages/source/p/paramiko/parami Patch0: paramiko-test_extend_timeout.patch Patch2: relaxed.patch Patch3: 1311.patch -Patch4: 1379.patch BuildRequires: %{python_module PyNaCl >= 1.0.1} BuildRequires: %{python_module bcrypt >= 3.1.3} BuildRequires: %{python_module cryptography >= 2.5} diff --git a/relaxed.patch b/relaxed.patch index 688a92e..128606e 100644 --- a/relaxed.patch +++ b/relaxed.patch @@ -1,5 +1,7 @@ ---- paramiko-2.4.2.orig/tests/test_client.py -+++ paramiko-2.4.2/tests/test_client.py +Index: paramiko-2.5.0/tests/test_client.py +=================================================================== +--- paramiko-2.5.0.orig/tests/test_client.py ++++ paramiko-2.5.0/tests/test_client.py @@ -33,7 +33,7 @@ import warnings import weakref from tempfile import mkstemp @@ -9,7 +11,7 @@ import paramiko from paramiko.pkey import PublicBlob -@@ -662,7 +662,7 @@ class PasswordPassphraseTests(ClientTest): +@@ -662,7 +662,7 @@ class PasswordPassphraseTests(ClientTest # TODO: more granular exception pending #387; should be signaling "no auth # methods available" because no key and no password @@ -18,12 +20,12 @@ def test_passphrase_kwarg_not_used_for_password_auth(self): # Using the "right" password in the "wrong" field shouldn't work. self._test_connection(passphrase="pygmalion") -@@ -683,7 +683,7 @@ class PasswordPassphraseTests(ClientTest): +@@ -683,7 +683,7 @@ class PasswordPassphraseTests(ClientTest password="television", ) - @raises(AuthenticationException) # TODO: more granular + @pytest.mark.xfail(raises=AuthenticationException) # TODO: more granular - def test_password_kwarg_not_used_for_passphrase_when_passphrase_kwarg_given( + def test_password_kwarg_not_used_for_passphrase_when_passphrase_kwarg_given( # noqa self - ): # noqa + ):