diff -Nru paramiko-2.0.0/debian/changelog paramiko-2.0.0/debian/changelog --- paramiko-2.0.0/debian/changelog 2016-06-09 04:07:55.000000000 +0000 +++ paramiko-2.0.0/debian/changelog 2018-03-16 22:44:26.000000000 +0000 @@ -1,3 +1,25 @@ +paramiko (2.0.0-1ubuntu0.1) artful-security; urgency=medium + + [Steve Beattie] + * SECURITY UPDATE: customized clients can skip auth + - 0004-Fixes-CVE-2018-7750-1175.patch: send message failure if not + authenticated and message type is a service request + - 0002-Allow-overriding-test-client-connect-kwargs-in-Trans.patch, + 0003-Initial-tests-proving-CVE-2018-7750-1175.patch: + add testcases plus prereq + - CVE-2018-7750 + + [ Fabien Tassin ] + * SECURITY UPDATE: weak diffie-hellman-group1-sha1 kex always preferred (LP: #1728607) + - 0010-git-c1233679c44-change-order-of-preferred-kex-and-hmac-algorithms.patch + - 0011-git-b395444062e-Reorder-cipher-and-key-preferences-to-make-more-sense.patch + Backport of the upstream changes from 2.3.1, matching the OpenSSH 7 + deprecation of diffie-hellman-group1-sha1 (http://www.openssh.com/legacy.html). + This patch doesn't remove the support of diffie-hellman-group1-sha1 but + makes it the least preferred kex for backward compatibility + + -- Steve Beattie Fri, 16 Mar 2018 15:44:26 -0700 + paramiko (2.0.0-1) unstable; urgency=medium * Imported Upstream version 2.0.0 (Closes: #826737) diff -Nru paramiko-2.0.0/debian/control paramiko-2.0.0/debian/control --- paramiko-2.0.0/debian/control 2016-06-09 03:46:16.000000000 +0000 +++ paramiko-2.0.0/debian/control 2018-03-16 22:44:26.000000000 +0000 @@ -1,7 +1,8 @@ Source: paramiko Section: python Priority: optional -Maintainer: Jeremy T. Bouse +Maintainer: Ubuntu Developers +XSBC-Original-Maintainer: Jeremy T. Bouse Uploaders: Guido Guenther X-Python-Version: >= 2.6 X-Python3-Version: >= 3.2 diff -Nru paramiko-2.0.0/debian/patches/0002-Allow-overriding-test-client-connect-kwargs-in-Trans.patch paramiko-2.0.0/debian/patches/0002-Allow-overriding-test-client-connect-kwargs-in-Trans.patch --- paramiko-2.0.0/debian/patches/0002-Allow-overriding-test-client-connect-kwargs-in-Trans.patch 1970-01-01 00:00:00.000000000 +0000 +++ paramiko-2.0.0/debian/patches/0002-Allow-overriding-test-client-connect-kwargs-in-Trans.patch 2018-03-16 22:41:37.000000000 +0000 @@ -0,0 +1,44 @@ +From 91b9249616cd0147944ff93fb2d508fac1e30524 Mon Sep 17 00:00:00 2001 +From: Jeff Forcier +Date: Mon, 12 Mar 2018 09:15:55 -0700 +Subject: [PATCH 12/13] Allow overriding test client connect kwargs in + Transport test suite + +--- + tests/test_transport.py | 13 ++++++++++--- + 1 file changed, 10 insertions(+), 3 deletions(-) + +diff --git a/tests/test_transport.py b/tests/test_transport.py +index 3e35291..a61cc7a 100644 +--- a/tests/test_transport.py ++++ b/tests/test_transport.py +@@ -129,7 +129,9 @@ class TransportTest(unittest.TestCase): + self.socks.close() + self.sockc.close() + +- def setup_test_server(self, client_options=None, server_options=None): ++ def setup_test_server( ++ self, client_options=None, server_options=None, connect_kwargs=None, ++ ): + host_key = RSAKey.from_private_key_file(test_path('test_rsa.key')) + public_host_key = RSAKey(data=host_key.asbytes()) + self.ts.add_server_key(host_key) +@@ -143,8 +145,13 @@ class TransportTest(unittest.TestCase): + self.server = NullServer() + self.assertTrue(not event.is_set()) + self.ts.start_server(event, self.server) +- self.tc.connect(hostkey=public_host_key, +- username='slowdive', password='pygmalion') ++ if connect_kwargs is None: ++ connect_kwargs = dict( ++ hostkey=public_host_key, ++ username='slowdive', ++ password='pygmalion', ++ ) ++ self.tc.connect(**connect_kwargs) + event.wait(1.0) + self.assertTrue(event.is_set()) + self.assertTrue(self.ts.is_active()) +-- +2.7.4 + diff -Nru paramiko-2.0.0/debian/patches/0003-Initial-tests-proving-CVE-2018-7750-1175.patch paramiko-2.0.0/debian/patches/0003-Initial-tests-proving-CVE-2018-7750-1175.patch --- paramiko-2.0.0/debian/patches/0003-Initial-tests-proving-CVE-2018-7750-1175.patch 1970-01-01 00:00:00.000000000 +0000 +++ paramiko-2.0.0/debian/patches/0003-Initial-tests-proving-CVE-2018-7750-1175.patch 2018-03-16 22:44:17.000000000 +0000 @@ -0,0 +1,76 @@ +From afd38eea1a1c76e05109d71cf79704133a4a8ff4 Mon Sep 17 00:00:00 2001 +From: Jeff Forcier +Date: Mon, 12 Mar 2018 09:17:43 -0700 +Subject: [PATCH] Initial tests proving CVE-2018-7750 / #1175 + +--- + tests/test_transport.py | 42 ++++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 40 insertions(+), 2 deletions(-) + +diff --git a/tests/test_transport.py b/tests/test_transport.py +index 778fed4..6e3fd24 100644 +--- a/tests/test_transport.py ++++ b/tests/test_transport.py +@@ -32,7 +32,7 @@ from hashlib import sha1 + import unittest + + from paramiko import Transport, SecurityOptions, ServerInterface, RSAKey, DSSKey, \ +- SSHException, ChannelException, Packetizer ++ SSHException, ChannelException, Packetizer, Channel + from paramiko import AUTH_FAILED, AUTH_SUCCESSFUL + from paramiko import OPEN_SUCCEEDED, OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED + from paramiko.common import MSG_KEXINIT, cMSG_CHANNEL_WINDOW_ADJUST, \ +@@ -88,7 +88,11 @@ class NullServer (ServerInterface): + + def check_global_request(self, kind, msg): + self._global_request = kind +- return False ++ # NOTE: for w/e reason, older impl of this returned False always, even ++ # tho that's only supposed to occur if the request cannot be served. ++ # For now, leaving that the default unless test supplies specific ++ # 'acceptable' request kind ++ return kind == 'acceptable' + + def check_channel_x11_request(self, channel, single_connection, auth_protocol, auth_cookie, screen_number): + self._x11_single_connection = single_connection +@@ -922,3 +926,37 @@ class TransportTest(unittest.TestCase): + hostkey=public_host_key, + username='slowdive', + password='pygmalion') ++ ++ def test_server_rejects_open_channel_without_auth(self): ++ try: ++ self.setup_test_server(connect_kwargs={}) ++ self.tc.open_session() ++ except ChannelException as e: ++ assert e.code == OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED ++ else: ++ assert False, "Did not raise ChannelException!" ++ ++ def test_server_rejects_arbitrary_global_request_without_auth(self): ++ self.setup_test_server(connect_kwargs={}) ++ # NOTE: this dummy global request kind would normally pass muster ++ # from the test server. ++ self.tc.global_request('acceptable') ++ # Global requests never raise exceptions, even on failure (not sure why ++ # this was the original design...ugh.) Best we can do to tell failure ++ # happened is that the client transport's global_response was set back ++ # to None; if it had succeeded, it would be the response Message. ++ err = "Unauthed global response incorrectly succeeded!" ++ assert self.tc.global_response is None, err ++ ++ def test_server_rejects_port_forward_without_auth(self): ++ # NOTE: at protocol level port forward requests are treated same as a ++ # regular global request, but Paramiko server implements a special-case ++ # method for it, so it gets its own test. (plus, THAT actually raises ++ # an exception on the client side, unlike the general case...) ++ self.setup_test_server(connect_kwargs={}) ++ try: ++ self.tc.request_port_forward('localhost', 1234) ++ except SSHException as e: ++ assert "forwarding request denied" in str(e) ++ else: ++ assert False, "Did not raise SSHException!" +-- +2.7.4 + diff -Nru paramiko-2.0.0/debian/patches/0004-Fixes-CVE-2018-7750-1175.patch paramiko-2.0.0/debian/patches/0004-Fixes-CVE-2018-7750-1175.patch --- paramiko-2.0.0/debian/patches/0004-Fixes-CVE-2018-7750-1175.patch 1970-01-01 00:00:00.000000000 +0000 +++ paramiko-2.0.0/debian/patches/0004-Fixes-CVE-2018-7750-1175.patch 2018-03-16 22:44:26.000000000 +0000 @@ -0,0 +1,97 @@ +From fa29bd8446c8eab237f5187d28787727b4610516 Mon Sep 17 00:00:00 2001 +From: Jeff Forcier +Date: Mon, 12 Mar 2018 15:34:06 -0700 +Subject: [PATCH] Fixes CVE-2018-7750 / #1175 + +At least, insofar as the new tests pass...! +--- + paramiko/common.py | 1 + + paramiko/transport.py | 45 +++++++++++++++++++++++++++++++++++++++++++-- + 2 files changed, 44 insertions(+), 2 deletions(-) + +diff --git a/paramiko/common.py b/paramiko/common.py +index 0012372..11c4121 100644 +--- a/paramiko/common.py ++++ b/paramiko/common.py +@@ -32,6 +32,7 @@ MSG_USERAUTH_INFO_REQUEST, MSG_USERAUTH_INFO_RESPONSE = range(60, 62) + MSG_USERAUTH_GSSAPI_RESPONSE, MSG_USERAUTH_GSSAPI_TOKEN = range(60, 62) + MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, MSG_USERAUTH_GSSAPI_ERROR,\ + MSG_USERAUTH_GSSAPI_ERRTOK, MSG_USERAUTH_GSSAPI_MIC = range(63, 67) ++HIGHEST_USERAUTH_MESSAGE_ID = 79 + MSG_GLOBAL_REQUEST, MSG_REQUEST_SUCCESS, MSG_REQUEST_FAILURE = range(80, 83) + MSG_CHANNEL_OPEN, MSG_CHANNEL_OPEN_SUCCESS, MSG_CHANNEL_OPEN_FAILURE, \ + MSG_CHANNEL_WINDOW_ADJUST, MSG_CHANNEL_DATA, MSG_CHANNEL_EXTENDED_DATA, \ +diff --git a/paramiko/transport.py b/paramiko/transport.py +index 711f395..3ec3f0b 100644 +--- a/paramiko/transport.py ++++ b/paramiko/transport.py +@@ -49,7 +49,8 @@ from paramiko.common import ( + MSG_CHANNEL_SUCCESS, MSG_CHANNEL_FAILURE, MSG_CHANNEL_DATA, \ + MSG_CHANNEL_EXTENDED_DATA, MSG_CHANNEL_WINDOW_ADJUST, MSG_CHANNEL_REQUEST, \ + MSG_CHANNEL_EOF, MSG_CHANNEL_CLOSE, MIN_WINDOW_SIZE, MIN_PACKET_SIZE, \ +- MAX_WINDOW_SIZE, DEFAULT_WINDOW_SIZE, DEFAULT_MAX_PACKET_SIZE ++ MAX_WINDOW_SIZE, DEFAULT_WINDOW_SIZE, DEFAULT_MAX_PACKET_SIZE, \ ++ HIGHEST_USERAUTH_MESSAGE_ID + from paramiko.compress import ZlibCompressor, ZlibDecompressor + from paramiko.dsskey import DSSKey + from paramiko.kex_gex import KexGex, KexGexSHA256 +@@ -1760,6 +1760,43 @@ class Transport(threading.Thread, ClosingContextManager): + max_packet_size = self.default_max_packet_size + return clamp_value(MIN_PACKET_SIZE, max_packet_size, MAX_WINDOW_SIZE) + ++ def _ensure_authed(self, ptype, message): ++ """ ++ Checks message type against current auth state. ++ ++ If server mode, and auth has not succeeded, and the message is of a ++ post-auth type (channel open or global request) an appropriate error ++ response Message is crafted and returned to caller for sending. ++ ++ Otherwise (client mode, authed, or pre-auth message) returns None. ++ """ ++ if ( ++ not self.server_mode ++ or ptype <= HIGHEST_USERAUTH_MESSAGE_ID ++ or self.is_authenticated() ++ ): ++ return None ++ # WELP. We must be dealing with someone trying to do non-auth things ++ # without being authed. Tell them off, based on message class. ++ reply = Message() ++ # Global requests have no details, just failure. ++ if ptype == MSG_GLOBAL_REQUEST: ++ reply.add_byte(cMSG_REQUEST_FAILURE) ++ # Channel opens let us reject w/ a specific type + message. ++ elif ptype == MSG_CHANNEL_OPEN: ++ kind = message.get_text() ++ chanid = message.get_int() ++ reply.add_byte(cMSG_CHANNEL_OPEN_FAILURE) ++ reply.add_int(chanid) ++ reply.add_int(OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED) ++ reply.add_string('') ++ reply.add_string('en') ++ # NOTE: Post-open channel messages do not need checking; the above will ++ # reject attemps to open channels, meaning that even if a malicious ++ # user tries to send a MSG_CHANNEL_REQUEST, it will simply fall under ++ # the logic that handles unknown channel IDs (as the channel list will ++ # be empty.) ++ return reply + + def run(self): + # (use the exposed "run" method, because if we specify a thread target +@@ -1820,7 +1857,11 @@ class Transport(threading.Thread, ClosingContextManager): + continue + + if ptype in self._handler_table: +- self._handler_table[ptype](self, m) ++ error_msg = self._ensure_authed(ptype, m) ++ if error_msg: ++ self._send_message(error_msg) ++ else: ++ self._handler_table[ptype](self, m) + elif ptype in self._channel_handler_table: + chanid = m.get_int() + chan = self._channels.get(chanid) +-- +2.7.4 + diff -Nru paramiko-2.0.0/debian/patches/0010-git-c1233679c44-change-order-of-preferred-kex-and-hmac-algorithms.patch paramiko-2.0.0/debian/patches/0010-git-c1233679c44-change-order-of-preferred-kex-and-hmac-algorithms.patch --- paramiko-2.0.0/debian/patches/0010-git-c1233679c44-change-order-of-preferred-kex-and-hmac-algorithms.patch 1970-01-01 00:00:00.000000000 +0000 +++ paramiko-2.0.0/debian/patches/0010-git-c1233679c44-change-order-of-preferred-kex-and-hmac-algorithms.patch 2018-03-16 22:44:26.000000000 +0000 @@ -0,0 +1,40 @@ +commit c1233679c448b445ec991710d259eec0a9f64b61 +Author: Fabien Tassin +Subject: transport: change order of preferred kex and hmac algorithms + +Bug: https://bugs.launchpad.net/ubuntu/+source/paramiko/+bug/1728607 + +Backport from https://github.com/paramiko/paramiko/commit/c1233679c448b445ec991710d259eec0a9f64b61 +--- + paramiko/transport.py | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +Index: b/paramiko/transport.py +=================================================================== +--- a/paramiko/transport.py ++++ b/paramiko/transport.py +@@ -114,20 +114,20 @@ class Transport (threading.Thread, Closi + _preferred_macs = ( + 'hmac-sha2-256', + 'hmac-sha2-512', ++ 'hmac-sha1', + 'hmac-md5', + 'hmac-sha1-96', + 'hmac-md5-96', +- 'hmac-sha1', + ) + _preferred_keys = ( + 'ssh-rsa', + 'ssh-dss', + ) + tuple(ECDSAKey.supported_key_format_identifiers()) + _preferred_kex = ( +- 'diffie-hellman-group1-sha1', +- 'diffie-hellman-group14-sha1', +- 'diffie-hellman-group-exchange-sha1', + 'diffie-hellman-group-exchange-sha256', ++ 'diffie-hellman-group-exchange-sha1', ++ 'diffie-hellman-group14-sha1', ++ 'diffie-hellman-group1-sha1', + ) + _preferred_compression = ('none',) + diff -Nru paramiko-2.0.0/debian/patches/0011-git-b395444062e-Reorder-cipher-and-key-preferences-to-make-more-sense.patch paramiko-2.0.0/debian/patches/0011-git-b395444062e-Reorder-cipher-and-key-preferences-to-make-more-sense.patch --- paramiko-2.0.0/debian/patches/0011-git-b395444062e-Reorder-cipher-and-key-preferences-to-make-more-sense.patch 1970-01-01 00:00:00.000000000 +0000 +++ paramiko-2.0.0/debian/patches/0011-git-b395444062e-Reorder-cipher-and-key-preferences-to-make-more-sense.patch 2018-03-16 22:44:26.000000000 +0000 @@ -0,0 +1,25 @@ +commit b395444062e82953d417a4da9157667c2e05d758 +Author: Fabien Tassin +Subject: Reorder cipher and key preferences to make more sense + +Bug: https://bugs.launchpad.net/ubuntu/+source/paramiko/+bug/1728607 + +[Patch differs from upstream in that paramiko 1.16 does not support +ssh-ed25519, so not changing the key algorithm priority -- sbeattie] + +Backport from https://github.com/paramiko/paramiko/commit/b395444062e82953d417a4da9157667c2e05d758 +Index: paramiko-1.16.0/paramiko/transport.py +=================================================================== +--- paramiko-1.16.0.orig/paramiko/transport.py ++++ paramiko-1.16.0/paramiko/transport.py +@@ -102,9 +102,9 @@ class Transport (threading.Thread, Closi + 'aes192-ctr', + 'aes256-ctr', + 'aes128-cbc', +- 'blowfish-cbc', + 'aes192-cbc', + 'aes256-cbc', ++ 'blowfish-cbc', + '3des-cbc', + 'arcfour128', + 'arcfour256', diff -Nru paramiko-2.0.0/debian/patches/series paramiko-2.0.0/debian/patches/series --- paramiko-2.0.0/debian/patches/series 2016-06-07 06:05:17.000000000 +0000 +++ paramiko-2.0.0/debian/patches/series 2018-03-16 22:44:26.000000000 +0000 @@ -1 +1,6 @@ 0001-Localize-generated-documentation.patch +0002-Allow-overriding-test-client-connect-kwargs-in-Trans.patch +0003-Initial-tests-proving-CVE-2018-7750-1175.patch +0004-Fixes-CVE-2018-7750-1175.patch +0010-git-c1233679c44-change-order-of-preferred-kex-and-hmac-algorithms.patch +0011-git-b395444062e-Reorder-cipher-and-key-preferences-to-make-more-sense.patch