new parent exception for all auth failures, and new specific exception for bad host key
This commit is contained in:
parent
02e8178510
commit
8843feb633
|
@ -60,8 +60,8 @@ if sys.version_info < (2, 2):
|
|||
|
||||
__author__ = "Robey Pointer <robey@lag.net>"
|
||||
__date__ = "11 Mar 2005"
|
||||
__version__ = "1.5.4 (tentacool)"
|
||||
__version_info__ = (1, 5, 4)
|
||||
__version__ = "1.6 (u?)"
|
||||
__version_info__ = (1, 6, 0)
|
||||
__license__ = "GNU Lesser General Public License (LGPL)"
|
||||
|
||||
|
||||
|
@ -69,7 +69,9 @@ from transport import randpool, SecurityOptions, Transport
|
|||
from client import SSHClient, MissingHostKeyPolicy, AutoAddPolicy, RejectPolicy
|
||||
from auth_handler import AuthHandler
|
||||
from channel import Channel, ChannelFile
|
||||
from ssh_exception import SSHException, PasswordRequiredException, BadAuthenticationType, ChannelException
|
||||
from ssh_exception import SSHException, PasswordRequiredException, \
|
||||
BadAuthenticationType, ChannelException, BadHostKeyException, \
|
||||
AuthenticationException
|
||||
from server import ServerInterface, SubsystemHandler, InteractiveQuery
|
||||
from rsakey import RSAKey
|
||||
from dsskey import DSSKey
|
||||
|
@ -96,7 +98,7 @@ for x in (Transport, SecurityOptions, Channel, SFTPServer, SSHException,
|
|||
SFTPHandle, SFTPServerInterface, BufferedFile, Agent, AgentKey,
|
||||
PKey, BaseSFTP, SFTPFile, ServerInterface, HostKeys, SSHClient,
|
||||
MissingHostKeyPolicy, AutoAddPolicy, RejectPolicy, ChannelException,
|
||||
SSHConfig):
|
||||
SSHConfig, BadHostKeyException, AuthenticationException):
|
||||
x.__module__ = 'paramiko'
|
||||
|
||||
from common import AUTH_SUCCESSFUL, AUTH_PARTIALLY_SUCCESSFUL, AUTH_FAILED, \
|
||||
|
@ -119,9 +121,11 @@ __all__ = [ 'Transport',
|
|||
'Agent',
|
||||
'Message',
|
||||
'SSHException',
|
||||
'AuthenticationException',
|
||||
'PasswordRequiredException',
|
||||
'BadAuthenticationType',
|
||||
'ChannelException',
|
||||
'BadHostKeyException',
|
||||
'SFTP',
|
||||
'SFTPFile',
|
||||
'SFTPHandle',
|
||||
|
|
|
@ -29,7 +29,8 @@ import encodings.utf_8
|
|||
from paramiko.common import *
|
||||
from paramiko import util
|
||||
from paramiko.message import Message
|
||||
from paramiko.ssh_exception import SSHException, BadAuthenticationType, PartialAuthentication
|
||||
from paramiko.ssh_exception import SSHException, AuthenticationException, \
|
||||
BadAuthenticationType, PartialAuthentication
|
||||
from paramiko.server import InteractiveQuery
|
||||
|
||||
|
||||
|
@ -158,14 +159,14 @@ class AuthHandler (object):
|
|||
if not self.transport.is_active():
|
||||
e = self.transport.get_exception()
|
||||
if e is None:
|
||||
e = SSHException('Authentication failed.')
|
||||
e = AuthenticationException('Authentication failed.')
|
||||
raise e
|
||||
if event.isSet():
|
||||
break
|
||||
if not self.is_authenticated():
|
||||
e = self.transport.get_exception()
|
||||
if e is None:
|
||||
e = SSHException('Authentication failed.')
|
||||
e = AuthenticationException('Authentication failed.')
|
||||
# this is horrible. python Exception isn't yet descended from
|
||||
# object, so type(e) won't work. :(
|
||||
if issubclass(e.__class__, PartialAuthentication):
|
||||
|
@ -410,4 +411,3 @@ class AuthHandler (object):
|
|||
MSG_USERAUTH_INFO_RESPONSE: _parse_userauth_info_response,
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -186,7 +186,7 @@ class SSHClient (object):
|
|||
"""
|
||||
return self._host_keys
|
||||
|
||||
def set_log_channel(self, channel):
|
||||
def set_log_channel(self, name):
|
||||
"""
|
||||
Set the channel for logging. The default is C{"paramiko.transport"}
|
||||
but it can be set to anything you want.
|
||||
|
@ -194,7 +194,7 @@ class SSHClient (object):
|
|||
@param name: new channel name for logging
|
||||
@type name: str
|
||||
"""
|
||||
self._log_channel = channel
|
||||
self._log_channel = name
|
||||
|
||||
def set_missing_host_key_policy(self, policy):
|
||||
"""
|
||||
|
@ -245,8 +245,11 @@ class SSHClient (object):
|
|||
for authentication
|
||||
@type key_filename: str
|
||||
|
||||
@raise SSHException: if there was an error authenticating or verifying
|
||||
the server's host key
|
||||
@raise BadHostKeyException: if the server's host key could not be
|
||||
verified
|
||||
@raise AuthenticationException: if authentication failed
|
||||
@raise SSHException: if there was any other error connecting or
|
||||
establishing an SSH session
|
||||
"""
|
||||
t = self._transport = Transport((hostname, port))
|
||||
if self._log_channel is not None:
|
||||
|
@ -254,7 +257,6 @@ class SSHClient (object):
|
|||
t.start_client()
|
||||
|
||||
server_key = t.get_remote_server_key()
|
||||
server_key_hex = hexify(server_key.get_fingerprint())
|
||||
keytype = server_key.get_name()
|
||||
|
||||
our_server_key = self._system_host_keys.get(hostname, {}).get(keytype, None)
|
||||
|
@ -263,14 +265,11 @@ class SSHClient (object):
|
|||
if our_server_key is None:
|
||||
# will raise exception if the key is rejected; let that fall out
|
||||
self._policy.missing_host_key(self, hostname, server_key)
|
||||
# if this continues, assume the key is ok
|
||||
# if the callback returns, assume the key is ok
|
||||
our_server_key = server_key
|
||||
|
||||
our_server_key_hex = hexify(our_server_key.get_fingerprint())
|
||||
|
||||
if server_key != our_server_key:
|
||||
raise SSHException('Host key for server %s does not match! (%s != %s)' %
|
||||
(hostname, our_server_key_kex, server_key_hex))
|
||||
raise BadHostKeyException(hostname, server_key, our_server_key)
|
||||
|
||||
if username is None:
|
||||
username = getpass.getuser()
|
||||
|
|
|
@ -28,14 +28,25 @@ class SSHException (Exception):
|
|||
pass
|
||||
|
||||
|
||||
class PasswordRequiredException (SSHException):
|
||||
class AuthenticationException (SSHException):
|
||||
"""
|
||||
Exception raised when authentication failed for some reason. It may be
|
||||
possible to retry with different credentials. (Other classes specify more
|
||||
specific reasons.)
|
||||
|
||||
@since: 1.6
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class PasswordRequiredException (AuthenticationException):
|
||||
"""
|
||||
Exception raised when a password is needed to unlock a private key file.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class BadAuthenticationType (SSHException):
|
||||
class BadAuthenticationType (AuthenticationException):
|
||||
"""
|
||||
Exception raised when an authentication type (like password) is used, but
|
||||
the server isn't allowing that type. (It may only allow public-key, for
|
||||
|
@ -58,7 +69,7 @@ class BadAuthenticationType (SSHException):
|
|||
return SSHException.__str__(self) + ' (allowed_types=%r)' % self.allowed_types
|
||||
|
||||
|
||||
class PartialAuthentication (SSHException):
|
||||
class PartialAuthentication (AuthenticationException):
|
||||
"""
|
||||
An internal exception thrown in the case of partial authentication.
|
||||
"""
|
||||
|
@ -73,8 +84,32 @@ class ChannelException (SSHException):
|
|||
"""
|
||||
Exception raised when an attempt to open a new L{Channel} fails.
|
||||
|
||||
@ivar code: the error code returned by the server
|
||||
@type code: int
|
||||
|
||||
@since: 1.6
|
||||
"""
|
||||
def __init__(self, code, text):
|
||||
SSHException.__init__(self, text)
|
||||
self.code = code
|
||||
|
||||
|
||||
class BadHostKeyException (SSHException):
|
||||
"""
|
||||
The host key given by the SSH server did not match what we were expecting.
|
||||
|
||||
@ivar hostname: the hostname of the SSH server
|
||||
@type hostname: str
|
||||
@ivar key: the host key presented by the server
|
||||
@type key: L{PKey}
|
||||
@ivar expected_key: the host key expected
|
||||
@type expected_key: L{PKey}
|
||||
|
||||
@since: 1.6
|
||||
"""
|
||||
def __init__(self, hostname, got_key, expected_key):
|
||||
SSHException.__init__(self, 'Host key for server %s does not match!' % hostname)
|
||||
self.hostname = hostname
|
||||
self.key = got_key
|
||||
self.expected_key = expected_key
|
||||
|
||||
|
|
|
@ -992,8 +992,9 @@ class Transport (threading.Thread):
|
|||
|
||||
@raise BadAuthenticationType: if password authentication isn't
|
||||
allowed by the server for this user (and no event was passed in)
|
||||
@raise SSHException: if the authentication failed (and no event was
|
||||
passed in)
|
||||
@raise AuthenticationException: if the authentication failed (and no
|
||||
event was passed in)
|
||||
@raise SSHException: if there was a network error
|
||||
"""
|
||||
if (not self.active) or (not self.initial_kex_done):
|
||||
# we should never try to send the password unless we're on a secure link
|
||||
|
@ -1056,13 +1057,14 @@ class Transport (threading.Thread):
|
|||
complete (whether it was successful or not)
|
||||
@type event: threading.Event
|
||||
@return: list of auth types permissible for the next stage of
|
||||
authentication (normally empty).
|
||||
authentication (normally empty)
|
||||
@rtype: list
|
||||
|
||||
@raise BadAuthenticationType: if public-key authentication isn't
|
||||
allowed by the server for this user (and no event was passed in).
|
||||
@raise SSHException: if the authentication failed (and no event was
|
||||
passed in).
|
||||
allowed by the server for this user (and no event was passed in)
|
||||
@raise AuthenticationException: if the authentication failed (and no
|
||||
event was passed in)
|
||||
@raise SSHException: if there was a network error
|
||||
"""
|
||||
if (not self.active) or (not self.initial_kex_done):
|
||||
# we should never try to authenticate unless we're on a secure link
|
||||
|
@ -1119,7 +1121,8 @@ class Transport (threading.Thread):
|
|||
|
||||
@raise BadAuthenticationType: if public-key authentication isn't
|
||||
allowed by the server for this user
|
||||
@raise SSHException: if the authentication failed
|
||||
@raise AuthenticationException: if the authentication failed
|
||||
@raise SSHException: if there was a network error
|
||||
|
||||
@since: 1.5
|
||||
"""
|
||||
|
|
|
@ -258,7 +258,7 @@ class TransportTest (unittest.TestCase):
|
|||
self.assert_(False)
|
||||
except:
|
||||
etype, evalue, etb = sys.exc_info()
|
||||
self.assertEquals(SSHException, etype)
|
||||
self.assert_(issubclass(etype, SSHException))
|
||||
self.tc.auth_password(username='slowdive', password='pygmalion')
|
||||
event.wait(1.0)
|
||||
self.assert_(event.isSet())
|
||||
|
|
Loading…
Reference in New Issue