Merge branch '1.12'
This commit is contained in:
commit
a24ca77636
|
@ -28,7 +28,7 @@ import UserDict
|
||||||
from paramiko.common import *
|
from paramiko.common import *
|
||||||
from paramiko.dsskey import DSSKey
|
from paramiko.dsskey import DSSKey
|
||||||
from paramiko.rsakey import RSAKey
|
from paramiko.rsakey import RSAKey
|
||||||
from paramiko.util import get_logger
|
from paramiko.util import get_logger, constant_time_bytes_eq
|
||||||
from paramiko.ecdsakey import ECDSAKey
|
from paramiko.ecdsakey import ECDSAKey
|
||||||
|
|
||||||
|
|
||||||
|
@ -247,7 +247,7 @@ class HostKeys (UserDict.DictMixin):
|
||||||
entries = []
|
entries = []
|
||||||
for e in self._entries:
|
for e in self._entries:
|
||||||
for h in e.hostnames:
|
for h in e.hostnames:
|
||||||
if (h.startswith('|1|') and (self.hash_host(hostname, h) == h)) or (h == hostname):
|
if h.startswith('|1|') and constant_time_bytes_eq(self.hash_host(hostname, h), h) or h == hostname:
|
||||||
entries.append(e)
|
entries.append(e)
|
||||||
if len(entries) == 0:
|
if len(entries) == 0:
|
||||||
return None
|
return None
|
||||||
|
|
|
@ -357,7 +357,7 @@ class Packetizer (object):
|
||||||
mac = post_packet[:self.__mac_size_in]
|
mac = post_packet[:self.__mac_size_in]
|
||||||
mac_payload = struct.pack('>II', self.__sequence_number_in, packet_size) + packet
|
mac_payload = struct.pack('>II', self.__sequence_number_in, packet_size) + packet
|
||||||
my_mac = compute_hmac(self.__mac_key_in, mac_payload, self.__mac_engine_in)[:self.__mac_size_in]
|
my_mac = compute_hmac(self.__mac_key_in, mac_payload, self.__mac_engine_in)[:self.__mac_size_in]
|
||||||
if my_mac != mac:
|
if not util.constant_time_bytes_eq(my_mac, mac):
|
||||||
raise SSHException('Mismatched MAC')
|
raise SSHException('Mismatched MAC')
|
||||||
padding = ord(packet[0])
|
padding = ord(packet[0])
|
||||||
payload = packet[1:packet_size - padding]
|
payload = packet[1:packet_size - padding]
|
||||||
|
|
|
@ -309,3 +309,12 @@ class Counter (object):
|
||||||
def new(cls, nbits, initial_value=1L, overflow=0L):
|
def new(cls, nbits, initial_value=1L, overflow=0L):
|
||||||
return cls(nbits, initial_value=initial_value, overflow=overflow)
|
return cls(nbits, initial_value=initial_value, overflow=overflow)
|
||||||
new = classmethod(new)
|
new = classmethod(new)
|
||||||
|
|
||||||
|
|
||||||
|
def constant_time_bytes_eq(a, b):
|
||||||
|
if len(a) != len(b):
|
||||||
|
return False
|
||||||
|
res = 0
|
||||||
|
for i in xrange(len(a)):
|
||||||
|
res |= ord(a[i]) ^ ord(b[i])
|
||||||
|
return res == 0
|
||||||
|
|
|
@ -2,6 +2,10 @@
|
||||||
Changelog
|
Changelog
|
||||||
=========
|
=========
|
||||||
|
|
||||||
|
* :bug:`-` Use constant-time hash comparison operations where possible, to
|
||||||
|
protect against `timing-based attacks
|
||||||
|
<http://codahale.com/a-lesson-in-timing-attacks/>`_. Thanks to Alex Gaynor
|
||||||
|
for the patch.
|
||||||
* :release:`1.12.2 <2014-02-14>`
|
* :release:`1.12.2 <2014-02-14>`
|
||||||
* :release:`1.11.4 <2014-02-14>`
|
* :release:`1.11.4 <2014-02-14>`
|
||||||
* :release:`1.10.6 <2014-02-14>`
|
* :release:`1.10.6 <2014-02-14>`
|
||||||
|
|
Loading…
Reference in New Issue