summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--README3
-rw-r--r--paramiko/ber.py5
-rw-r--r--paramiko/channel.py49
-rw-r--r--paramiko/dsskey.py10
-rw-r--r--paramiko/file.py3
-rw-r--r--paramiko/kex_gex.py6
-rw-r--r--paramiko/message.py2
-rw-r--r--paramiko/packet.py10
-rw-r--r--paramiko/pipe.py6
-rw-r--r--paramiko/pkey.py8
-rw-r--r--paramiko/primes.py13
-rw-r--r--paramiko/rsakey.py14
-rw-r--r--paramiko/sftp_attr.py50
-rw-r--r--paramiko/sftp_client.py10
-rw-r--r--paramiko/sftp_file.py12
-rw-r--r--paramiko/sftp_handle.py20
-rw-r--r--paramiko/sftp_server.py12
-rw-r--r--paramiko/transport.py73
-rw-r--r--paramiko/util.py10
19 files changed, 182 insertions, 134 deletions
diff --git a/README b/README
index 280a7ade..56081722 100644
--- a/README
+++ b/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
+
diff --git a/paramiko/ber.py b/paramiko/ber.py
index 6a7823d8..e8d6d620 100644
--- a/paramiko/ber.py
+++ b/paramiko/ber.py
@@ -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):
diff --git a/paramiko/channel.py b/paramiko/channel.py
index 8a002339..ee2ec495 100644
--- a/paramiko/channel.py
+++ b/paramiko/channel.py
@@ -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):
diff --git a/paramiko/dsskey.py b/paramiko/dsskey.py
index 2b313723..dcb74115 100644
--- a/paramiko/dsskey.py
+++ b/paramiko/dsskey.py
@@ -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()
diff --git a/paramiko/file.py b/paramiko/file.py
index c29e7c45..43784745 100644
--- a/paramiko/file.py
+++ b/paramiko/file.py
@@ -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()
diff --git a/paramiko/kex_gex.py b/paramiko/kex_gex.py
index 994d76cb..3e322102 100644
--- a/paramiko/kex_gex.py
+++ b/paramiko/kex_gex.py
@@ -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:
diff --git a/paramiko/message.py b/paramiko/message.py
index 1d75a019..b110700d 100644
--- a/paramiko/message.py
+++ b/paramiko/message.py
@@ -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):
"""
diff --git a/paramiko/packet.py b/paramiko/packet.py
index 277d68e0..7e9afc78 100644
--- a/paramiko/packet.py
+++ b/paramiko/packet.py
@@ -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)
diff --git a/paramiko/pipe.py b/paramiko/pipe.py
index cc28f43a..4048a14f 100644
--- a/paramiko/pipe.py
+++ b/paramiko/pipe.py
@@ -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):
diff --git a/paramiko/pkey.py b/paramiko/pkey.py
index 75db8e56..b6baf80b 100644
--- a/paramiko/pkey.py
+++ b/paramiko/pkey.py
@@ -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
diff --git a/paramiko/primes.py b/paramiko/primes.py
index 36773944..fa0175d8 100644
--- a/paramiko/primes.py
+++ b/paramiko/primes.py
@@ -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:
diff --git a/paramiko/rsakey.py b/paramiko/rsakey.py
index 780ea1b6..754e412a 100644
--- a/paramiko/rsakey.py
+++ b/paramiko/rsakey.py
@@ -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) ]
diff --git a/paramiko/sftp_attr.py b/paramiko/sftp_attr.py
index eae7c993..0548dcd1 100644
--- a/paramiko/sftp_attr.py
+++ b/paramiko/sftp_attr.py
@@ -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)
diff --git a/paramiko/sftp_client.py b/paramiko/sftp_client.py
index 2fe89e91..ba37455f 100644
--- a/paramiko/sftp_client.py
+++ b/paramiko/sftp_client.py
@@ -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():
diff --git a/paramiko/sftp_file.py b/paramiko/sftp_file.py
index f224f025..bdc60c7a 100644
--- a/paramiko/sftp_file.py
+++ b/paramiko/sftp_file.py
@@ -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:
diff --git a/paramiko/sftp_handle.py b/paramiko/sftp_handle.py
index e1d93e9f..11a72c2b 100644
--- a/paramiko/sftp_handle.py
+++ b/paramiko/sftp_handle.py
@@ -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)
diff --git a/paramiko/sftp_server.py b/paramiko/sftp_server.py
index 7b634838..253cffb3 100644
--- a/paramiko/sftp_server.py
+++ b/paramiko/sftp_server.py
@@ -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)
diff --git a/paramiko/transport.py b/paramiko/transport.py
index 8714a960..abc1ea96 100644
--- a/paramiko/transport.py
+++ b/paramiko/transport.py
@@ -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]
diff --git a/paramiko/util.py b/paramiko/util.py
index abab825d..77eee3f6 100644
--- a/paramiko/util.py
+++ b/paramiko/util.py
@@ -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