[project @ Arch-1:robey@lag.net--2003-public%secsh--dev--1.0--patch-69]
clean up SecurityOptions the preferences are now tuples in Transport, and passed as tuples out of SecurityOptions, so that the options can't be modified without setting them back to the options field again. the algorithm lists in Transport are used to validate the fields.
This commit is contained in:
parent
aebe186c3e
commit
440b3de06a
|
@ -56,37 +56,61 @@ atexit.register(_join_lingering_threads)
|
||||||
class SecurityOptions (object):
|
class SecurityOptions (object):
|
||||||
"""
|
"""
|
||||||
Simple object containing the security preferences of an ssh transport.
|
Simple object containing the security preferences of an ssh transport.
|
||||||
These are lists of acceptable ciphers, digests, key types, and key
|
These are tuples of acceptable ciphers, digests, key types, and key
|
||||||
exchange algorithms, listed in order of preference.
|
exchange algorithms, listed in order of preference.
|
||||||
|
|
||||||
|
Changing the contents and/or order of these fields affects the underlying
|
||||||
|
L{Transport} (but only if you change them before starting the session).
|
||||||
|
If you try to add an algorithm that paramiko doesn't recognize,
|
||||||
|
C{ValueError} will be raised. If you try to assign something besides a
|
||||||
|
tuple to one of the fields, L{TypeError} will be raised.
|
||||||
"""
|
"""
|
||||||
__slots__ = [ 'ciphers', 'digests', 'key_types', 'kex', '_transport' ]
|
__slots__ = [ 'ciphers', 'digests', 'key_types', 'kex', '_transport' ]
|
||||||
|
|
||||||
def __init__(self, transport):
|
def __init__(self, transport):
|
||||||
self._transport = transport
|
self._transport = transport
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
"""
|
||||||
|
Returns a string representation of this object, for debugging.
|
||||||
|
|
||||||
|
@rtype: string
|
||||||
|
"""
|
||||||
|
return '<paramiko.SecurityOptions for %s>' % repr(self._transport)
|
||||||
|
|
||||||
def _get_ciphers(self):
|
def _get_ciphers(self):
|
||||||
return self._transport._preferred_ciphers
|
return self._transport._preferred_ciphers
|
||||||
|
|
||||||
def _set_ciphers(self, x):
|
|
||||||
self._transport._preferred_ciphers = x
|
|
||||||
|
|
||||||
def _get_digests(self):
|
def _get_digests(self):
|
||||||
return self._transport._preferred_macs
|
return self._transport._preferred_macs
|
||||||
|
|
||||||
def _set_digests(self, x):
|
|
||||||
self._transport._preferred_macs = x
|
|
||||||
|
|
||||||
def _get_key_types(self):
|
def _get_key_types(self):
|
||||||
return self._transport._preferred_keys
|
return self._transport._preferred_keys
|
||||||
|
|
||||||
def _set_key_types(self, x):
|
|
||||||
self._transport._preferred_keys = x
|
|
||||||
|
|
||||||
def _get_kex(self):
|
def _get_kex(self):
|
||||||
return self._transport._preferred_kex
|
return self._transport._preferred_kex
|
||||||
|
|
||||||
|
def _set(self, name, orig, x):
|
||||||
|
if type(x) is list:
|
||||||
|
x = tuple(x)
|
||||||
|
if type(x) is not tuple:
|
||||||
|
raise TypeError('expected tuple or list')
|
||||||
|
possible = getattr(self._transport, orig).keys()
|
||||||
|
if len(filter(lambda n: n not in possible, x)) > 0:
|
||||||
|
raise ValueError('unknown cipher')
|
||||||
|
setattr(self._transport, name, x)
|
||||||
|
|
||||||
|
def _set_ciphers(self, x):
|
||||||
|
self._set('_preferred_ciphers', '_cipher_info', x)
|
||||||
|
|
||||||
|
def _set_digests(self, x):
|
||||||
|
self._set('_preferred_macs', '_mac_info', x)
|
||||||
|
|
||||||
|
def _set_key_types(self, x):
|
||||||
|
self._set('_preferred_keys', '_key_info', x)
|
||||||
|
|
||||||
def _set_kex(self, x):
|
def _set_kex(self, x):
|
||||||
self._transport._preferred_kex = x
|
self._set('_preferred_kex', '_kex_info', x)
|
||||||
|
|
||||||
ciphers = property(_get_ciphers, _set_ciphers, None,
|
ciphers = property(_get_ciphers, _set_ciphers, None,
|
||||||
"Symmetric encryption ciphers")
|
"Symmetric encryption ciphers")
|
||||||
|
@ -106,10 +130,10 @@ class BaseTransport (threading.Thread):
|
||||||
_PROTO_ID = '2.0'
|
_PROTO_ID = '2.0'
|
||||||
_CLIENT_ID = 'pyssh_1.1'
|
_CLIENT_ID = 'pyssh_1.1'
|
||||||
|
|
||||||
_preferred_ciphers = [ 'aes128-cbc', 'blowfish-cbc', 'aes256-cbc', '3des-cbc' ]
|
_preferred_ciphers = ( 'aes128-cbc', 'blowfish-cbc', 'aes256-cbc', '3des-cbc' )
|
||||||
_preferred_macs = [ 'hmac-sha1', 'hmac-md5', 'hmac-sha1-96', 'hmac-md5-96' ]
|
_preferred_macs = ( 'hmac-sha1', 'hmac-md5', 'hmac-sha1-96', 'hmac-md5-96' )
|
||||||
_preferred_keys = [ 'ssh-rsa', 'ssh-dss' ]
|
_preferred_keys = ( 'ssh-rsa', 'ssh-dss' )
|
||||||
_preferred_kex = [ 'diffie-hellman-group1-sha1', 'diffie-hellman-group-exchange-sha1' ]
|
_preferred_kex = ( 'diffie-hellman-group1-sha1', 'diffie-hellman-group-exchange-sha1' )
|
||||||
|
|
||||||
_cipher_info = {
|
_cipher_info = {
|
||||||
'blowfish-cbc': { 'class': Blowfish, 'mode': Blowfish.MODE_CBC, 'block-size': 8, 'key-size': 16 },
|
'blowfish-cbc': { 'class': Blowfish, 'mode': Blowfish.MODE_CBC, 'block-size': 8, 'key-size': 16 },
|
||||||
|
@ -125,6 +149,11 @@ class BaseTransport (threading.Thread):
|
||||||
'hmac-md5-96': { 'class': MD5, 'size': 12 },
|
'hmac-md5-96': { 'class': MD5, 'size': 12 },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_key_info = {
|
||||||
|
'ssh-rsa': RSAKey,
|
||||||
|
'ssh-dss': DSSKey,
|
||||||
|
}
|
||||||
|
|
||||||
_kex_info = {
|
_kex_info = {
|
||||||
'diffie-hellman-group1-sha1': KexGroup1,
|
'diffie-hellman-group1-sha1': KexGroup1,
|
||||||
'diffie-hellman-group-exchange-sha1': KexGex,
|
'diffie-hellman-group-exchange-sha1': KexGex,
|
||||||
|
@ -225,7 +254,7 @@ class BaseTransport (threading.Thread):
|
||||||
self.keepalive_interval = 0
|
self.keepalive_interval = 0
|
||||||
self.keepalive_last = time.time()
|
self.keepalive_last = time.time()
|
||||||
# server mode:
|
# server mode:
|
||||||
self.server_mode = 0
|
self.server_mode = False
|
||||||
self.server_object = None
|
self.server_object = None
|
||||||
self.server_key_dict = { }
|
self.server_key_dict = { }
|
||||||
self.server_accepts = [ ]
|
self.server_accepts = [ ]
|
||||||
|
@ -321,7 +350,7 @@ class BaseTransport (threading.Thread):
|
||||||
"""
|
"""
|
||||||
if server is None:
|
if server is None:
|
||||||
server = ServerInterface()
|
server = ServerInterface()
|
||||||
self.server_mode = 1
|
self.server_mode = True
|
||||||
self.server_object = server
|
self.server_object = server
|
||||||
self.completion_event = event
|
self.completion_event = event
|
||||||
self.start()
|
self.start()
|
||||||
|
@ -947,16 +976,8 @@ class BaseTransport (threading.Thread):
|
||||||
"used by a kex object to register the next packet type it expects to see"
|
"used by a kex object to register the next packet type it expects to see"
|
||||||
self.expected_packet = type
|
self.expected_packet = type
|
||||||
|
|
||||||
def _key_from_blob(self, keytype, keyblob):
|
|
||||||
if keytype == 'ssh-rsa':
|
|
||||||
return RSAKey(Message(keyblob))
|
|
||||||
elif keytype == 'ssh-dss':
|
|
||||||
return DSSKey(Message(keyblob))
|
|
||||||
else:
|
|
||||||
return None
|
|
||||||
|
|
||||||
def _verify_key(self, host_key, sig):
|
def _verify_key(self, host_key, sig):
|
||||||
key = self._key_from_blob(self.host_key_type, host_key)
|
key = self._key_info[self.host_key_type](Message(host_key))
|
||||||
if (key == None) or not key.valid:
|
if (key == None) or not key.valid:
|
||||||
raise SSHException('Unknown host key type')
|
raise SSHException('Unknown host key type')
|
||||||
if not key.verify_ssh_sig(self.H, Message(sig)):
|
if not key.verify_ssh_sig(self.H, Message(sig)):
|
||||||
|
|
Loading…
Reference in New Issue