fix a bunch of pychecker warnings, some of which were actual (but unlikely) bugs
This commit is contained in:
parent
26397bff47
commit
cb3008b402
3
README
3
README
|
@ -255,3 +255,6 @@ v1.0 JIGGLYPUFF
|
||||||
key files, etc)
|
key files, etc)
|
||||||
local and remote port forwarding
|
local and remote port forwarding
|
||||||
* SFTPClient.set_size
|
* SFTPClient.set_size
|
||||||
|
* remove @since that predate 1.0
|
||||||
|
* put examples in examples/ folder
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
# along with Paramiko; if not, write to the Free Software Foundation, Inc.,
|
# along with Paramiko; if not, write to the Free Software Foundation, Inc.,
|
||||||
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||||
|
|
||||||
import struct
|
|
||||||
import util
|
import util
|
||||||
|
|
||||||
|
|
||||||
|
@ -91,8 +91,9 @@ class BER(object):
|
||||||
while True:
|
while True:
|
||||||
x = b.decode_next()
|
x = b.decode_next()
|
||||||
if x is None:
|
if x is None:
|
||||||
return out
|
break
|
||||||
out.append(x)
|
out.append(x)
|
||||||
|
return out
|
||||||
decode_sequence = staticmethod(decode_sequence)
|
decode_sequence = staticmethod(decode_sequence)
|
||||||
|
|
||||||
def encode_tlv(self, ident, val):
|
def encode_tlv(self, ident, val):
|
||||||
|
|
|
@ -148,12 +148,7 @@ class Channel (object):
|
||||||
m.add_string('')
|
m.add_string('')
|
||||||
self.event.clear()
|
self.event.clear()
|
||||||
self.transport._send_user_message(m)
|
self.transport._send_user_message(m)
|
||||||
while True:
|
return self._wait_for_event()
|
||||||
self.event.wait(0.1)
|
|
||||||
if self.closed:
|
|
||||||
return False
|
|
||||||
if self.event.isSet():
|
|
||||||
return True
|
|
||||||
|
|
||||||
def invoke_shell(self):
|
def invoke_shell(self):
|
||||||
"""
|
"""
|
||||||
|
@ -180,12 +175,7 @@ class Channel (object):
|
||||||
m.add_boolean(1)
|
m.add_boolean(1)
|
||||||
self.event.clear()
|
self.event.clear()
|
||||||
self.transport._send_user_message(m)
|
self.transport._send_user_message(m)
|
||||||
while True:
|
return self._wait_for_event()
|
||||||
self.event.wait(0.1)
|
|
||||||
if self.closed:
|
|
||||||
return False
|
|
||||||
if self.event.isSet():
|
|
||||||
return True
|
|
||||||
|
|
||||||
def exec_command(self, command):
|
def exec_command(self, command):
|
||||||
"""
|
"""
|
||||||
|
@ -212,12 +202,7 @@ class Channel (object):
|
||||||
m.add_string(command)
|
m.add_string(command)
|
||||||
self.event.clear()
|
self.event.clear()
|
||||||
self.transport._send_user_message(m)
|
self.transport._send_user_message(m)
|
||||||
while True:
|
return self._wait_for_event()
|
||||||
self.event.wait(0.1)
|
|
||||||
if self.closed:
|
|
||||||
return False
|
|
||||||
if self.event.isSet():
|
|
||||||
return True
|
|
||||||
|
|
||||||
def invoke_subsystem(self, subsystem):
|
def invoke_subsystem(self, subsystem):
|
||||||
"""
|
"""
|
||||||
|
@ -243,12 +228,7 @@ class Channel (object):
|
||||||
m.add_string(subsystem)
|
m.add_string(subsystem)
|
||||||
self.event.clear()
|
self.event.clear()
|
||||||
self.transport._send_user_message(m)
|
self.transport._send_user_message(m)
|
||||||
while True:
|
return self._wait_for_event()
|
||||||
self.event.wait(0.1)
|
|
||||||
if self.closed:
|
|
||||||
return False
|
|
||||||
if self.event.isSet():
|
|
||||||
return True
|
|
||||||
|
|
||||||
def resize_pty(self, width=80, height=24):
|
def resize_pty(self, width=80, height=24):
|
||||||
"""
|
"""
|
||||||
|
@ -274,12 +254,7 @@ class Channel (object):
|
||||||
m.add_int(0).add_int(0)
|
m.add_int(0).add_int(0)
|
||||||
self.event.clear()
|
self.event.clear()
|
||||||
self.transport._send_user_message(m)
|
self.transport._send_user_message(m)
|
||||||
while True:
|
self._wait_for_event()
|
||||||
self.event.wait(0.1)
|
|
||||||
if self.closed:
|
|
||||||
return False
|
|
||||||
if self.event.isSet():
|
|
||||||
return True
|
|
||||||
|
|
||||||
def recv_exit_status(self):
|
def recv_exit_status(self):
|
||||||
"""
|
"""
|
||||||
|
@ -296,8 +271,9 @@ class Channel (object):
|
||||||
"""
|
"""
|
||||||
while True:
|
while True:
|
||||||
if self.closed or self.status_event.isSet():
|
if self.closed or self.status_event.isSet():
|
||||||
return self.exit_status
|
break
|
||||||
self.status_event.wait(0.1)
|
self.status_event.wait(0.1)
|
||||||
|
return self.exit_status
|
||||||
|
|
||||||
def send_exit_status(self, status):
|
def send_exit_status(self, status):
|
||||||
"""
|
"""
|
||||||
|
@ -1027,6 +1003,15 @@ class Channel (object):
|
||||||
def _log(self, level, msg):
|
def _log(self, level, msg):
|
||||||
self.logger.log(level, msg)
|
self.logger.log(level, msg)
|
||||||
|
|
||||||
|
def _wait_for_event(self):
|
||||||
|
while True:
|
||||||
|
self.event.wait(0.1)
|
||||||
|
if self.closed:
|
||||||
|
return False
|
||||||
|
if self.event.isSet():
|
||||||
|
break
|
||||||
|
return True
|
||||||
|
|
||||||
def _set_closed(self):
|
def _set_closed(self):
|
||||||
# you are holding the lock.
|
# you are holding the lock.
|
||||||
self.closed = True
|
self.closed = True
|
||||||
|
@ -1155,8 +1140,6 @@ class ChannelFile (BufferedFile):
|
||||||
def _write(self, data):
|
def _write(self, data):
|
||||||
self.channel.sendall(data)
|
self.channel.sendall(data)
|
||||||
return len(data)
|
return len(data)
|
||||||
|
|
||||||
seek = BufferedFile.seek
|
|
||||||
|
|
||||||
|
|
||||||
class ChannelStderrFile (ChannelFile):
|
class ChannelStderrFile (ChannelFile):
|
||||||
|
|
|
@ -36,6 +36,12 @@ class DSSKey (PKey):
|
||||||
Representation of a DSS key which can be used to sign an verify SSH2
|
Representation of a DSS key which can be used to sign an verify SSH2
|
||||||
data.
|
data.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
p = None
|
||||||
|
q = None
|
||||||
|
g = None
|
||||||
|
y = None
|
||||||
|
x = None
|
||||||
|
|
||||||
def __init__(self, msg=None, data=None, filename=None, password=None, vals=None):
|
def __init__(self, msg=None, data=None, filename=None, password=None, vals=None):
|
||||||
if filename is not None:
|
if filename is not None:
|
||||||
|
@ -81,7 +87,7 @@ class DSSKey (PKey):
|
||||||
return self.size
|
return self.size
|
||||||
|
|
||||||
def can_sign(self):
|
def can_sign(self):
|
||||||
return hasattr(self, 'x')
|
return self.x is not None
|
||||||
|
|
||||||
def sign_ssh_data(self, rpool, data):
|
def sign_ssh_data(self, rpool, data):
|
||||||
digest = SHA.new(data).digest()
|
digest = SHA.new(data).digest()
|
||||||
|
@ -124,6 +130,8 @@ class DSSKey (PKey):
|
||||||
return dss.verify(sigM, (sigR, sigS))
|
return dss.verify(sigM, (sigR, sigS))
|
||||||
|
|
||||||
def write_private_key_file(self, filename, password=None):
|
def write_private_key_file(self, filename, password=None):
|
||||||
|
if self.x is None:
|
||||||
|
raise SSHException('Not enough key information')
|
||||||
keylist = [ 0, self.p, self.q, self.g, self.y, self.x ]
|
keylist = [ 0, self.p, self.q, self.g, self.y, self.x ]
|
||||||
try:
|
try:
|
||||||
b = BER()
|
b = BER()
|
||||||
|
|
|
@ -45,6 +45,7 @@ class BufferedFile (object):
|
||||||
SEEK_END = 2
|
SEEK_END = 2
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
self.newlines = None
|
||||||
self._flags = 0
|
self._flags = 0
|
||||||
self._bufsize = self._DEFAULT_BUFSIZE
|
self._bufsize = self._DEFAULT_BUFSIZE
|
||||||
self._wbuffer = StringIO()
|
self._wbuffer = StringIO()
|
||||||
|
@ -55,6 +56,8 @@ class BufferedFile (object):
|
||||||
# realpos - position according the OS
|
# realpos - position according the OS
|
||||||
# (these may be different because we buffer for line reading)
|
# (these may be different because we buffer for line reading)
|
||||||
self._pos = self._realpos = 0
|
self._pos = self._realpos = 0
|
||||||
|
# size only matters for seekable files
|
||||||
|
self._size = 0
|
||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
self.close()
|
self.close()
|
||||||
|
|
|
@ -43,6 +43,12 @@ class KexGex (object):
|
||||||
|
|
||||||
def __init__(self, transport):
|
def __init__(self, transport):
|
||||||
self.transport = transport
|
self.transport = transport
|
||||||
|
self.p = None
|
||||||
|
self.q = None
|
||||||
|
self.g = None
|
||||||
|
self.x = None
|
||||||
|
self.e = None
|
||||||
|
self.f = None
|
||||||
|
|
||||||
def start_kex(self):
|
def start_kex(self):
|
||||||
if self.transport.server_mode:
|
if self.transport.server_mode:
|
||||||
|
|
|
@ -285,7 +285,7 @@ class Message (object):
|
||||||
elif type(i) is list:
|
elif type(i) is list:
|
||||||
return self.add_list(i)
|
return self.add_list(i)
|
||||||
else:
|
else:
|
||||||
raise exception('Unknown type')
|
raise Exception('Unknown type')
|
||||||
|
|
||||||
def add(self, *seq):
|
def add(self, *seq):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -219,7 +219,7 @@ class Packetizer (object):
|
||||||
if n < 0:
|
if n < 0:
|
||||||
raise EOFError()
|
raise EOFError()
|
||||||
if n == len(out):
|
if n == len(out):
|
||||||
return
|
break
|
||||||
out = out[n:]
|
out = out[n:]
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -398,23 +398,24 @@ class Packetizer (object):
|
||||||
x = self.__socket.recv(1)
|
x = self.__socket.recv(1)
|
||||||
if len(x) == 0:
|
if len(x) == 0:
|
||||||
raise EOFError()
|
raise EOFError()
|
||||||
return x
|
break
|
||||||
if self.__closed:
|
if self.__closed:
|
||||||
raise EOFError()
|
raise EOFError()
|
||||||
now = time.time()
|
now = time.time()
|
||||||
if now - start >= timeout:
|
if now - start >= timeout:
|
||||||
raise socket.timeout()
|
raise socket.timeout()
|
||||||
|
return x
|
||||||
|
|
||||||
def _read_timeout(self, timeout):
|
def _read_timeout(self, timeout):
|
||||||
if PY22:
|
if PY22:
|
||||||
return self._py22_read_timeout(n)
|
return self._py22_read_timeout(timeout)
|
||||||
start = time.time()
|
start = time.time()
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
x = self.__socket.recv(1)
|
x = self.__socket.recv(1)
|
||||||
if len(x) == 0:
|
if len(x) == 0:
|
||||||
raise EOFError()
|
raise EOFError()
|
||||||
return x
|
break
|
||||||
except socket.timeout:
|
except socket.timeout:
|
||||||
pass
|
pass
|
||||||
if self.__closed:
|
if self.__closed:
|
||||||
|
@ -422,6 +423,7 @@ class Packetizer (object):
|
||||||
now = time.time()
|
now = time.time()
|
||||||
if now - start >= timeout:
|
if now - start >= timeout:
|
||||||
raise socket.timeout()
|
raise socket.timeout()
|
||||||
|
return x
|
||||||
|
|
||||||
def _build_packet(self, payload):
|
def _build_packet(self, payload):
|
||||||
# pad up at least 4 bytes, to nearest block-size (usually 8)
|
# pad up at least 4 bytes, to nearest block-size (usually 8)
|
||||||
|
|
|
@ -28,8 +28,10 @@ import socket
|
||||||
|
|
||||||
def make_pipe ():
|
def make_pipe ():
|
||||||
if sys.platform[:3] != 'win':
|
if sys.platform[:3] != 'win':
|
||||||
return PosixPipe()
|
p = PosixPipe()
|
||||||
return WindowsPipe()
|
else:
|
||||||
|
p = WindowsPipe()
|
||||||
|
return p
|
||||||
|
|
||||||
|
|
||||||
class PosixPipe (object):
|
class PosixPipe (object):
|
||||||
|
|
|
@ -173,7 +173,7 @@ class PKey (object):
|
||||||
"""
|
"""
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def from_private_key_file(cl, filename, password=None):
|
def from_private_key_file(cls, filename, password=None):
|
||||||
"""
|
"""
|
||||||
Create a key object by reading a private key file. If the private
|
Create a key object by reading a private key file. If the private
|
||||||
key is encrypted and C{password} is not C{None}, the given password
|
key is encrypted and C{password} is not C{None}, the given password
|
||||||
|
@ -197,7 +197,7 @@ class PKey (object):
|
||||||
|
|
||||||
@since: fearow
|
@since: fearow
|
||||||
"""
|
"""
|
||||||
key = cl(filename=filename, password=password)
|
key = cls(filename=filename, password=password)
|
||||||
return key
|
return key
|
||||||
from_private_key_file = classmethod(from_private_key_file)
|
from_private_key_file = classmethod(from_private_key_file)
|
||||||
|
|
||||||
|
@ -216,7 +216,7 @@ class PKey (object):
|
||||||
|
|
||||||
@since: fearow
|
@since: fearow
|
||||||
"""
|
"""
|
||||||
raise exception('Not implemented in PKey')
|
raise Exception('Not implemented in PKey')
|
||||||
|
|
||||||
def _read_private_key_file(self, tag, filename, password=None):
|
def _read_private_key_file(self, tag, filename, password=None):
|
||||||
"""
|
"""
|
||||||
|
@ -265,7 +265,7 @@ class PKey (object):
|
||||||
# if we trudged to the end of the file, just try to cope.
|
# if we trudged to the end of the file, just try to cope.
|
||||||
try:
|
try:
|
||||||
data = base64.decodestring(''.join(lines[start:end]))
|
data = base64.decodestring(''.join(lines[start:end]))
|
||||||
except binascii.Error, e:
|
except base64.binascii.Error, e:
|
||||||
raise SSHException('base64 decoding error: ' + str(e))
|
raise SSHException('base64 decoding error: ' + str(e))
|
||||||
if not headers.has_key('proc-type'):
|
if not headers.has_key('proc-type'):
|
||||||
# unencryped: done
|
# unencryped: done
|
||||||
|
|
|
@ -23,6 +23,7 @@ Utility functions for dealing with primes.
|
||||||
from Crypto.Util import number
|
from Crypto.Util import number
|
||||||
|
|
||||||
from paramiko import util
|
from paramiko import util
|
||||||
|
from paramiko.ssh_exception import SSHException
|
||||||
|
|
||||||
|
|
||||||
def _generate_prime(bits, randpool):
|
def _generate_prime(bits, randpool):
|
||||||
|
@ -39,7 +40,8 @@ def _generate_prime(bits, randpool):
|
||||||
while not number.isPrime(n):
|
while not number.isPrime(n):
|
||||||
n += 2
|
n += 2
|
||||||
if util.bit_length(n) == bits:
|
if util.bit_length(n) == bits:
|
||||||
return n
|
break
|
||||||
|
return n
|
||||||
|
|
||||||
def _roll_random(rpool, n):
|
def _roll_random(rpool, n):
|
||||||
"returns a random # from 0 to N-1"
|
"returns a random # from 0 to N-1"
|
||||||
|
@ -59,7 +61,8 @@ def _roll_random(rpool, n):
|
||||||
x = chr(ord(x[0]) & hbyte_mask) + x[1:]
|
x = chr(ord(x[0]) & hbyte_mask) + x[1:]
|
||||||
num = util.inflate_long(x, 1)
|
num = util.inflate_long(x, 1)
|
||||||
if num < n:
|
if num < n:
|
||||||
return num
|
break
|
||||||
|
return num
|
||||||
|
|
||||||
|
|
||||||
class ModulusPack (object):
|
class ModulusPack (object):
|
||||||
|
@ -75,8 +78,8 @@ class ModulusPack (object):
|
||||||
self.randpool = rpool
|
self.randpool = rpool
|
||||||
|
|
||||||
def _parse_modulus(self, line):
|
def _parse_modulus(self, line):
|
||||||
timestamp, type, tests, tries, size, generator, modulus = line.split()
|
timestamp, mod_type, tests, tries, size, generator, modulus = line.split()
|
||||||
type = int(type)
|
mod_type = int(mod_type)
|
||||||
tests = int(tests)
|
tests = int(tests)
|
||||||
tries = int(tries)
|
tries = int(tries)
|
||||||
size = int(size)
|
size = int(size)
|
||||||
|
@ -87,7 +90,7 @@ class ModulusPack (object):
|
||||||
# type 2 (meets basic structural requirements)
|
# type 2 (meets basic structural requirements)
|
||||||
# test 4 (more than just a small-prime sieve)
|
# test 4 (more than just a small-prime sieve)
|
||||||
# tries < 100 if test & 4 (at least 100 tries of miller-rabin)
|
# tries < 100 if test & 4 (at least 100 tries of miller-rabin)
|
||||||
if (type < 2) or (tests < 4) or ((tests & 4) and (tests < 8) and (tries < 100)):
|
if (mod_type < 2) or (tests < 4) or ((tests & 4) and (tests < 8) and (tries < 100)):
|
||||||
self.discarded.append((modulus, 'does not meet basic requirements'))
|
self.discarded.append((modulus, 'does not meet basic requirements'))
|
||||||
return
|
return
|
||||||
if generator == 0:
|
if generator == 0:
|
||||||
|
|
|
@ -38,6 +38,12 @@ class RSAKey (PKey):
|
||||||
data.
|
data.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
n = None
|
||||||
|
e = None
|
||||||
|
d = None
|
||||||
|
p = None
|
||||||
|
q = None
|
||||||
|
|
||||||
def __init__(self, msg=None, data=None, filename=None, password=None, vals=None):
|
def __init__(self, msg=None, data=None, filename=None, password=None, vals=None):
|
||||||
if filename is not None:
|
if filename is not None:
|
||||||
self._from_private_key_file(filename, password)
|
self._from_private_key_file(filename, password)
|
||||||
|
@ -75,7 +81,7 @@ class RSAKey (PKey):
|
||||||
return self.size
|
return self.size
|
||||||
|
|
||||||
def can_sign(self):
|
def can_sign(self):
|
||||||
return hasattr(self, 'd')
|
return self.d is not None
|
||||||
|
|
||||||
def sign_ssh_data(self, rpool, data):
|
def sign_ssh_data(self, rpool, data):
|
||||||
digest = SHA.new(data).digest()
|
digest = SHA.new(data).digest()
|
||||||
|
@ -93,11 +99,13 @@ class RSAKey (PKey):
|
||||||
# verify the signature by SHA'ing the data and encrypting it using the
|
# verify the signature by SHA'ing the data and encrypting it using the
|
||||||
# public key. some wackiness ensues where we "pkcs1imify" the 20-byte
|
# public key. some wackiness ensues where we "pkcs1imify" the 20-byte
|
||||||
# hash into a string as long as the RSA key.
|
# hash into a string as long as the RSA key.
|
||||||
hash = util.inflate_long(self._pkcs1imify(SHA.new(data).digest()), True)
|
hash_obj = util.inflate_long(self._pkcs1imify(SHA.new(data).digest()), True)
|
||||||
rsa = RSA.construct((long(self.n), long(self.e)))
|
rsa = RSA.construct((long(self.n), long(self.e)))
|
||||||
return rsa.verify(hash, (sig,))
|
return rsa.verify(hash_obj, (sig,))
|
||||||
|
|
||||||
def write_private_key_file(self, filename, password=None):
|
def write_private_key_file(self, filename, password=None):
|
||||||
|
if (self.p is None) or (self.q is None):
|
||||||
|
raise SSHException('Not enough key info to write private key file')
|
||||||
keylist = [ 0, self.n, self.e, self.d, self.p, self.q,
|
keylist = [ 0, self.n, self.e, self.d, self.p, self.q,
|
||||||
self.d % (self.p - 1), self.d % (self.q - 1),
|
self.d % (self.p - 1), self.d % (self.q - 1),
|
||||||
util.mod_inverse(self.q, self.p) ]
|
util.mod_inverse(self.q, self.p) ]
|
||||||
|
|
|
@ -51,6 +51,12 @@ class SFTPAttributes (object):
|
||||||
Create a new (empty) SFTPAttributes object. All fields will be empty.
|
Create a new (empty) SFTPAttributes object. All fields will be empty.
|
||||||
"""
|
"""
|
||||||
self._flags = 0
|
self._flags = 0
|
||||||
|
self.st_size = -1
|
||||||
|
self.st_uid = -1
|
||||||
|
self.st_gid = -1
|
||||||
|
self.st_mode = 0
|
||||||
|
self.st_atime = 0
|
||||||
|
self.st_mtime = 0
|
||||||
self.attr = {}
|
self.attr = {}
|
||||||
|
|
||||||
def from_stat(cls, obj, filename=None):
|
def from_stat(cls, obj, filename=None):
|
||||||
|
@ -114,13 +120,13 @@ class SFTPAttributes (object):
|
||||||
|
|
||||||
def _pack(self, msg):
|
def _pack(self, msg):
|
||||||
self._flags = 0
|
self._flags = 0
|
||||||
if hasattr(self, 'st_size'):
|
if self.st_size >= 0:
|
||||||
self._flags |= self.FLAG_SIZE
|
self._flags |= self.FLAG_SIZE
|
||||||
if hasattr(self, 'st_uid') or hasattr(self, 'st_gid'):
|
if (self.st_uid >= 0) or (self.st_gid >= 0):
|
||||||
self._flags |= self.FLAG_UIDGID
|
self._flags |= self.FLAG_UIDGID
|
||||||
if hasattr(self, 'st_mode'):
|
if self.st_mode != 0:
|
||||||
self._flags |= self.FLAG_PERMISSIONS
|
self._flags |= self.FLAG_PERMISSIONS
|
||||||
if hasattr(self, 'st_atime') or hasattr(self, 'st_mtime'):
|
if (self.st_atime > 0) or (self.st_mtime > 0):
|
||||||
self._flags |= self.FLAG_AMTIME
|
self._flags |= self.FLAG_AMTIME
|
||||||
if len(self.attr) > 0:
|
if len(self.attr) > 0:
|
||||||
self._flags |= self.FLAG_EXTENDED
|
self._flags |= self.FLAG_EXTENDED
|
||||||
|
@ -128,13 +134,13 @@ class SFTPAttributes (object):
|
||||||
if self._flags & self.FLAG_SIZE:
|
if self._flags & self.FLAG_SIZE:
|
||||||
msg.add_int64(self.st_size)
|
msg.add_int64(self.st_size)
|
||||||
if self._flags & self.FLAG_UIDGID:
|
if self._flags & self.FLAG_UIDGID:
|
||||||
msg.add_int(getattr(self, 'st_uid', 0))
|
msg.add_int(self.st_uid)
|
||||||
msg.add_int(getattr(self, 'st_gid', 0))
|
msg.add_int(self.st_gid)
|
||||||
if self._flags & self.FLAG_PERMISSIONS:
|
if self._flags & self.FLAG_PERMISSIONS:
|
||||||
msg.add_int(self.st_mode)
|
msg.add_int(self.st_mode)
|
||||||
if self._flags & self.FLAG_AMTIME:
|
if self._flags & self.FLAG_AMTIME:
|
||||||
msg.add_int(getattr(self, 'st_atime', 0))
|
msg.add_int(self.st_atime)
|
||||||
msg.add_int(getattr(self, 'st_mtime', 0))
|
msg.add_int(self.st_mtime)
|
||||||
if self._flags & self.FLAG_EXTENDED:
|
if self._flags & self.FLAG_EXTENDED:
|
||||||
msg.add_int(len(self.attr))
|
msg.add_int(len(self.attr))
|
||||||
for key, val in self.attr.iteritems():
|
for key, val in self.attr.iteritems():
|
||||||
|
@ -144,15 +150,14 @@ class SFTPAttributes (object):
|
||||||
|
|
||||||
def _debug_str(self):
|
def _debug_str(self):
|
||||||
out = '[ '
|
out = '[ '
|
||||||
if hasattr(self, 'st_size'):
|
if self.st_size >= 0:
|
||||||
out += 'size=%d ' % self.st_size
|
out += 'size=%d ' % self.st_size
|
||||||
if hasattr(self, 'st_uid') or hasattr(self, 'st_gid'):
|
if (self.st_uid >= 0) or (self.st_gid >= 0):
|
||||||
out += 'uid=%d gid=%d ' % (getattr(self, 'st_uid', 0), getattr(self, 'st_gid', 0))
|
out += 'uid=%d gid=%d ' % (self.st_uid, self.st_gid)
|
||||||
if hasattr(self, 'st_mode'):
|
if self.st_mode != 0:
|
||||||
out += 'mode=' + oct(self.st_mode) + ' '
|
out += 'mode=' + oct(self.st_mode) + ' '
|
||||||
if hasattr(self, 'st_atime') or hasattr(self, 'st_mtime'):
|
if (self.st_atime > 0) or (self.st_mtime > 0):
|
||||||
out += 'atime=%d mtime=%d ' % (getattr(self, 'st_atime', 0),
|
out += 'atime=%d mtime=%d ' % (self.st_atime, self.st_mtime)
|
||||||
getattr(self, 'st_mtime', 0))
|
|
||||||
for k, v in self.attr.iteritems():
|
for k, v in self.attr.iteritems():
|
||||||
out += '"%s"=%r ' % (str(k), v)
|
out += '"%s"=%r ' % (str(k), v)
|
||||||
out += ']'
|
out += ']'
|
||||||
|
@ -171,7 +176,7 @@ class SFTPAttributes (object):
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
"create a unix-style long description of the file (like ls -l)"
|
"create a unix-style long description of the file (like ls -l)"
|
||||||
if hasattr(self, 'st_mode'):
|
if self.st_mode != 0:
|
||||||
kind = stat.S_IFMT(self.st_mode)
|
kind = stat.S_IFMT(self.st_mode)
|
||||||
if kind == stat.S_IFIFO:
|
if kind == stat.S_IFIFO:
|
||||||
ks = 'p'
|
ks = 'p'
|
||||||
|
@ -194,15 +199,12 @@ class SFTPAttributes (object):
|
||||||
ks += self._rwx(self.st_mode & 7, self.st_mode & stat.S_ISVTX, True)
|
ks += self._rwx(self.st_mode & 7, self.st_mode & stat.S_ISVTX, True)
|
||||||
else:
|
else:
|
||||||
ks = '?---------'
|
ks = '?---------'
|
||||||
uid = getattr(self, 'st_uid', -1)
|
|
||||||
gid = getattr(self, 'st_gid', -1)
|
|
||||||
size = getattr(self, 'st_size', -1)
|
|
||||||
mtime = getattr(self, 'st_mtime', 0)
|
|
||||||
# compute display date
|
# compute display date
|
||||||
if abs(time.time() - mtime) > 15552000:
|
if abs(time.time() - self.st_mtime) > 15552000:
|
||||||
# (15552000 = 6 months)
|
# (15552000 = 6 months)
|
||||||
datestr = time.strftime('%d %b %Y', time.localtime(mtime))
|
datestr = time.strftime('%d %b %Y', time.localtime(self.st_mtime))
|
||||||
else:
|
else:
|
||||||
datestr = time.strftime('%d %b %H:%M', time.localtime(mtime))
|
datestr = time.strftime('%d %b %H:%M', time.localtime(self.st_mtime))
|
||||||
filename = getattr(self, 'filename', '?')
|
filename = getattr(self, 'filename', '?')
|
||||||
return '%s 1 %-8d %-8d %8d %-12s %s' % (ks, uid, gid, size, datestr, filename)
|
return '%s 1 %-8d %-8d %8d %-12s %s' % (ks, self.st_uid, self.st_gid,
|
||||||
|
self.st_size, datestr, filename)
|
||||||
|
|
|
@ -23,6 +23,7 @@ Client-mode SFTP support.
|
||||||
import errno
|
import errno
|
||||||
import os
|
import os
|
||||||
import threading
|
import threading
|
||||||
|
import time
|
||||||
import weakref
|
import weakref
|
||||||
from paramiko.sftp import *
|
from paramiko.sftp import *
|
||||||
from paramiko.sftp_attr import SFTPAttributes
|
from paramiko.sftp_attr import SFTPAttributes
|
||||||
|
@ -74,7 +75,7 @@ class SFTPClient (BaseSFTP):
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
self.close()
|
self.close()
|
||||||
|
|
||||||
def from_transport(selfclass, t):
|
def from_transport(cls, t):
|
||||||
"""
|
"""
|
||||||
Create an SFTP client channel from an open L{Transport}.
|
Create an SFTP client channel from an open L{Transport}.
|
||||||
|
|
||||||
|
@ -89,7 +90,7 @@ class SFTPClient (BaseSFTP):
|
||||||
return None
|
return None
|
||||||
if not chan.invoke_subsystem('sftp'):
|
if not chan.invoke_subsystem('sftp'):
|
||||||
raise SFTPError('Failed to invoke sftp subsystem')
|
raise SFTPError('Failed to invoke sftp subsystem')
|
||||||
return selfclass(chan)
|
return cls(chan)
|
||||||
from_transport = classmethod(from_transport)
|
from_transport = classmethod(from_transport)
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
|
@ -560,7 +561,7 @@ class SFTPClient (BaseSFTP):
|
||||||
self._log(DEBUG, 'Unexpected response #%d' % (num,))
|
self._log(DEBUG, 'Unexpected response #%d' % (num,))
|
||||||
if waitfor is None:
|
if waitfor is None:
|
||||||
# just doing a single check
|
# just doing a single check
|
||||||
return
|
break
|
||||||
continue
|
continue
|
||||||
fileobj = self._expecting[num]
|
fileobj = self._expecting[num]
|
||||||
del self._expecting[num]
|
del self._expecting[num]
|
||||||
|
@ -573,7 +574,8 @@ class SFTPClient (BaseSFTP):
|
||||||
fileobj._async_response(t, msg)
|
fileobj._async_response(t, msg)
|
||||||
if waitfor is None:
|
if waitfor is None:
|
||||||
# just doing a single check
|
# just doing a single check
|
||||||
return
|
break
|
||||||
|
return (None, None)
|
||||||
|
|
||||||
def _finish_responses(self, fileobj):
|
def _finish_responses(self, fileobj):
|
||||||
while fileobj in self._expecting.values():
|
while fileobj in self._expecting.values():
|
||||||
|
|
|
@ -43,12 +43,18 @@ class SFTPFile (BufferedFile):
|
||||||
BufferedFile._set_mode(self, mode, bufsize)
|
BufferedFile._set_mode(self, mode, bufsize)
|
||||||
self.pipelined = False
|
self.pipelined = False
|
||||||
self._prefetching = False
|
self._prefetching = False
|
||||||
|
self._prefetch_so_far = 0
|
||||||
|
self._prefetch_size = 0
|
||||||
|
self._prefetch_data = {}
|
||||||
self._saved_exception = None
|
self._saved_exception = None
|
||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
self.close(_async=True)
|
self._close(async=True)
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
self._close(async=False)
|
||||||
|
|
||||||
def close(self, _async=False):
|
def _close(self, async=False):
|
||||||
# We allow double-close without signaling an error, because real
|
# We allow double-close without signaling an error, because real
|
||||||
# Python file objects do. However, we must protect against actually
|
# Python file objects do. However, we must protect against actually
|
||||||
# sending multiple CMD_CLOSE packets, because after we close our
|
# sending multiple CMD_CLOSE packets, because after we close our
|
||||||
|
@ -62,7 +68,7 @@ class SFTPFile (BufferedFile):
|
||||||
self.sftp._finish_responses(self)
|
self.sftp._finish_responses(self)
|
||||||
BufferedFile.close(self)
|
BufferedFile.close(self)
|
||||||
try:
|
try:
|
||||||
if _async:
|
if async:
|
||||||
# GC'd file handle could be called from an arbitrary thread -- don't wait for a response
|
# GC'd file handle could be called from an arbitrary thread -- don't wait for a response
|
||||||
self.sftp._async_request(type(None), CMD_CLOSE, self.handle)
|
self.sftp._async_request(type(None), CMD_CLOSE, self.handle)
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -81,15 +81,16 @@ class SFTPHandle (object):
|
||||||
@return: data read from the file, or an SFTP error code.
|
@return: data read from the file, or an SFTP error code.
|
||||||
@rtype: str
|
@rtype: str
|
||||||
"""
|
"""
|
||||||
if not hasattr(self, 'readfile') or (self.readfile is None):
|
readfile = getattr(self, 'readfile', None)
|
||||||
|
if readfile is None:
|
||||||
return SFTP_OP_UNSUPPORTED
|
return SFTP_OP_UNSUPPORTED
|
||||||
try:
|
try:
|
||||||
if self.__tell is None:
|
if self.__tell is None:
|
||||||
self.__tell = self.readfile.tell()
|
self.__tell = readfile.tell()
|
||||||
if offset != self.__tell:
|
if offset != self.__tell:
|
||||||
self.readfile.seek(offset)
|
readfile.seek(offset)
|
||||||
self.__tell = offset
|
self.__tell = offset
|
||||||
data = self.readfile.read(length)
|
data = readfile.read(length)
|
||||||
except IOError, e:
|
except IOError, e:
|
||||||
self.__tell = None
|
self.__tell = None
|
||||||
return SFTPServer.convert_errno(e.errno)
|
return SFTPServer.convert_errno(e.errno)
|
||||||
|
@ -116,16 +117,17 @@ class SFTPHandle (object):
|
||||||
@type data: str
|
@type data: str
|
||||||
@return: an SFTP error code like L{SFTP_OK}.
|
@return: an SFTP error code like L{SFTP_OK}.
|
||||||
"""
|
"""
|
||||||
if not hasattr(self, 'writefile') or (self.writefile is None):
|
writefile = getattr(self, 'writefile', None)
|
||||||
|
if writefile is None:
|
||||||
return SFTP_OP_UNSUPPORTED
|
return SFTP_OP_UNSUPPORTED
|
||||||
try:
|
try:
|
||||||
if self.__tell is None:
|
if self.__tell is None:
|
||||||
self.__tell = self.writefile.tell()
|
self.__tell = writefile.tell()
|
||||||
if offset != self.__tell:
|
if offset != self.__tell:
|
||||||
self.writefile.seek(offset)
|
writefile.seek(offset)
|
||||||
self.__tell = offset
|
self.__tell = offset
|
||||||
self.writefile.write(data)
|
writefile.write(data)
|
||||||
self.writefile.flush()
|
writefile.flush()
|
||||||
except IOError, e:
|
except IOError, e:
|
||||||
self.__tell = None
|
self.__tell = None
|
||||||
return SFTPServer.convert_errno(e.errno)
|
return SFTPServer.convert_errno(e.errno)
|
||||||
|
|
|
@ -246,29 +246,29 @@ class SFTPServer (BaseSFTP, SubsystemHandler):
|
||||||
self._send_status(request_number, SFTP_FAILURE, 'Block size too small')
|
self._send_status(request_number, SFTP_FAILURE, 'Block size too small')
|
||||||
return
|
return
|
||||||
|
|
||||||
sum = ''
|
sum_out = ''
|
||||||
offset = start
|
offset = start
|
||||||
while offset < start + length:
|
while offset < start + length:
|
||||||
blocklen = min(block_size, start + length - offset)
|
blocklen = min(block_size, start + length - offset)
|
||||||
# don't try to read more than about 64KB at a time
|
# don't try to read more than about 64KB at a time
|
||||||
chunklen = min(blocklen, 65536)
|
chunklen = min(blocklen, 65536)
|
||||||
count = 0
|
count = 0
|
||||||
hash = alg.new()
|
hash_obj = alg.new()
|
||||||
while count < blocklen:
|
while count < blocklen:
|
||||||
data = f.read(offset, chunklen)
|
data = f.read(offset, chunklen)
|
||||||
if not type(data) is str:
|
if not type(data) is str:
|
||||||
self._send_status(request_number, data, 'Unable to hash file')
|
self._send_status(request_number, data, 'Unable to hash file')
|
||||||
return
|
return
|
||||||
hash.update(data)
|
hash_obj.update(data)
|
||||||
count += len(data)
|
count += len(data)
|
||||||
offset += count
|
offset += count
|
||||||
sum += hash.digest()
|
sum_out += hash_obj.digest()
|
||||||
|
|
||||||
msg = Message()
|
msg = Message()
|
||||||
msg.add_int(request_number)
|
msg.add_int(request_number)
|
||||||
msg.add_string('check-file')
|
msg.add_string('check-file')
|
||||||
msg.add_string(algname)
|
msg.add_string(algname)
|
||||||
msg.add_bytes(sum)
|
msg.add_bytes(sum_out)
|
||||||
self._send_packet(CMD_EXTENDED_REPLY, str(msg))
|
self._send_packet(CMD_EXTENDED_REPLY, str(msg))
|
||||||
|
|
||||||
def _convert_pflags(self, pflags):
|
def _convert_pflags(self, pflags):
|
||||||
|
@ -412,7 +412,7 @@ class SFTPServer (BaseSFTP, SubsystemHandler):
|
||||||
if tag == 'check-file':
|
if tag == 'check-file':
|
||||||
self._check_file(request_number, msg)
|
self._check_file(request_number, msg)
|
||||||
else:
|
else:
|
||||||
send._send_status(request_number, SFTP_OP_UNSUPPORTED)
|
self._send_status(request_number, SFTP_OP_UNSUPPORTED)
|
||||||
else:
|
else:
|
||||||
self._send_status(request_number, SFTP_OP_UNSUPPORTED)
|
self._send_status(request_number, SFTP_OP_UNSUPPORTED)
|
||||||
|
|
||||||
|
|
|
@ -30,19 +30,20 @@ import time
|
||||||
import weakref
|
import weakref
|
||||||
|
|
||||||
from paramiko import util
|
from paramiko import util
|
||||||
|
from paramiko.auth_handler import AuthHandler
|
||||||
|
from paramiko.channel import Channel
|
||||||
from paramiko.common import *
|
from paramiko.common import *
|
||||||
from paramiko.compress import ZlibCompressor, ZlibDecompressor
|
from paramiko.compress import ZlibCompressor, ZlibDecompressor
|
||||||
from paramiko.ssh_exception import SSHException, BadAuthenticationType
|
|
||||||
from paramiko.message import Message
|
|
||||||
from paramiko.channel import Channel
|
|
||||||
from paramiko.sftp_client import SFTPClient
|
|
||||||
from paramiko.packet import Packetizer, NeedRekeyException
|
|
||||||
from paramiko.rsakey import RSAKey
|
|
||||||
from paramiko.dsskey import DSSKey
|
from paramiko.dsskey import DSSKey
|
||||||
from paramiko.kex_group1 import KexGroup1
|
|
||||||
from paramiko.kex_gex import KexGex
|
from paramiko.kex_gex import KexGex
|
||||||
|
from paramiko.kex_group1 import KexGroup1
|
||||||
|
from paramiko.message import Message
|
||||||
|
from paramiko.packet import Packetizer, NeedRekeyException
|
||||||
from paramiko.primes import ModulusPack
|
from paramiko.primes import ModulusPack
|
||||||
from paramiko.auth_handler import AuthHandler
|
from paramiko.rsakey import RSAKey
|
||||||
|
from paramiko.server import ServerInterface
|
||||||
|
from paramiko.sftp_client import SFTPClient
|
||||||
|
from paramiko.ssh_exception import SSHException, BadAuthenticationType
|
||||||
|
|
||||||
# these come from PyCrypt
|
# these come from PyCrypt
|
||||||
# http://www.amk.ca/python/writing/pycrypt/
|
# http://www.amk.ca/python/writing/pycrypt/
|
||||||
|
@ -110,7 +111,8 @@ class SecurityOptions (object):
|
||||||
if type(x) is not tuple:
|
if type(x) is not tuple:
|
||||||
raise TypeError('expected tuple or list')
|
raise TypeError('expected tuple or list')
|
||||||
possible = getattr(self._transport, orig).keys()
|
possible = getattr(self._transport, orig).keys()
|
||||||
if len(filter(lambda n: n not in possible, x)) > 0:
|
forbidden = filter(lambda n: n not in possible, x)
|
||||||
|
if len(forbidden) > 0:
|
||||||
raise ValueError('unknown cipher')
|
raise ValueError('unknown cipher')
|
||||||
setattr(self._transport, name, x)
|
setattr(self._transport, name, x)
|
||||||
|
|
||||||
|
@ -245,25 +247,39 @@ class Transport (threading.Thread):
|
||||||
self.sock.settimeout(0.1)
|
self.sock.settimeout(0.1)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# negotiated crypto parameters
|
# negotiated crypto parameters
|
||||||
self.packetizer = Packetizer(sock)
|
self.packetizer = Packetizer(sock)
|
||||||
self.local_version = 'SSH-' + self._PROTO_ID + '-' + self._CLIENT_ID
|
self.local_version = 'SSH-' + self._PROTO_ID + '-' + self._CLIENT_ID
|
||||||
self.remote_version = ''
|
self.remote_version = ''
|
||||||
self.local_cipher = self.remote_cipher = ''
|
self.local_cipher = self.remote_cipher = ''
|
||||||
self.local_kex_init = self.remote_kex_init = None
|
self.local_kex_init = self.remote_kex_init = None
|
||||||
|
self.local_mac = self.remote_mac = None
|
||||||
|
self.local_compression = self.remote_compression = None
|
||||||
self.session_id = None
|
self.session_id = None
|
||||||
# /negotiated crypto parameters
|
self.host_key_type = None
|
||||||
self.expected_packet = 0
|
self.host_key = None
|
||||||
|
|
||||||
|
# state used during negotiation
|
||||||
|
self.kex_engine = None
|
||||||
|
self.H = None
|
||||||
|
self.K = None
|
||||||
|
|
||||||
self.active = False
|
self.active = False
|
||||||
self.initial_kex_done = False
|
self.initial_kex_done = False
|
||||||
self.in_kex = False
|
self.in_kex = False
|
||||||
|
self.authenticated = False
|
||||||
|
self.expected_packet = 0
|
||||||
self.lock = threading.Lock() # synchronization (always higher level than write_lock)
|
self.lock = threading.Lock() # synchronization (always higher level than write_lock)
|
||||||
|
|
||||||
|
# tracking open channels
|
||||||
self.channels = weakref.WeakValueDictionary() # (id -> Channel)
|
self.channels = weakref.WeakValueDictionary() # (id -> Channel)
|
||||||
self.channel_events = { } # (id -> Event)
|
self.channel_events = { } # (id -> Event)
|
||||||
self.channels_seen = { } # (id -> True)
|
self.channels_seen = { } # (id -> True)
|
||||||
self.channel_counter = 1
|
self.channel_counter = 1
|
||||||
self.window_size = 65536
|
self.window_size = 65536
|
||||||
self.max_packet_size = 34816
|
self.max_packet_size = 34816
|
||||||
|
|
||||||
self.saved_exception = None
|
self.saved_exception = None
|
||||||
self.clear_to_send = threading.Event()
|
self.clear_to_send = threading.Event()
|
||||||
self.clear_to_send_lock = threading.Lock()
|
self.clear_to_send_lock = threading.Lock()
|
||||||
|
@ -271,9 +287,9 @@ class Transport (threading.Thread):
|
||||||
self.logger = util.get_logger(self.log_name)
|
self.logger = util.get_logger(self.log_name)
|
||||||
self.packetizer.set_log(self.logger)
|
self.packetizer.set_log(self.logger)
|
||||||
self.auth_handler = None
|
self.auth_handler = None
|
||||||
self.authenticated = False
|
self.global_response = None # response Message from an arbitrary global request
|
||||||
# user-defined event callbacks:
|
self.completion_event = None # user-defined event callbacks
|
||||||
self.completion_event = None
|
|
||||||
# server mode:
|
# server mode:
|
||||||
self.server_mode = False
|
self.server_mode = False
|
||||||
self.server_object = None
|
self.server_object = None
|
||||||
|
@ -993,7 +1009,7 @@ class Transport (threading.Thread):
|
||||||
return self.auth_handler.wait_for_response(my_event)
|
return self.auth_handler.wait_for_response(my_event)
|
||||||
except BadAuthenticationType, x:
|
except BadAuthenticationType, x:
|
||||||
# if password auth isn't allowed, but keyboard-interactive *is*, try to fudge it
|
# if password auth isn't allowed, but keyboard-interactive *is*, try to fudge it
|
||||||
if not fallback or not 'keyboard-interactive' in x.allowed_types:
|
if not fallback or ('keyboard-interactive' not in x.allowed_types):
|
||||||
raise
|
raise
|
||||||
try:
|
try:
|
||||||
def handler(title, instructions, fields):
|
def handler(title, instructions, fields):
|
||||||
|
@ -1010,6 +1026,7 @@ class Transport (threading.Thread):
|
||||||
except SSHException, ignored:
|
except SSHException, ignored:
|
||||||
# attempt failed; just raise the original exception
|
# attempt failed; just raise the original exception
|
||||||
raise x
|
raise x
|
||||||
|
return None
|
||||||
|
|
||||||
def auth_publickey(self, username, key, event=None):
|
def auth_publickey(self, username, key, event=None):
|
||||||
"""
|
"""
|
||||||
|
@ -1262,9 +1279,9 @@ class Transport (threading.Thread):
|
||||||
m.add_mpint(self.K)
|
m.add_mpint(self.K)
|
||||||
m.add_bytes(self.H)
|
m.add_bytes(self.H)
|
||||||
m.add_bytes(sofar)
|
m.add_bytes(sofar)
|
||||||
hash = SHA.new(str(m)).digest()
|
digest = SHA.new(str(m)).digest()
|
||||||
out += hash
|
out += digest
|
||||||
sofar += hash
|
sofar += digest
|
||||||
return out[:nbytes]
|
return out[:nbytes]
|
||||||
|
|
||||||
def _get_cipher(self, name, key, iv):
|
def _get_cipher(self, name, key, iv):
|
||||||
|
@ -1394,24 +1411,24 @@ class Transport (threading.Thread):
|
||||||
else:
|
else:
|
||||||
timeout = 2
|
timeout = 2
|
||||||
try:
|
try:
|
||||||
buffer = self.packetizer.readline(timeout)
|
buf = self.packetizer.readline(timeout)
|
||||||
except Exception, x:
|
except Exception, x:
|
||||||
raise SSHException('Error reading SSH protocol banner' + str(x))
|
raise SSHException('Error reading SSH protocol banner' + str(x))
|
||||||
if buffer[:4] == 'SSH-':
|
if buf[:4] == 'SSH-':
|
||||||
break
|
break
|
||||||
self._log(DEBUG, 'Banner: ' + buffer)
|
self._log(DEBUG, 'Banner: ' + buf)
|
||||||
if buffer[:4] != 'SSH-':
|
if buf[:4] != 'SSH-':
|
||||||
raise SSHException('Indecipherable protocol version "' + buffer + '"')
|
raise SSHException('Indecipherable protocol version "' + buf + '"')
|
||||||
# save this server version string for later
|
# save this server version string for later
|
||||||
self.remote_version = buffer
|
self.remote_version = buf
|
||||||
# pull off any attached comment
|
# pull off any attached comment
|
||||||
comment = ''
|
comment = ''
|
||||||
i = string.find(buffer, ' ')
|
i = string.find(buf, ' ')
|
||||||
if i >= 0:
|
if i >= 0:
|
||||||
comment = buffer[i+1:]
|
comment = buf[i+1:]
|
||||||
buffer = buffer[:i]
|
buf = buf[:i]
|
||||||
# parse out version string and make sure it matches
|
# parse out version string and make sure it matches
|
||||||
segs = buffer.split('-', 2)
|
segs = buf.split('-', 2)
|
||||||
if len(segs) < 3:
|
if len(segs) < 3:
|
||||||
raise SSHException('Invalid SSH banner')
|
raise SSHException('Invalid SSH banner')
|
||||||
version = segs[1]
|
version = segs[1]
|
||||||
|
|
|
@ -168,12 +168,12 @@ def generate_key_bytes(hashclass, salt, key, nbytes):
|
||||||
if len(salt) > 8:
|
if len(salt) > 8:
|
||||||
salt = salt[:8]
|
salt = salt[:8]
|
||||||
while nbytes > 0:
|
while nbytes > 0:
|
||||||
hash = hashclass.new()
|
hash_obj = hashclass.new()
|
||||||
if len(digest) > 0:
|
if len(digest) > 0:
|
||||||
hash.update(digest)
|
hash_obj.update(digest)
|
||||||
hash.update(key)
|
hash_obj.update(key)
|
||||||
hash.update(salt)
|
hash_obj.update(salt)
|
||||||
digest = hash.digest()
|
digest = hash_obj.digest()
|
||||||
size = min(nbytes, len(digest))
|
size = min(nbytes, len(digest))
|
||||||
keydata += digest[:size]
|
keydata += digest[:size]
|
||||||
nbytes -= size
|
nbytes -= size
|
||||||
|
|
Loading…
Reference in New Issue