diff options
author | Tim Savage <tim@savage.company> | 2016-12-22 19:28:57 +1100 |
---|---|---|
committer | Tim Savage <tim@savage.company> | 2016-12-22 19:28:57 +1100 |
commit | 0fd54bb9813c2a62dcea7351e05ce780127ccdbe (patch) | |
tree | b6b3a38a8c30d3656ca9966e362655f4192e5337 | |
parent | ec3fdd72dba89626635e5ea1c31ac65a31091042 (diff) |
Added a auth_timeout to handle situations where SSH server stops responding during auth.
This is has been observed with certain windows SSH servers.
-rw-r--r-- | paramiko/auth_handler.py | 5 | ||||
-rw-r--r-- | paramiko/client.py | 8 | ||||
-rw-r--r-- | paramiko/transport.py | 2 |
3 files changed, 12 insertions, 3 deletions
diff --git a/paramiko/auth_handler.py b/paramiko/auth_handler.py index 38b23729..7a09d8a2 100644 --- a/paramiko/auth_handler.py +++ b/paramiko/auth_handler.py @@ -21,6 +21,7 @@ """ import weakref +import time from paramiko.common import cMSG_SERVICE_REQUEST, cMSG_DISCONNECT, \ DISCONNECT_SERVICE_NOT_AVAILABLE, DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE, \ cMSG_USERAUTH_REQUEST, cMSG_SERVICE_ACCEPT, DEBUG, AUTH_SUCCESSFUL, INFO, \ @@ -188,6 +189,7 @@ class AuthHandler (object): return m.asbytes() def wait_for_response(self, event): + max_ts = time.time() + self.transport.auth_timeout if self.transport.auth_timeout is not None else None while True: event.wait(0.1) if not self.transport.is_active(): @@ -197,6 +199,9 @@ class AuthHandler (object): raise e if event.is_set(): break + elif max_ts is not None and max_ts >= time.time(): + raise AuthenticationException('Authentication timeout.') + if not self.is_authenticated(): e = self.transport.get_exception() if e is None: diff --git a/paramiko/client.py b/paramiko/client.py index a2c02c51..9dc1029e 100644 --- a/paramiko/client.py +++ b/paramiko/client.py @@ -226,7 +226,8 @@ class SSHClient (ClosingContextManager): gss_kex=False, gss_deleg_creds=True, gss_host=None, - banner_timeout=None + banner_timeout=None, + auth_timeout=None ): """ Connect to an SSH server and authenticate to it. The server's host key @@ -278,7 +279,8 @@ class SSHClient (ClosingContextManager): The targets name in the kerberos database. default: hostname :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 + an authentication response. :raises BadHostKeyException: if the server's host key could not be verified :raises AuthenticationException: if authentication failed @@ -335,6 +337,8 @@ class SSHClient (ClosingContextManager): t.set_log_channel(self._log_channel) if banner_timeout is not None: t.banner_timeout = banner_timeout + if auth_timeout is not None: + t.auth_timeout = auth_timeout t.start_client(timeout=timeout) ResourceManager.register(self, t) diff --git a/paramiko/transport.py b/paramiko/transport.py index 7906c9f2..22f81dd6 100644 --- a/paramiko/transport.py +++ b/paramiko/transport.py @@ -383,7 +383,7 @@ class Transport (threading.Thread, ClosingContextManager): self.completion_event = None # user-defined event callbacks self.banner_timeout = 15 # how long (seconds) to wait for the SSH banner self.handshake_timeout = 15 # how long (seconds) to wait for the handshake to finish after SSH banner sent. - + self.auth_timeout = 15 # how long (seconds) to wait for the auth response. # server mode: self.server_mode = False |