summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnselm Kruis <a.kruis@science-computing.de>2017-08-05 14:24:10 +0200
committersdeiss@science-computing.de <sdeiss@science-computing.de>2017-09-13 14:53:27 +0200
commitad5c0d17fffd6b365a5477d2b884d3207879d8b8 (patch)
tree359c500d90290179a9ce233a882d8feac9580ccb
parentc4aed573db0392ec35f1dbe3d4ba6aa0b25f8815 (diff)
downloadparamiko-ad5c0d17fffd6b365a5477d2b884d3207879d8b8.tar.gz
Invent the parameter 'gss_trust_dns' for Kerberos support
In response to Paramiko issue #915 the parameter 'gss_trust_dns' was added for Kerberos support. Set by default to 'True' the parameter indicates whether or not the DNS is trusted to securely canonicalize the hostname of the target host. If set to 'False' the hostname entered will be passed to GSSAPI. This option behaves like GSSAPITrustDNS from OpenSSH. Also, the parameter 'gss_host' is now always set, regardless if GSSAPI is used or not. Further, a minor fix was required to make the SFTP test work again.
-rw-r--r--demos/demo_simple.py2
-rw-r--r--paramiko/client.py20
-rw-r--r--paramiko/transport.py25
3 files changed, 32 insertions, 15 deletions
diff --git a/demos/demo_simple.py b/demos/demo_simple.py
index 7ae3d8c8..9def57f8 100644
--- a/demos/demo_simple.py
+++ b/demos/demo_simple.py
@@ -79,8 +79,6 @@ try:
if not UseGSSAPI and not DoGSSAPIKeyExchange:
client.connect(hostname, port, username, password)
else:
- # SSPI works only with the FQDN of the target host
- hostname = socket.getfqdn(hostname)
try:
client.connect(hostname, port, username, gss_auth=UseGSSAPI,
gss_kex=DoGSSAPIKeyExchange)
diff --git a/paramiko/client.py b/paramiko/client.py
index 34491230..a9677b05 100644
--- a/paramiko/client.py
+++ b/paramiko/client.py
@@ -228,6 +228,7 @@ class SSHClient (ClosingContextManager):
gss_host=None,
banner_timeout=None,
auth_timeout=None,
+ gss_trust_dns=True
):
"""
Connect to an SSH server and authenticate to it. The server's host key
@@ -277,6 +278,9 @@ class SSHClient (ClosingContextManager):
:param bool gss_deleg_creds: Delegate GSS-API client credentials or not
:param str gss_host:
The targets name in the kerberos database. default: hostname
+ :param bool gss_trust_dns: Indicates whether or not the DNS is trusted to
+ securely canonicalize the name of the host being
+ connected to (default ``True``).
:param float banner_timeout: an optional timeout (in seconds) to wait
for the SSH banner to be presented.
:param float auth_timeout: an optional timeout (in seconds) to wait for
@@ -331,12 +335,11 @@ class SSHClient (ClosingContextManager):
t = self._transport = Transport(
sock, gss_kex=gss_kex, gss_deleg_creds=gss_deleg_creds)
t.use_compression(compress=compress)
- if gss_kex and gss_host is None:
- t.set_gss_host(hostname)
- elif gss_kex and gss_host is not None:
- t.set_gss_host(gss_host)
- else:
- pass
+ if gss_host is None:
+ t.set_gss_host(hostname, gss_trust_dns)
+ elif gss_host is not None:
+ # Don't canonicalize gss_host
+ t.set_gss_host(gss_host, False)
if self._log_channel is not None:
t.set_log_channel(self._log_channel)
if banner_timeout is not None:
@@ -387,10 +390,9 @@ class SSHClient (ClosingContextManager):
key_filenames = [key_filename]
else:
key_filenames = key_filename
- if gss_host is None:
- gss_host = hostname
+
self._auth(username, password, pkey, key_filenames, allow_agent,
- look_for_keys, gss_auth, gss_kex, gss_deleg_creds, gss_host)
+ look_for_keys, gss_auth, gss_kex, gss_deleg_creds, t.gss_host)
def close(self):
"""
diff --git a/paramiko/transport.py b/paramiko/transport.py
index 55c0fa62..8131daa1 100644
--- a/paramiko/transport.py
+++ b/paramiko/transport.py
@@ -292,10 +292,12 @@ class Transport(threading.Thread, ClosingContextManager):
arguments.
"""
self.active = False
+ self.hostname = None
if isinstance(sock, string_types):
# convert "host:port" into (host, port)
hl = sock.split(':', 1)
+ self.hostname = hl[0]
if len(hl) == 1:
sock = (hl[0], 22)
else:
@@ -303,6 +305,7 @@ class Transport(threading.Thread, ClosingContextManager):
if type(sock) is tuple:
# connect to the given (host, port)
hostname, port = sock
+ self.hostname = hostname
reason = 'No suitable address family'
addrinfos = socket.getaddrinfo(
hostname, port, socket.AF_UNSPEC, socket.SOCK_STREAM
@@ -446,15 +449,20 @@ class Transport(threading.Thread, ClosingContextManager):
"""
return SecurityOptions(self)
- def set_gss_host(self, gss_host):
+ def set_gss_host(self, gss_host, dns_lookup=True):
"""
Setter for C{gss_host} if GSS-API Key Exchange is performed.
:param str gss_host: The targets name in the kerberos database
Default: The name of the host to connect to
+ :param bool dns_lookup: Indicates whether or not ``gss_host`` should be
+ canonicalized (default ``True``).
+ :rtype: Void
"""
- # We need the FQDN to get this working with SSPI
- self.gss_host = socket.getfqdn(gss_host)
+ if dns_lookup:
+ self.gss_host = socket.getfqdn(gss_host)
+ else:
+ self.gss_host = gss_host
def start_client(self, event=None, timeout=None):
"""
@@ -1075,6 +1083,7 @@ class Transport(threading.Thread, ClosingContextManager):
gss_auth=False,
gss_kex=False,
gss_deleg_creds=True,
+ gss_trust_dns=True,
):
"""
Negotiate an SSH2 session, and optionally verify the server's host key
@@ -1113,6 +1122,9 @@ class Transport(threading.Thread, ClosingContextManager):
Perform GSS-API Key Exchange and user authentication.
:param bool gss_deleg_creds:
Whether to delegate GSS-API client credentials.
+ :param gss_trust_dns: Indicates whether or not the DNS is trusted to
+ securely canonicalize the name of the host being
+ connected to (default ``True``).
:raises: `.SSHException` -- if the SSH2 negotiation fails, the host key
supplied by the server is incorrect, or authentication fails.
@@ -1120,6 +1132,11 @@ class Transport(threading.Thread, ClosingContextManager):
if hostkey is not None:
self._preferred_keys = [hostkey.get_name()]
+ if gss_host is not None:
+ self.set_gss_host(gss_host, False)
+ elif self.hostname is not None:
+ self.set_gss_host(self.hostname, gss_trust_dns)
+
self.start_client()
# check host key if we were given one
@@ -1144,7 +1161,7 @@ class Transport(threading.Thread, ClosingContextManager):
if (pkey is not None) or (password is not None) or gss_auth or gss_kex:
if gss_auth:
self._log(DEBUG, 'Attempting GSS-API auth... (gssapi-with-mic)') # noqa
- self.auth_gssapi_with_mic(username, gss_host, gss_deleg_creds)
+ self.auth_gssapi_with_mic(username, self.gss_host, gss_deleg_creds)
elif gss_kex:
self._log(DEBUG, 'Attempting GSS-API auth... (gssapi-keyex)')
self.auth_gssapi_keyex(username)