summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--[-rwxr-xr-x]demos/demo_simple.py11
-rw-r--r--paramiko/client.py2
-rw-r--r--paramiko/transport.py12
-rw-r--r--sites/www/changelog.rst6
-rw-r--r--tests/test_client.py61
5 files changed, 81 insertions, 11 deletions
diff --git a/demos/demo_simple.py b/demos/demo_simple.py
index 3a17988c..7ae3d8c8 100755..100644
--- a/demos/demo_simple.py
+++ b/demos/demo_simple.py
@@ -37,8 +37,10 @@ except ImportError:
# setup logging
paramiko.util.log_to_file('demo_simple.log')
# Paramiko client configuration
-UseGSSAPI = True # enable GSS-API / SSPI authentication
-DoGSSAPIKeyExchange = True
+UseGSSAPI = paramiko.GSS_AUTH_AVAILABLE # enable "gssapi-with-mic" authentication, if supported by your python installation
+DoGSSAPIKeyExchange = paramiko.GSS_AUTH_AVAILABLE # enable "gssapi-kex" key exchange, if supported by your python installation
+# UseGSSAPI = False
+# DoGSSAPIKeyExchange = False
port = 22
# get hostname
@@ -64,7 +66,7 @@ if username == '':
username = input('Username [%s]: ' % default_username)
if len(username) == 0:
username = default_username
-if not UseGSSAPI or (not UseGSSAPI and not DoGSSAPIKeyExchange):
+if not UseGSSAPI and not DoGSSAPIKeyExchange:
password = getpass.getpass('Password for %s@%s: ' % (username, hostname))
@@ -74,7 +76,7 @@ try:
client.load_system_host_keys()
client.set_missing_host_key_policy(paramiko.WarningPolicy())
print('*** Connecting...')
- if not UseGSSAPI or (not UseGSSAPI and not DoGSSAPIKeyExchange):
+ if not UseGSSAPI and not DoGSSAPIKeyExchange:
client.connect(hostname, port, username, password)
else:
# SSPI works only with the FQDN of the target host
@@ -83,6 +85,7 @@ try:
client.connect(hostname, port, username, gss_auth=UseGSSAPI,
gss_kex=DoGSSAPIKeyExchange)
except Exception:
+ # traceback.print_exc()
password = getpass.getpass('Password for %s@%s: ' % (username, hostname))
client.connect(hostname, port, username, password)
diff --git a/paramiko/client.py b/paramiko/client.py
index 224109bf..39617d5b 100644
--- a/paramiko/client.py
+++ b/paramiko/client.py
@@ -353,7 +353,7 @@ class SSHClient (ClosingContextManager):
# If GSS-API Key Exchange is performed we are not required to check the
# host key, because the host is authenticated via GSS-API / SSPI as
# well as our client.
- if not self._transport.use_gss_kex:
+ if not self._transport.gss_kex_used:
our_server_key = self._system_host_keys.get(
server_hostkey_name, {}).get(keytype)
if our_server_key is None:
diff --git a/paramiko/transport.py b/paramiko/transport.py
index c68397dd..1ab60841 100644
--- a/paramiko/transport.py
+++ b/paramiko/transport.py
@@ -132,6 +132,11 @@ class Transport(threading.Thread, ClosingContextManager):
'diffie-hellman-group-exchange-sha1',
'diffie-hellman-group-exchange-sha256',
)
+ _preferred_gsskex = (
+ 'gss-gex-sha1-toWM5Slw5Ew8Mqkay+al2g==',
+ 'gss-group14-sha1-toWM5Slw5Ew8Mqkay+al2g==',
+ 'gss-group1-sha1-toWM5Slw5Ew8Mqkay+al2g==',
+ )
_preferred_compression = ('none',)
_cipher_info = {
@@ -333,12 +338,7 @@ class Transport(threading.Thread, ClosingContextManager):
self.gss_host = None
if self.use_gss_kex:
self.kexgss_ctxt = GSSAuth("gssapi-keyex", gss_deleg_creds)
- self._preferred_kex = ('gss-gex-sha1-toWM5Slw5Ew8Mqkay+al2g==',
- 'gss-group14-sha1-toWM5Slw5Ew8Mqkay+al2g==',
- 'gss-group1-sha1-toWM5Slw5Ew8Mqkay+al2g==',
- 'diffie-hellman-group-exchange-sha1',
- 'diffie-hellman-group14-sha1',
- 'diffie-hellman-group1-sha1')
+ self._preferred_kex = self._preferred_gsskex + self._preferred_kex
# state used during negotiation
self.kex_engine = None
diff --git a/sites/www/changelog.rst b/sites/www/changelog.rst
index cb3ddb67..988aedac 100644
--- a/sites/www/changelog.rst
+++ b/sites/www/changelog.rst
@@ -2,6 +2,12 @@
Changelog
=========
+* :bug:`1060` Fix key exchange (kex) algorithm list for GSSAPI authentication;
+ previously, the list used solely out-of-date algorithms, and now contains
+ newer ones listed preferentially before the old. Credit: Anselm Kruis.
+* :bug:`1055` (also :issue:`1056`, :issue:`1057`, :issue:`1058`, :issue:`1059`)
+ Fix up host-key checking in our GSSAPI support, which was previously using an
+ incorrect API call. Thanks to Anselm Kruis for the patches.
* :release:`2.0.6 <2017-06-09>`
* :release:`1.18.3 <2017-06-09>`
* :release:`1.17.5 <2017-06-09>`
diff --git a/tests/test_client.py b/tests/test_client.py
index bfdf5f81..9da6eaca 100644
--- a/tests/test_client.py
+++ b/tests/test_client.py
@@ -141,6 +141,7 @@ class SSHClientTest (unittest.TestCase):
self.assertTrue(self.ts.is_active())
self.assertEqual('slowdive', self.ts.get_username())
self.assertEqual(True, self.ts.is_authenticated())
+ self.assertEqual(False, self.tc.get_transport().gss_kex_used)
# Command execution functions?
stdin, stdout, stderr = self.tc.exec_command('yes')
@@ -366,3 +367,63 @@ class SSHClientTest (unittest.TestCase):
password='pygmalion',
)
self._test_connection(**kwargs)
+
+ def test_9_auth_trickledown_gsskex(self):
+ """
+ Failed gssapi-keyex auth doesn't prevent subsequent key auth from succeeding
+ """
+ if not paramiko.GSS_AUTH_AVAILABLE:
+ return # for python 2.6 lacks skipTest
+ kwargs = dict(
+ gss_kex=True,
+ key_filename=[test_path('test_rsa.key')],
+ )
+ self._test_connection(**kwargs)
+
+ def test_10_auth_trickledown_gssauth(self):
+ """
+ Failed gssapi-with-mic auth doesn't prevent subsequent key auth from succeeding
+ """
+ if not paramiko.GSS_AUTH_AVAILABLE:
+ return # for python 2.6 lacks skipTest
+ kwargs = dict(
+ gss_auth=True,
+ key_filename=[test_path('test_rsa.key')],
+ )
+ self._test_connection(**kwargs)
+
+ def test_11_reject_policy(self):
+ """
+ verify that SSHClient's RejectPolicy works.
+ """
+ threading.Thread(target=self._run).start()
+
+ self.tc = paramiko.SSHClient()
+ self.tc.set_missing_host_key_policy(paramiko.RejectPolicy())
+ self.assertEqual(0, len(self.tc.get_host_keys()))
+ self.assertRaises(
+ paramiko.SSHException,
+ self.tc.connect,
+ password='pygmalion', **self.connect_kwargs
+ )
+
+ def test_12_reject_policy_gsskex(self):
+ """
+ verify that SSHClient's RejectPolicy works,
+ even if gssapi-keyex was enabled but not used.
+ """
+ # Test for a bug present in paramiko versions released before 2017-08-01
+ if not paramiko.GSS_AUTH_AVAILABLE:
+ return # for python 2.6 lacks skipTest
+ threading.Thread(target=self._run).start()
+
+ self.tc = paramiko.SSHClient()
+ self.tc.set_missing_host_key_policy(paramiko.RejectPolicy())
+ self.assertEqual(0, len(self.tc.get_host_keys()))
+ self.assertRaises(
+ paramiko.SSHException,
+ self.tc.connect,
+ password='pygmalion',
+ gss_kex=True,
+ **self.connect_kwargs
+ )