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