Convert and detect types properly, use helper constants, use StringIO and range
This commit is contained in:
parent
2d738fa08b
commit
0b7d0cf0a2
|
@ -49,13 +49,13 @@ class BER(object):
|
||||||
def decode_next(self):
|
def decode_next(self):
|
||||||
if self.idx >= len(self.content):
|
if self.idx >= len(self.content):
|
||||||
return None
|
return None
|
||||||
ident = ord(self.content[self.idx])
|
ident = byte_ord(self.content[self.idx])
|
||||||
self.idx += 1
|
self.idx += 1
|
||||||
if (ident & 31) == 31:
|
if (ident & 31) == 31:
|
||||||
# identifier > 30
|
# identifier > 30
|
||||||
ident = 0
|
ident = 0
|
||||||
while self.idx < len(self.content):
|
while self.idx < len(self.content):
|
||||||
t = ord(self.content[self.idx])
|
t = byte_ord(self.content[self.idx])
|
||||||
self.idx += 1
|
self.idx += 1
|
||||||
ident = (ident << 7) | (t & 0x7f)
|
ident = (ident << 7) | (t & 0x7f)
|
||||||
if not (t & 0x80):
|
if not (t & 0x80):
|
||||||
|
@ -63,7 +63,7 @@ class BER(object):
|
||||||
if self.idx >= len(self.content):
|
if self.idx >= len(self.content):
|
||||||
return None
|
return None
|
||||||
# now fetch length
|
# now fetch length
|
||||||
size = ord(self.content[self.idx])
|
size = byte_ord(self.content[self.idx])
|
||||||
self.idx += 1
|
self.idx += 1
|
||||||
if size & 0x80:
|
if size & 0x80:
|
||||||
# more complimicated...
|
# more complimicated...
|
||||||
|
@ -102,12 +102,12 @@ class BER(object):
|
||||||
|
|
||||||
def encode_tlv(self, ident, val):
|
def encode_tlv(self, ident, val):
|
||||||
# no need to support ident > 31 here
|
# no need to support ident > 31 here
|
||||||
self.content += chr(ident)
|
self.content += byte_chr(ident)
|
||||||
if len(val) > 0x7f:
|
if len(val) > 0x7f:
|
||||||
lenstr = util.deflate_long(len(val))
|
lenstr = util.deflate_long(len(val))
|
||||||
self.content += chr(0x80 + len(lenstr)) + lenstr
|
self.content += byte_chr(0x80 + len(lenstr)) + lenstr
|
||||||
else:
|
else:
|
||||||
self.content += chr(len(val))
|
self.content += byte_chr(len(val))
|
||||||
self.content += val
|
self.content += val
|
||||||
|
|
||||||
def encode(self, x):
|
def encode(self, x):
|
||||||
|
|
|
@ -969,7 +969,7 @@ class Channel (object):
|
||||||
self.transport._send_user_message(m)
|
self.transport._send_user_message(m)
|
||||||
|
|
||||||
def _feed(self, m):
|
def _feed(self, m):
|
||||||
if type(m) is str:
|
if isinstance(m, bytes_type):
|
||||||
# passed from _feed_extended
|
# passed from _feed_extended
|
||||||
s = m
|
s = m
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -335,7 +335,7 @@ class SSHClient (object):
|
||||||
|
|
||||||
if key_filename is None:
|
if key_filename is None:
|
||||||
key_filenames = []
|
key_filenames = []
|
||||||
elif isinstance(key_filename, (str, unicode)):
|
elif isinstance(key_filename, string_types):
|
||||||
key_filenames = [ key_filename ]
|
key_filenames = [ key_filename ]
|
||||||
else:
|
else:
|
||||||
key_filenames = key_filename
|
key_filenames = key_filename
|
||||||
|
|
|
@ -96,15 +96,15 @@ class KexGex (object):
|
||||||
# generate an "x" (1 < x < (p-1)/2).
|
# generate an "x" (1 < x < (p-1)/2).
|
||||||
q = (self.p - 1) // 2
|
q = (self.p - 1) // 2
|
||||||
qnorm = util.deflate_long(q, 0)
|
qnorm = util.deflate_long(q, 0)
|
||||||
qhbyte = ord(qnorm[0])
|
qhbyte = byte_ord(qnorm[0])
|
||||||
byte_count = len(qnorm)
|
byte_count = len(qnorm)
|
||||||
qmask = 0xff
|
qmask = 0xff
|
||||||
while not (qhbyte & 0x80):
|
while not (qhbyte & 0x80):
|
||||||
qhbyte <<= 1
|
qhbyte <<= 1
|
||||||
qmask >>= 1
|
qmask >>= 1
|
||||||
while True:
|
while True:
|
||||||
x_bytes = chr(ord(x_bytes[0]) & qmask) + x_bytes[1:]
|
|
||||||
x_bytes = self.transport.rng.read(byte_count)
|
x_bytes = self.transport.rng.read(byte_count)
|
||||||
|
x_bytes = byte_mask(x_bytes[0], qmask) + x_bytes[1:]
|
||||||
x = util.inflate_long(x_bytes, 1)
|
x = util.inflate_long(x_bytes, 1)
|
||||||
if (x > 1) and (x < q):
|
if (x > 1) and (x < q):
|
||||||
break
|
break
|
||||||
|
|
|
@ -30,9 +30,10 @@ from paramiko.ssh_exception import SSHException
|
||||||
|
|
||||||
|
|
||||||
_MSG_KEXDH_INIT, _MSG_KEXDH_REPLY = range(30, 32)
|
_MSG_KEXDH_INIT, _MSG_KEXDH_REPLY = range(30, 32)
|
||||||
|
c_MSG_KEXDH_INIT, c_MSG_KEXDH_REPLY = [byte_chr(c) for c in range(30, 32)]
|
||||||
|
|
||||||
# draft-ietf-secsh-transport-09.txt, page 17
|
# draft-ietf-secsh-transport-09.txt, page 17
|
||||||
P = 0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFFL
|
P = 0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF
|
||||||
G = 2
|
G = 2
|
||||||
|
|
||||||
|
|
||||||
|
@ -42,9 +43,9 @@ class KexGroup1(object):
|
||||||
|
|
||||||
def __init__(self, transport):
|
def __init__(self, transport):
|
||||||
self.transport = transport
|
self.transport = transport
|
||||||
self.x = 0L
|
self.x = long_zero
|
||||||
self.e = 0L
|
self.e = long_zero
|
||||||
self.f = 0L
|
self.f = long_zero
|
||||||
|
|
||||||
def start_kex(self):
|
def start_kex(self):
|
||||||
self._generate_x()
|
self._generate_x()
|
||||||
|
@ -80,7 +81,7 @@ class KexGroup1(object):
|
||||||
# larger than q (but this is a tiny tiny subset of potential x).
|
# larger than q (but this is a tiny tiny subset of potential x).
|
||||||
while 1:
|
while 1:
|
||||||
x_bytes = self.transport.rng.read(128)
|
x_bytes = self.transport.rng.read(128)
|
||||||
x_bytes = chr(ord(x_bytes[0]) & 0x7f) + x_bytes[1:]
|
x_bytes = byte_mask(x_bytes[0], 0x7f) + x_bytes[1:]
|
||||||
if (x_bytes[:8] != '\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF') and \
|
if (x_bytes[:8] != '\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF') and \
|
||||||
(x_bytes[:8] != '\x00\x00\x00\x00\x00\x00\x00\x00'):
|
(x_bytes[:8] != '\x00\x00\x00\x00\x00\x00\x00\x00'):
|
||||||
break
|
break
|
||||||
|
|
|
@ -38,6 +38,7 @@ try:
|
||||||
except ImportError:
|
except ImportError:
|
||||||
from Crypto.Hash.HMAC import HMAC
|
from Crypto.Hash.HMAC import HMAC
|
||||||
|
|
||||||
|
|
||||||
def compute_hmac(key, message, digest_class):
|
def compute_hmac(key, message, digest_class):
|
||||||
return HMAC(key, message, digest_class).digest()
|
return HMAC(key, message, digest_class).digest()
|
||||||
|
|
||||||
|
@ -66,7 +67,7 @@ class Packetizer (object):
|
||||||
self.__dump_packets = False
|
self.__dump_packets = False
|
||||||
self.__need_rekey = False
|
self.__need_rekey = False
|
||||||
self.__init_count = 0
|
self.__init_count = 0
|
||||||
self.__remainder = ''
|
self.__remainder = bytes()
|
||||||
|
|
||||||
# used for noticing when to re-key:
|
# used for noticing when to re-key:
|
||||||
self.__sent_bytes = 0
|
self.__sent_bytes = 0
|
||||||
|
@ -90,8 +91,8 @@ class Packetizer (object):
|
||||||
self.__mac_key_in = ''
|
self.__mac_key_in = ''
|
||||||
self.__compress_engine_out = None
|
self.__compress_engine_out = None
|
||||||
self.__compress_engine_in = None
|
self.__compress_engine_in = None
|
||||||
self.__sequence_number_out = 0L
|
self.__sequence_number_out = long_zero
|
||||||
self.__sequence_number_in = 0L
|
self.__sequence_number_in = long_zero
|
||||||
|
|
||||||
# lock around outbound writes (packet computation)
|
# lock around outbound writes (packet computation)
|
||||||
self.__write_lock = threading.RLock()
|
self.__write_lock = threading.RLock()
|
||||||
|
@ -196,7 +197,7 @@ class Packetizer (object):
|
||||||
@raise EOFError: if the socket was closed before all the bytes could
|
@raise EOFError: if the socket was closed before all the bytes could
|
||||||
be read
|
be read
|
||||||
"""
|
"""
|
||||||
out = ''
|
out = bytes()
|
||||||
# handle over-reading from reading the banner line
|
# handle over-reading from reading the banner line
|
||||||
if len(self.__remainder) > 0:
|
if len(self.__remainder) > 0:
|
||||||
out = self.__remainder[:n]
|
out = self.__remainder[:n]
|
||||||
|
@ -275,22 +276,22 @@ class Packetizer (object):
|
||||||
line, so it's okay to attempt large reads.
|
line, so it's okay to attempt large reads.
|
||||||
"""
|
"""
|
||||||
buf = self.__remainder
|
buf = self.__remainder
|
||||||
while not '\n' in buf:
|
while not newline_byte in buf:
|
||||||
buf += self._read_timeout(timeout)
|
buf += self._read_timeout(timeout)
|
||||||
n = buf.index('\n')
|
n = buf.index(newline_byte)
|
||||||
self.__remainder = buf[n+1:]
|
self.__remainder = buf[n+1:]
|
||||||
buf = buf[:n]
|
buf = buf[:n]
|
||||||
if (len(buf) > 0) and (buf[-1] == '\r'):
|
if (len(buf) > 0) and (buf[-1] == cr_byte):
|
||||||
buf = buf[:-1]
|
buf = buf[:-1]
|
||||||
return buf
|
return u(buf)
|
||||||
|
|
||||||
def send_message(self, data):
|
def send_message(self, data):
|
||||||
"""
|
"""
|
||||||
Write a block of data using the current cipher, as an SSH block.
|
Write a block of data using the current cipher, as an SSH block.
|
||||||
"""
|
"""
|
||||||
# encrypt this sucka
|
# encrypt this sucka
|
||||||
data = str(data)
|
data = asbytes(data)
|
||||||
cmd = ord(data[0])
|
cmd = byte_ord(data[0])
|
||||||
if cmd in MSG_NAMES:
|
if cmd in MSG_NAMES:
|
||||||
cmd_name = MSG_NAMES[cmd]
|
cmd_name = MSG_NAMES[cmd]
|
||||||
else:
|
else:
|
||||||
|
@ -312,7 +313,7 @@ class Packetizer (object):
|
||||||
if self.__block_engine_out != None:
|
if self.__block_engine_out != None:
|
||||||
payload = struct.pack('>I', self.__sequence_number_out) + packet
|
payload = struct.pack('>I', self.__sequence_number_out) + packet
|
||||||
out += compute_hmac(self.__mac_key_out, payload, self.__mac_engine_out)[:self.__mac_size_out]
|
out += compute_hmac(self.__mac_key_out, payload, self.__mac_engine_out)[:self.__mac_size_out]
|
||||||
self.__sequence_number_out = (self.__sequence_number_out + 1) & 0xffffffffL
|
self.__sequence_number_out = (self.__sequence_number_out + 1) & xffffffff
|
||||||
self.write_all(out)
|
self.write_all(out)
|
||||||
|
|
||||||
self.__sent_bytes += len(out)
|
self.__sent_bytes += len(out)
|
||||||
|
@ -361,7 +362,7 @@ class Packetizer (object):
|
||||||
my_mac = compute_hmac(self.__mac_key_in, mac_payload, self.__mac_engine_in)[:self.__mac_size_in]
|
my_mac = compute_hmac(self.__mac_key_in, mac_payload, self.__mac_engine_in)[:self.__mac_size_in]
|
||||||
if my_mac != mac:
|
if my_mac != mac:
|
||||||
raise SSHException('Mismatched MAC')
|
raise SSHException('Mismatched MAC')
|
||||||
padding = ord(packet[0])
|
padding = byte_ord(packet[0])
|
||||||
payload = packet[1:packet_size - padding]
|
payload = packet[1:packet_size - padding]
|
||||||
|
|
||||||
if self.__dump_packets:
|
if self.__dump_packets:
|
||||||
|
@ -372,7 +373,7 @@ class Packetizer (object):
|
||||||
|
|
||||||
msg = Message(payload[1:])
|
msg = Message(payload[1:])
|
||||||
msg.seqno = self.__sequence_number_in
|
msg.seqno = self.__sequence_number_in
|
||||||
self.__sequence_number_in = (self.__sequence_number_in + 1) & 0xffffffffL
|
self.__sequence_number_in = (self.__sequence_number_in + 1) & xffffffff
|
||||||
|
|
||||||
# check for rekey
|
# check for rekey
|
||||||
raw_packet_size = packet_size + self.__mac_size_in + 4
|
raw_packet_size = packet_size + self.__mac_size_in + 4
|
||||||
|
@ -395,7 +396,7 @@ class Packetizer (object):
|
||||||
self.__received_packets_overflow = 0
|
self.__received_packets_overflow = 0
|
||||||
self._trigger_rekey()
|
self._trigger_rekey()
|
||||||
|
|
||||||
cmd = ord(payload[0])
|
cmd = byte_ord(payload[0])
|
||||||
if cmd in MSG_NAMES:
|
if cmd in MSG_NAMES:
|
||||||
cmd_name = MSG_NAMES[cmd]
|
cmd_name = MSG_NAMES[cmd]
|
||||||
else:
|
else:
|
||||||
|
@ -493,7 +494,7 @@ class Packetizer (object):
|
||||||
if self.__sdctr_out or self.__block_engine_out is None:
|
if self.__sdctr_out or self.__block_engine_out is None:
|
||||||
# cute trick i caught openssh doing: if we're not encrypting or SDCTR mode (RFC4344),
|
# cute trick i caught openssh doing: if we're not encrypting or SDCTR mode (RFC4344),
|
||||||
# don't waste random bytes for the padding
|
# don't waste random bytes for the padding
|
||||||
packet += (chr(0) * padding)
|
packet += (zero_byte * padding)
|
||||||
else:
|
else:
|
||||||
packet += rng.read(padding)
|
packet += rng.read(padding)
|
||||||
return packet
|
return packet
|
||||||
|
|
|
@ -64,7 +64,7 @@ class PosixPipe (object):
|
||||||
if self._set or self._closed:
|
if self._set or self._closed:
|
||||||
return
|
return
|
||||||
self._set = True
|
self._set = True
|
||||||
os.write(self._wfd, '*')
|
os.write(self._wfd, b('*'))
|
||||||
|
|
||||||
def set_forever (self):
|
def set_forever (self):
|
||||||
self._forever = True
|
self._forever = True
|
||||||
|
@ -110,7 +110,7 @@ class WindowsPipe (object):
|
||||||
if self._set or self._closed:
|
if self._set or self._closed:
|
||||||
return
|
return
|
||||||
self._set = True
|
self._set = True
|
||||||
self._wsock.send('*')
|
self._wsock.send(b('*'))
|
||||||
|
|
||||||
def set_forever (self):
|
def set_forever (self):
|
||||||
self._forever = True
|
self._forever = True
|
||||||
|
|
|
@ -352,9 +352,9 @@ class PKey (object):
|
||||||
|
|
||||||
@raise IOError: if there was an error writing the file.
|
@raise IOError: if there was an error writing the file.
|
||||||
"""
|
"""
|
||||||
f = open(filename, 'w', 0600)
|
f = open(filename, 'w', o600)
|
||||||
# grrr... the mode doesn't always take hold
|
# grrr... the mode doesn't always take hold
|
||||||
os.chmod(filename, 0600)
|
os.chmod(filename, o600)
|
||||||
self._write_private_key(tag, f, data, password)
|
self._write_private_key(tag, f, data, password)
|
||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ def _generate_prime(bits, rng):
|
||||||
# loop catches the case where we increment n into a higher bit-range
|
# loop catches the case where we increment n into a higher bit-range
|
||||||
x = rng.read((bits+7) // 8)
|
x = rng.read((bits+7) // 8)
|
||||||
if hbyte_mask > 0:
|
if hbyte_mask > 0:
|
||||||
x = chr(ord(x[0]) & hbyte_mask) + x[1:]
|
x = byte_mask(x[0], hbyte_mask) + x[1:]
|
||||||
n = util.inflate_long(x, 1)
|
n = util.inflate_long(x, 1)
|
||||||
n |= 1
|
n |= 1
|
||||||
n |= (1 << (bits - 1))
|
n |= (1 << (bits - 1))
|
||||||
|
@ -59,7 +59,7 @@ def _roll_random(rng, n):
|
||||||
while True:
|
while True:
|
||||||
x = rng.read(byte_count)
|
x = rng.read(byte_count)
|
||||||
if hbyte_mask > 0:
|
if hbyte_mask > 0:
|
||||||
x = chr(ord(x[0]) & hbyte_mask) + x[1:]
|
x = byte_mask(x[0], hbyte_mask) + x[1:]
|
||||||
num = util.inflate_long(x, 1)
|
num = util.inflate_long(x, 1)
|
||||||
if num < n:
|
if num < n:
|
||||||
break
|
break
|
||||||
|
|
|
@ -48,7 +48,7 @@ class InteractiveQuery (object):
|
||||||
self.instructions = instructions
|
self.instructions = instructions
|
||||||
self.prompts = []
|
self.prompts = []
|
||||||
for x in prompts:
|
for x in prompts:
|
||||||
if (type(x) is str) or (type(x) is unicode):
|
if isinstance(x, string_types):
|
||||||
self.add_prompt(x)
|
self.add_prompt(x)
|
||||||
else:
|
else:
|
||||||
self.add_prompt(x[0], x[1])
|
self.add_prompt(x[0], x[1])
|
||||||
|
|
|
@ -166,8 +166,8 @@ class BaseSFTP (object):
|
||||||
|
|
||||||
def _send_packet(self, t, packet):
|
def _send_packet(self, t, packet):
|
||||||
#self._log(DEBUG2, 'write: %s (len=%d)' % (CMD_NAMES.get(t, '0x%02x' % t), len(packet)))
|
#self._log(DEBUG2, 'write: %s (len=%d)' % (CMD_NAMES.get(t, '0x%02x' % t), len(packet)))
|
||||||
out = struct.pack('>I', len(packet) + 1) + chr(t) + packet
|
|
||||||
packet = asbytes(packet)
|
packet = asbytes(packet)
|
||||||
|
out = struct.pack('>I', len(packet) + 1) + byte_chr(t) + packet
|
||||||
if self.ultra_debug:
|
if self.ultra_debug:
|
||||||
self._log(DEBUG, util.format_binary(out, 'OUT: '))
|
self._log(DEBUG, util.format_binary(out, 'OUT: '))
|
||||||
self._write_all(out)
|
self._write_all(out)
|
||||||
|
@ -183,7 +183,7 @@ class BaseSFTP (object):
|
||||||
if self.ultra_debug:
|
if self.ultra_debug:
|
||||||
self._log(DEBUG, util.format_binary(data, 'IN: '));
|
self._log(DEBUG, util.format_binary(data, 'IN: '));
|
||||||
if size > 0:
|
if size > 0:
|
||||||
t = ord(data[0])
|
t = byte_ord(data[0])
|
||||||
#self._log(DEBUG2, 'read: %s (len=%d)' % (CMD_NAMES.get(t), '0x%02x' % t, len(data)-1))
|
#self._log(DEBUG2, 'read: %s (len=%d)' % (CMD_NAMES.get(t), '0x%02x' % t, len(data)-1))
|
||||||
return t, data[1:]
|
return t, data[1:]
|
||||||
return 0, ''
|
return 0, ''
|
||||||
|
|
|
@ -44,7 +44,7 @@ class SFTPAttributes (object):
|
||||||
FLAG_UIDGID = 2
|
FLAG_UIDGID = 2
|
||||||
FLAG_PERMISSIONS = 4
|
FLAG_PERMISSIONS = 4
|
||||||
FLAG_AMTIME = 8
|
FLAG_AMTIME = 8
|
||||||
FLAG_EXTENDED = 0x80000000L
|
FLAG_EXTENDED = x80000000
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
"""
|
"""
|
||||||
|
@ -194,13 +194,13 @@ class SFTPAttributes (object):
|
||||||
ks = 's'
|
ks = 's'
|
||||||
else:
|
else:
|
||||||
ks = '?'
|
ks = '?'
|
||||||
ks += self._rwx((self.st_mode & 0700) >> 6, self.st_mode & stat.S_ISUID)
|
ks += self._rwx((self.st_mode & o700) >> 6, self.st_mode & stat.S_ISUID)
|
||||||
ks += self._rwx((self.st_mode & 070) >> 3, self.st_mode & stat.S_ISGID)
|
ks += self._rwx((self.st_mode & o70) >> 3, self.st_mode & stat.S_ISGID)
|
||||||
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 = '?---------'
|
||||||
# compute display date
|
# compute display date
|
||||||
if (self.st_mtime is None) or (self.st_mtime == 0xffffffffL):
|
if (self.st_mtime is None) or (self.st_mtime == xffffffff):
|
||||||
# shouldn't really happen
|
# shouldn't really happen
|
||||||
datestr = '(unknown date)'
|
datestr = '(unknown date)'
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -285,7 +285,7 @@ class SFTPClient (BaseSFTP):
|
||||||
self._log(DEBUG, 'rename(%r, %r)' % (oldpath, newpath))
|
self._log(DEBUG, 'rename(%r, %r)' % (oldpath, newpath))
|
||||||
self._request(CMD_RENAME, oldpath, newpath)
|
self._request(CMD_RENAME, oldpath, newpath)
|
||||||
|
|
||||||
def mkdir(self, path, mode=0777):
|
def mkdir(self, path, mode=o777):
|
||||||
"""
|
"""
|
||||||
Create a folder (directory) named C{path} with numeric mode C{mode}.
|
Create a folder (directory) named C{path} with numeric mode C{mode}.
|
||||||
The default mode is 0777 (octal). On some systems, mode is ignored.
|
The default mode is 0777 (octal). On some systems, mode is ignored.
|
||||||
|
@ -698,7 +698,7 @@ class SFTPClient (BaseSFTP):
|
||||||
msg.add_int(item)
|
msg.add_int(item)
|
||||||
elif isinstance(item, long):
|
elif isinstance(item, long):
|
||||||
msg.add_int64(item)
|
msg.add_int64(item)
|
||||||
elif isinstance(item, str):
|
elif isinstance(item, string_types):
|
||||||
msg.add_string(item)
|
msg.add_string(item)
|
||||||
elif isinstance(item, SFTPAttributes):
|
elif isinstance(item, SFTPAttributes):
|
||||||
item._pack(msg)
|
item._pack(msg)
|
||||||
|
|
|
@ -183,7 +183,7 @@ class SFTPServer (BaseSFTP, SubsystemHandler):
|
||||||
msg.add_int(item)
|
msg.add_int(item)
|
||||||
elif type(item) is long:
|
elif type(item) is long:
|
||||||
msg.add_int64(item)
|
msg.add_int64(item)
|
||||||
elif type(item) is str:
|
elif isinstance(item, string_types):
|
||||||
msg.add_string(item)
|
msg.add_string(item)
|
||||||
elif type(item) is SFTPAttributes:
|
elif type(item) is SFTPAttributes:
|
||||||
item._pack(msg)
|
item._pack(msg)
|
||||||
|
@ -420,7 +420,7 @@ class SFTPServer (BaseSFTP, SubsystemHandler):
|
||||||
elif t == CMD_READLINK:
|
elif t == CMD_READLINK:
|
||||||
path = msg.get_text()
|
path = msg.get_text()
|
||||||
resp = self.server.readlink(path)
|
resp = self.server.readlink(path)
|
||||||
if type(resp) is str:
|
if isinstance(resp, string_types):
|
||||||
self._response(request_number, CMD_NAME, 1, resp, '', SFTPAttributes())
|
self._response(request_number, CMD_NAME, 1, resp, '', SFTPAttributes())
|
||||||
else:
|
else:
|
||||||
self._send_status(request_number, resp)
|
self._send_status(request_number, resp)
|
||||||
|
|
|
@ -376,7 +376,7 @@ class Transport (threading.Thread):
|
||||||
|
|
||||||
@rtype: str
|
@rtype: str
|
||||||
"""
|
"""
|
||||||
out = '<paramiko.Transport at %s' % hex(long(id(self)) & 0xffffffffL)
|
out = '<paramiko.Transport at %s' % hex(long(id(self)) & xffffffff)
|
||||||
if not self.active:
|
if not self.active:
|
||||||
out += ' (unconnected)'
|
out += ' (unconnected)'
|
||||||
else:
|
else:
|
||||||
|
@ -1553,12 +1553,12 @@ class Transport (threading.Thread):
|
||||||
# active=True occurs before the thread is launched, to avoid a race
|
# active=True occurs before the thread is launched, to avoid a race
|
||||||
_active_threads.append(self)
|
_active_threads.append(self)
|
||||||
if self.server_mode:
|
if self.server_mode:
|
||||||
self._log(DEBUG, 'starting thread (server mode): %s' % hex(long(id(self)) & 0xffffffffL))
|
self._log(DEBUG, 'starting thread (server mode): %s' % hex(long(id(self)) & xffffffff))
|
||||||
else:
|
else:
|
||||||
self._log(DEBUG, 'starting thread (client mode): %s' % hex(long(id(self)) & 0xffffffffL))
|
self._log(DEBUG, 'starting thread (client mode): %s' % hex(long(id(self)) & xffffffff))
|
||||||
try:
|
try:
|
||||||
try:
|
try:
|
||||||
self.packetizer.write_all(self.local_version + '\r\n')
|
self.packetizer.write_all(b(self.local_version + '\r\n'))
|
||||||
self._check_banner()
|
self._check_banner()
|
||||||
self._send_kex_init()
|
self._send_kex_init()
|
||||||
self._expect_packet(MSG_KEXINIT)
|
self._expect_packet(MSG_KEXINIT)
|
||||||
|
|
|
@ -48,60 +48,53 @@ if sys.version_info < (2,3):
|
||||||
|
|
||||||
def inflate_long(s, always_positive=False):
|
def inflate_long(s, always_positive=False):
|
||||||
"turns a normalized byte string into a long-int (adapted from Crypto.Util.number)"
|
"turns a normalized byte string into a long-int (adapted from Crypto.Util.number)"
|
||||||
out = 0L
|
out = long_zero
|
||||||
negative = 0
|
negative = 0
|
||||||
if not always_positive and (len(s) > 0) and (ord(s[0]) >= 0x80):
|
if not always_positive and (len(s) > 0) and (byte_ord(s[0]) >= 0x80):
|
||||||
negative = 1
|
negative = 1
|
||||||
if len(s) % 4:
|
if len(s) % 4:
|
||||||
filler = '\x00'
|
filler = zero_byte
|
||||||
if negative:
|
if negative:
|
||||||
filler = '\xff'
|
filler = max_byte
|
||||||
s = filler * (4 - len(s) % 4) + s
|
s = filler * (4 - len(s) % 4) + s
|
||||||
for i in range(0, len(s), 4):
|
for i in range(0, len(s), 4):
|
||||||
out = (out << 32) + struct.unpack('>I', s[i:i+4])[0]
|
out = (out << 32) + struct.unpack('>I', s[i:i+4])[0]
|
||||||
if negative:
|
if negative:
|
||||||
out -= (1L << (8 * len(s)))
|
out -= (long_one << (8 * len(s)))
|
||||||
return out
|
return out
|
||||||
|
|
||||||
|
deflate_zero = 0 if PY3 else zero_byte
|
||||||
|
deflate_ff = 0xff if PY3 else max_byte
|
||||||
|
|
||||||
def deflate_long(n, add_sign_padding=True):
|
def deflate_long(n, add_sign_padding=True):
|
||||||
"turns a long-int into a normalized byte string (adapted from Crypto.Util.number)"
|
"turns a long-int into a normalized byte string (adapted from Crypto.Util.number)"
|
||||||
# after much testing, this algorithm was deemed to be the fastest
|
# after much testing, this algorithm was deemed to be the fastest
|
||||||
s = ''
|
s = bytes()
|
||||||
n = long(n)
|
n = long(n)
|
||||||
while (n != 0) and (n != -1):
|
while (n != 0) and (n != -1):
|
||||||
s = struct.pack('>I', n & 0xffffffffL) + s
|
s = struct.pack('>I', n & xffffffff) + s
|
||||||
n = n >> 32
|
n = n >> 32
|
||||||
# strip off leading zeros, FFs
|
# strip off leading zeros, FFs
|
||||||
for i in enumerate(s):
|
for i in enumerate(s):
|
||||||
if (n == 0) and (i[1] != '\000'):
|
if (n == 0) and (i[1] != deflate_zero):
|
||||||
break
|
break
|
||||||
if (n == -1) and (i[1] != '\xff'):
|
if (n == -1) and (i[1] != deflate_ff):
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
# degenerate case, n was either 0 or -1
|
# degenerate case, n was either 0 or -1
|
||||||
i = (0,)
|
i = (0,)
|
||||||
if n == 0:
|
if n == 0:
|
||||||
s = '\000'
|
s = zero_byte
|
||||||
else:
|
else:
|
||||||
s = '\xff'
|
s = max_byte
|
||||||
s = s[i[0]:]
|
s = s[i[0]:]
|
||||||
if add_sign_padding:
|
if add_sign_padding:
|
||||||
if (n == 0) and (ord(s[0]) >= 0x80):
|
if (n == 0) and (byte_ord(s[0]) >= 0x80):
|
||||||
s = '\x00' + s
|
s = zero_byte + s
|
||||||
if (n == -1) and (ord(s[0]) < 0x80):
|
if (n == -1) and (byte_ord(s[0]) < 0x80):
|
||||||
s = '\xff' + s
|
s = max_byte + s
|
||||||
return s
|
return s
|
||||||
|
|
||||||
def format_binary_weird(data):
|
|
||||||
out = ''
|
|
||||||
for i in enumerate(data):
|
|
||||||
out += '%02X' % ord(i[1])
|
|
||||||
if i[0] % 2:
|
|
||||||
out += ' '
|
|
||||||
if i[0] % 16 == 15:
|
|
||||||
out += '\n'
|
|
||||||
return out
|
|
||||||
|
|
||||||
def format_binary(data, prefix=''):
|
def format_binary(data, prefix=''):
|
||||||
x = 0
|
x = 0
|
||||||
out = []
|
out = []
|
||||||
|
@ -113,8 +106,8 @@ def format_binary(data, prefix=''):
|
||||||
return [prefix + x for x in out]
|
return [prefix + x for x in out]
|
||||||
|
|
||||||
def format_binary_line(data):
|
def format_binary_line(data):
|
||||||
left = ' '.join(['%02X' % ord(c) for c in data])
|
left = ' '.join(['%02X' % byte_ord(c) for c in data])
|
||||||
right = ''.join([('.%c..' % c)[(ord(c)+63)//95] for c in data])
|
right = ''.join([('.%c..' % c)[(byte_ord(c)+63)//95] for c in data])
|
||||||
return '%-50s %s' % (left, right)
|
return '%-50s %s' % (left, right)
|
||||||
|
|
||||||
def hexify(s):
|
def hexify(s):
|
||||||
|
@ -126,17 +119,17 @@ def unhexify(s):
|
||||||
def safe_string(s):
|
def safe_string(s):
|
||||||
out = ''
|
out = ''
|
||||||
for c in s:
|
for c in s:
|
||||||
if (ord(c) >= 32) and (ord(c) <= 127):
|
if (byte_ord(c) >= 32) and (byte_ord(c) <= 127):
|
||||||
out += c
|
out += c
|
||||||
else:
|
else:
|
||||||
out += '%%%02X' % ord(c)
|
out += '%%%02X' % byte_ord(c)
|
||||||
return out
|
return out
|
||||||
|
|
||||||
# ''.join([['%%%02X' % ord(c), c][(ord(c) >= 32) and (ord(c) <= 127)] for c in s])
|
# ''.join([['%%%02X' % ord(c), c][(ord(c) >= 32) and (ord(c) <= 127)] for c in s])
|
||||||
|
|
||||||
def bit_length(n):
|
def bit_length(n):
|
||||||
norm = deflate_long(n, 0)
|
norm = deflate_long(n, 0)
|
||||||
hbyte = ord(norm[0])
|
hbyte = byte_ord(norm[0])
|
||||||
if hbyte == 0:
|
if hbyte == 0:
|
||||||
return 1
|
return 1
|
||||||
bitlen = len(norm) * 8
|
bitlen = len(norm) * 8
|
||||||
|
@ -298,15 +291,15 @@ class Counter (object):
|
||||||
"""Increament the counter and return the new value"""
|
"""Increament the counter and return the new value"""
|
||||||
i = self.blocksize - 1
|
i = self.blocksize - 1
|
||||||
while i > -1:
|
while i > -1:
|
||||||
c = self.value[i] = chr((ord(self.value[i]) + 1) % 256)
|
c = self.value[i] = byte_chr((byte_ord(self.value[i]) + 1) % 256)
|
||||||
if c != '\x00':
|
if c != zero_byte:
|
||||||
return self.value.tostring()
|
return self.value.tostring()
|
||||||
i -= 1
|
i -= 1
|
||||||
# counter reset
|
# counter reset
|
||||||
x = deflate_long(self.overflow, add_sign_padding=False)
|
x = deflate_long(self.overflow, add_sign_padding=False)
|
||||||
self.value = array.array('c', '\x00' * (self.blocksize - len(x)) + x)
|
self.value = array.array('c', zero_byte * (self.blocksize - len(x)) + x)
|
||||||
return self.value.tostring()
|
return self.value.tostring()
|
||||||
|
|
||||||
def new(cls, nbits, initial_value=1L, overflow=0L):
|
def new(cls, nbits, initial_value=long_one, overflow=long_zero):
|
||||||
return cls(nbits, initial_value=initial_value, overflow=overflow)
|
return cls(nbits, initial_value=initial_value, overflow=overflow)
|
||||||
new = classmethod(new)
|
new = classmethod(new)
|
||||||
|
|
|
@ -32,7 +32,7 @@ class LoopSocket (object):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.__in_buffer = ''
|
self.__in_buffer = bytes()
|
||||||
self.__lock = threading.Lock()
|
self.__lock = threading.Lock()
|
||||||
self.__cv = threading.Condition(self.__lock)
|
self.__cv = threading.Condition(self.__lock)
|
||||||
self.__timeout = None
|
self.__timeout = None
|
||||||
|
@ -42,7 +42,7 @@ class LoopSocket (object):
|
||||||
self.__unlink()
|
self.__unlink()
|
||||||
try:
|
try:
|
||||||
self.__lock.acquire()
|
self.__lock.acquire()
|
||||||
self.__in_buffer = ''
|
self.__in_buffer = bytes()
|
||||||
finally:
|
finally:
|
||||||
self.__lock.release()
|
self.__lock.release()
|
||||||
|
|
||||||
|
|
|
@ -104,7 +104,7 @@ class StubSFTPServer (SFTPServerInterface):
|
||||||
else:
|
else:
|
||||||
# os.open() defaults to 0777 which is
|
# os.open() defaults to 0777 which is
|
||||||
# an odd default mode for files
|
# an odd default mode for files
|
||||||
fd = os.open(path, flags, 0666)
|
fd = os.open(path, flags, o666)
|
||||||
except OSError:
|
except OSError:
|
||||||
e = sys.exc_info()[1]
|
e = sys.exc_info()[1]
|
||||||
return SFTPServer.convert_errno(e.errno)
|
return SFTPServer.convert_errno(e.errno)
|
||||||
|
|
|
@ -32,6 +32,11 @@ from paramiko import OPEN_SUCCEEDED, OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED
|
||||||
from tests.loop import LoopSocket
|
from tests.loop import LoopSocket
|
||||||
from tests.util import test_path
|
from tests.util import test_path
|
||||||
|
|
||||||
|
try:
|
||||||
|
_pwd = u'\u2022'
|
||||||
|
except Exception:
|
||||||
|
_pwd = '\u2022'
|
||||||
|
|
||||||
|
|
||||||
class NullServer (ServerInterface):
|
class NullServer (ServerInterface):
|
||||||
paranoid_did_password = False
|
paranoid_did_password = False
|
||||||
|
@ -65,7 +70,7 @@ class NullServer (ServerInterface):
|
||||||
if self.paranoid_did_public_key:
|
if self.paranoid_did_public_key:
|
||||||
return AUTH_SUCCESSFUL
|
return AUTH_SUCCESSFUL
|
||||||
return AUTH_PARTIALLY_SUCCESSFUL
|
return AUTH_PARTIALLY_SUCCESSFUL
|
||||||
if (username == 'utf8') and (password == u'\u2022'):
|
if (username == 'utf8') and (password == _pwd):
|
||||||
return AUTH_SUCCESSFUL
|
return AUTH_SUCCESSFUL
|
||||||
if (username == 'non-utf8') and (password == '\xff'):
|
if (username == 'non-utf8') and (password == '\xff'):
|
||||||
return AUTH_SUCCESSFUL
|
return AUTH_SUCCESSFUL
|
||||||
|
@ -203,7 +208,7 @@ class AuthTest (unittest.TestCase):
|
||||||
"""
|
"""
|
||||||
self.start_server()
|
self.start_server()
|
||||||
self.tc.connect(hostkey=self.public_host_key)
|
self.tc.connect(hostkey=self.public_host_key)
|
||||||
remain = self.tc.auth_password('utf8', u'\u2022')
|
remain = self.tc.auth_password('utf8', _pwd)
|
||||||
self.assertEquals([], remain)
|
self.assertEquals([], remain)
|
||||||
self.verify_finished()
|
self.verify_finished()
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ from paramiko.common import *
|
||||||
|
|
||||||
class FakeRng (object):
|
class FakeRng (object):
|
||||||
def read(self, n):
|
def read(self, n):
|
||||||
return chr(0xcc) * n
|
return byte_chr(0xcc) * n
|
||||||
|
|
||||||
|
|
||||||
class FakeKey (object):
|
class FakeKey (object):
|
||||||
|
@ -44,7 +44,7 @@ class FakeKey (object):
|
||||||
|
|
||||||
|
|
||||||
class FakeModulusPack (object):
|
class FakeModulusPack (object):
|
||||||
P = 0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFFL
|
P = 0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF
|
||||||
G = 2
|
G = 2
|
||||||
def get_modulus(self, min, ask, max):
|
def get_modulus(self, min, ask, max):
|
||||||
return self.G, self.P
|
return self.G, self.P
|
||||||
|
@ -78,7 +78,7 @@ class FakeTransport (object):
|
||||||
|
|
||||||
class KexTest (unittest.TestCase):
|
class KexTest (unittest.TestCase):
|
||||||
|
|
||||||
K = 14730343317708716439807310032871972459448364195094179797249681733965528989482751523943515690110179031004049109375612685505881911274101441415545039654102474376472240501616988799699744135291070488314748284283496055223852115360852283821334858541043710301057312858051901453919067023103730011648890038847384890504L
|
K = 14730343317708716439807310032871972459448364195094179797249681733965528989482751523943515690110179031004049109375612685505881911274101441415545039654102474376472240501616988799699744135291070488314748284283496055223852115360852283821334858541043710301057312858051901453919067023103730011648890038847384890504
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
pass
|
pass
|
||||||
|
|
|
@ -99,7 +99,7 @@ class KeyTest (unittest.TestCase):
|
||||||
self.assertEquals(PUB_RSA.split()[1], key.get_base64())
|
self.assertEquals(PUB_RSA.split()[1], key.get_base64())
|
||||||
self.assertEquals(1024, key.get_bits())
|
self.assertEquals(1024, key.get_bits())
|
||||||
|
|
||||||
s = StringIO.StringIO()
|
s = StringIO()
|
||||||
key.write_private_key(s)
|
key.write_private_key(s)
|
||||||
self.assertEquals(RSA_PRIVATE_OUT, s.getvalue())
|
self.assertEquals(RSA_PRIVATE_OUT, s.getvalue())
|
||||||
s.seek(0)
|
s.seek(0)
|
||||||
|
@ -124,7 +124,7 @@ class KeyTest (unittest.TestCase):
|
||||||
self.assertEquals(PUB_DSS.split()[1], key.get_base64())
|
self.assertEquals(PUB_DSS.split()[1], key.get_base64())
|
||||||
self.assertEquals(1024, key.get_bits())
|
self.assertEquals(1024, key.get_bits())
|
||||||
|
|
||||||
s = StringIO.StringIO()
|
s = StringIO()
|
||||||
key.write_private_key(s)
|
key.write_private_key(s)
|
||||||
self.assertEquals(DSS_PRIVATE_OUT, s.getvalue())
|
self.assertEquals(DSS_PRIVATE_OUT, s.getvalue())
|
||||||
s.seek(0)
|
s.seek(0)
|
||||||
|
@ -207,7 +207,7 @@ class KeyTest (unittest.TestCase):
|
||||||
self.assertEquals(PUB_ECDSA.split()[1], key.get_base64())
|
self.assertEquals(PUB_ECDSA.split()[1], key.get_base64())
|
||||||
self.assertEquals(256, key.get_bits())
|
self.assertEquals(256, key.get_bits())
|
||||||
|
|
||||||
s = StringIO.StringIO()
|
s = StringIO()
|
||||||
key.write_private_key(s)
|
key.write_private_key(s)
|
||||||
self.assertEquals(ECDSA_PRIVATE_OUT, s.getvalue())
|
self.assertEquals(ECDSA_PRIVATE_OUT, s.getvalue())
|
||||||
s.seek(0)
|
s.seek(0)
|
||||||
|
|
|
@ -71,7 +71,10 @@ FOLDER = os.environ.get('TEST_FOLDER', 'temp-testing000')
|
||||||
sftp = None
|
sftp = None
|
||||||
tc = None
|
tc = None
|
||||||
g_big_file_test = True
|
g_big_file_test = True
|
||||||
|
try:
|
||||||
|
unicode_folder = u'\u00fcnic\u00f8de'
|
||||||
|
except SyntaxError:
|
||||||
|
unicode_folder = '\u00fcnic\u00f8de'
|
||||||
|
|
||||||
def get_sftp():
|
def get_sftp():
|
||||||
global sftp
|
global sftp
|
||||||
|
@ -141,7 +144,7 @@ class SFTPTest (unittest.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
global FOLDER
|
global FOLDER
|
||||||
for i in xrange(1000):
|
for i in range(1000):
|
||||||
FOLDER = FOLDER[:-3] + '%03d' % i
|
FOLDER = FOLDER[:-3] + '%03d' % i
|
||||||
try:
|
try:
|
||||||
sftp.mkdir(FOLDER)
|
sftp.mkdir(FOLDER)
|
||||||
|
@ -236,7 +239,7 @@ class SFTPTest (unittest.TestCase):
|
||||||
pass
|
pass
|
||||||
f = sftp.open(FOLDER + '/second.txt', 'r')
|
f = sftp.open(FOLDER + '/second.txt', 'r')
|
||||||
f.seek(-6, f.SEEK_END)
|
f.seek(-6, f.SEEK_END)
|
||||||
self.assertEqual(f.read(4), 'tent')
|
self.assertEqual(u(f.read(4)), 'tent')
|
||||||
f.close()
|
f.close()
|
||||||
finally:
|
finally:
|
||||||
try:
|
try:
|
||||||
|
@ -301,16 +304,16 @@ class SFTPTest (unittest.TestCase):
|
||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
stat = sftp.stat(FOLDER + '/special')
|
stat = sftp.stat(FOLDER + '/special')
|
||||||
sftp.chmod(FOLDER + '/special', (stat.st_mode & ~0777) | 0600)
|
sftp.chmod(FOLDER + '/special', (stat.st_mode & ~o777) | o600)
|
||||||
stat = sftp.stat(FOLDER + '/special')
|
stat = sftp.stat(FOLDER + '/special')
|
||||||
expected_mode = 0600
|
expected_mode = o600
|
||||||
if sys.platform == 'win32':
|
if sys.platform == 'win32':
|
||||||
# chmod not really functional on windows
|
# chmod not really functional on windows
|
||||||
expected_mode = 0666
|
expected_mode = o666
|
||||||
if sys.platform == 'cygwin':
|
if sys.platform == 'cygwin':
|
||||||
# even worse.
|
# even worse.
|
||||||
expected_mode = 0644
|
expected_mode = o644
|
||||||
self.assertEqual(stat.st_mode & 0777, expected_mode)
|
self.assertEqual(stat.st_mode & o777, expected_mode)
|
||||||
self.assertEqual(stat.st_size, 1024)
|
self.assertEqual(stat.st_size, 1024)
|
||||||
|
|
||||||
mtime = stat.st_mtime - 3600
|
mtime = stat.st_mtime - 3600
|
||||||
|
@ -341,17 +344,17 @@ class SFTPTest (unittest.TestCase):
|
||||||
|
|
||||||
f = sftp.open(FOLDER + '/special', 'r+')
|
f = sftp.open(FOLDER + '/special', 'r+')
|
||||||
stat = f.stat()
|
stat = f.stat()
|
||||||
f.chmod((stat.st_mode & ~0777) | 0600)
|
f.chmod((stat.st_mode & ~o777) | o600)
|
||||||
stat = f.stat()
|
stat = f.stat()
|
||||||
|
|
||||||
expected_mode = 0600
|
expected_mode = o600
|
||||||
if sys.platform == 'win32':
|
if sys.platform == 'win32':
|
||||||
# chmod not really functional on windows
|
# chmod not really functional on windows
|
||||||
expected_mode = 0666
|
expected_mode = o666
|
||||||
if sys.platform == 'cygwin':
|
if sys.platform == 'cygwin':
|
||||||
# even worse.
|
# even worse.
|
||||||
expected_mode = 0644
|
expected_mode = o644
|
||||||
self.assertEqual(stat.st_mode & 0777, expected_mode)
|
self.assertEqual(stat.st_mode & o777, expected_mode)
|
||||||
self.assertEqual(stat.st_size, 1024)
|
self.assertEqual(stat.st_size, 1024)
|
||||||
|
|
||||||
mtime = stat.st_mtime - 3600
|
mtime = stat.st_mtime - 3600
|
||||||
|
@ -643,7 +646,7 @@ class SFTPTest (unittest.TestCase):
|
||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
sftp.rename(FOLDER + '/something', FOLDER + u'/\u00fcnic\u00f8de')
|
sftp.rename(FOLDER + '/something', FOLDER + '/' + unicode_folder)
|
||||||
sftp.open(FOLDER + '/\xc3\xbcnic\xc3\xb8\x64\x65', 'r')
|
sftp.open(FOLDER + '/\xc3\xbcnic\xc3\xb8\x64\x65', 'r')
|
||||||
except Exception:
|
except Exception:
|
||||||
e = sys.exc_info()[1]
|
e = sys.exc_info()[1]
|
||||||
|
@ -651,16 +654,16 @@ class SFTPTest (unittest.TestCase):
|
||||||
sftp.unlink(FOLDER + '/\xc3\xbcnic\xc3\xb8\x64\x65')
|
sftp.unlink(FOLDER + '/\xc3\xbcnic\xc3\xb8\x64\x65')
|
||||||
|
|
||||||
def test_L_utf8_chdir(self):
|
def test_L_utf8_chdir(self):
|
||||||
sftp.mkdir(FOLDER + u'\u00fcnic\u00f8de')
|
sftp.mkdir(FOLDER + '/' + unicode_folder)
|
||||||
try:
|
try:
|
||||||
sftp.chdir(FOLDER + u'\u00fcnic\u00f8de')
|
sftp.chdir(FOLDER + '/' + unicode_folder)
|
||||||
f = sftp.open('something', 'w')
|
f = sftp.open('something', 'w')
|
||||||
f.write('okay')
|
f.write('okay')
|
||||||
f.close()
|
f.close()
|
||||||
sftp.unlink('something')
|
sftp.unlink('something')
|
||||||
finally:
|
finally:
|
||||||
sftp.chdir(None)
|
sftp.chdir(None)
|
||||||
sftp.rmdir(FOLDER + u'\u00fcnic\u00f8de')
|
sftp.rmdir(FOLDER + '/' + unicode_folder)
|
||||||
|
|
||||||
def test_M_bad_readv(self):
|
def test_M_bad_readv(self):
|
||||||
"""
|
"""
|
||||||
|
@ -733,10 +736,16 @@ class SFTPTest (unittest.TestCase):
|
||||||
Send an empty file and confirm it is sent.
|
Send an empty file and confirm it is sent.
|
||||||
"""
|
"""
|
||||||
target = FOLDER + '/empty file.txt'
|
target = FOLDER + '/empty file.txt'
|
||||||
stream = StringIO.StringIO()
|
stream = StringIO()
|
||||||
try:
|
try:
|
||||||
attrs = sftp.putfo(stream, target)
|
attrs = sftp.putfo(stream, target)
|
||||||
# the returned attributes should not be null
|
# the returned attributes should not be null
|
||||||
self.assertNotEqual(attrs, None)
|
self.assertNotEqual(attrs, None)
|
||||||
finally:
|
finally:
|
||||||
sftp.remove(target)
|
sftp.remove(target)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
SFTPTest.init_loopback()
|
||||||
|
from unittest import main
|
||||||
|
main()
|
||||||
|
|
|
@ -46,7 +46,7 @@ class BigSFTPTest (unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
global FOLDER
|
global FOLDER
|
||||||
sftp = get_sftp()
|
sftp = get_sftp()
|
||||||
for i in xrange(1000):
|
for i in range(1000):
|
||||||
FOLDER = FOLDER[:-3] + '%03d' % i
|
FOLDER = FOLDER[:-3] + '%03d' % i
|
||||||
try:
|
try:
|
||||||
sftp.mkdir(FOLDER)
|
sftp.mkdir(FOLDER)
|
||||||
|
@ -69,7 +69,7 @@ class BigSFTPTest (unittest.TestCase):
|
||||||
f = sftp.open('%s/file%d.txt' % (FOLDER, i), 'w', 1)
|
f = sftp.open('%s/file%d.txt' % (FOLDER, i), 'w', 1)
|
||||||
f.write('this is file #%d.\n' % i)
|
f.write('this is file #%d.\n' % i)
|
||||||
f.close()
|
f.close()
|
||||||
sftp.chmod('%s/file%d.txt' % (FOLDER, i), 0660)
|
sftp.chmod('%s/file%d.txt' % (FOLDER, i), o660)
|
||||||
|
|
||||||
# now make sure every file is there, by creating a list of filenmes
|
# now make sure every file is there, by creating a list of filenmes
|
||||||
# and reading them in random order.
|
# and reading them in random order.
|
||||||
|
@ -124,7 +124,7 @@ class BigSFTPTest (unittest.TestCase):
|
||||||
write a 1MB file, with no linefeeds, using pipelining.
|
write a 1MB file, with no linefeeds, using pipelining.
|
||||||
"""
|
"""
|
||||||
sftp = get_sftp()
|
sftp = get_sftp()
|
||||||
kblob = ''.join([struct.pack('>H', n) for n in xrange(512)])
|
kblob = ''.join([struct.pack('>H', n) for n in range(512)])
|
||||||
start = time.time()
|
start = time.time()
|
||||||
try:
|
try:
|
||||||
f = sftp.open('%s/hongry.txt' % FOLDER, 'w')
|
f = sftp.open('%s/hongry.txt' % FOLDER, 'w')
|
||||||
|
@ -165,7 +165,7 @@ class BigSFTPTest (unittest.TestCase):
|
||||||
|
|
||||||
def test_4_prefetch_seek(self):
|
def test_4_prefetch_seek(self):
|
||||||
sftp = get_sftp()
|
sftp = get_sftp()
|
||||||
kblob = ''.join([struct.pack('>H', n) for n in xrange(512)])
|
kblob = ''.join([struct.pack('>H', n) for n in range(512)])
|
||||||
try:
|
try:
|
||||||
f = sftp.open('%s/hongry.txt' % FOLDER, 'w')
|
f = sftp.open('%s/hongry.txt' % FOLDER, 'w')
|
||||||
f.set_pipelined(True)
|
f.set_pipelined(True)
|
||||||
|
@ -181,13 +181,13 @@ class BigSFTPTest (unittest.TestCase):
|
||||||
start = time.time()
|
start = time.time()
|
||||||
k2blob = kblob + kblob
|
k2blob = kblob + kblob
|
||||||
chunk = 793
|
chunk = 793
|
||||||
for i in xrange(10):
|
for i in range(10):
|
||||||
f = sftp.open('%s/hongry.txt' % FOLDER, 'r')
|
f = sftp.open('%s/hongry.txt' % FOLDER, 'r')
|
||||||
f.prefetch()
|
f.prefetch()
|
||||||
base_offset = (512 * 1024) + 17 * random.randint(1000, 2000)
|
base_offset = (512 * 1024) + 17 * random.randint(1000, 2000)
|
||||||
offsets = [base_offset + j * chunk for j in xrange(100)]
|
offsets = [base_offset + j * chunk for j in range(100)]
|
||||||
# randomly seek around and read them out
|
# randomly seek around and read them out
|
||||||
for j in xrange(100):
|
for j in range(100):
|
||||||
offset = offsets[random.randint(0, len(offsets) - 1)]
|
offset = offsets[random.randint(0, len(offsets) - 1)]
|
||||||
offsets.remove(offset)
|
offsets.remove(offset)
|
||||||
f.seek(offset)
|
f.seek(offset)
|
||||||
|
@ -203,7 +203,7 @@ class BigSFTPTest (unittest.TestCase):
|
||||||
|
|
||||||
def test_5_readv_seek(self):
|
def test_5_readv_seek(self):
|
||||||
sftp = get_sftp()
|
sftp = get_sftp()
|
||||||
kblob = ''.join([struct.pack('>H', n) for n in xrange(512)])
|
kblob = ''.join([struct.pack('>H', n) for n in range(512)])
|
||||||
try:
|
try:
|
||||||
f = sftp.open('%s/hongry.txt' % FOLDER, 'w')
|
f = sftp.open('%s/hongry.txt' % FOLDER, 'w')
|
||||||
f.set_pipelined(True)
|
f.set_pipelined(True)
|
||||||
|
@ -219,21 +219,21 @@ class BigSFTPTest (unittest.TestCase):
|
||||||
start = time.time()
|
start = time.time()
|
||||||
k2blob = kblob + kblob
|
k2blob = kblob + kblob
|
||||||
chunk = 793
|
chunk = 793
|
||||||
for i in xrange(10):
|
for i in range(10):
|
||||||
f = sftp.open('%s/hongry.txt' % FOLDER, 'r')
|
f = sftp.open('%s/hongry.txt' % FOLDER, 'r')
|
||||||
base_offset = (512 * 1024) + 17 * random.randint(1000, 2000)
|
base_offset = (512 * 1024) + 17 * random.randint(1000, 2000)
|
||||||
# make a bunch of offsets and put them in random order
|
# make a bunch of offsets and put them in random order
|
||||||
offsets = [base_offset + j * chunk for j in xrange(100)]
|
offsets = [base_offset + j * chunk for j in range(100)]
|
||||||
readv_list = []
|
readv_list = []
|
||||||
for j in xrange(100):
|
for j in range(100):
|
||||||
o = offsets[random.randint(0, len(offsets) - 1)]
|
o = offsets[random.randint(0, len(offsets) - 1)]
|
||||||
offsets.remove(o)
|
offsets.remove(o)
|
||||||
readv_list.append((o, chunk))
|
readv_list.append((o, chunk))
|
||||||
ret = f.readv(readv_list)
|
ret = f.readv(readv_list)
|
||||||
for i in xrange(len(readv_list)):
|
for i in range(len(readv_list)):
|
||||||
offset = readv_list[i][0]
|
offset = readv_list[i][0]
|
||||||
n_offset = offset % 1024
|
n_offset = offset % 1024
|
||||||
self.assertEqual(ret.next(), k2blob[n_offset:n_offset + chunk])
|
self.assertEqual(next(ret), k2blob[n_offset:n_offset + chunk])
|
||||||
f.close()
|
f.close()
|
||||||
end = time.time()
|
end = time.time()
|
||||||
sys.stderr.write('%ds ' % round(end - start))
|
sys.stderr.write('%ds ' % round(end - start))
|
||||||
|
@ -279,7 +279,7 @@ class BigSFTPTest (unittest.TestCase):
|
||||||
verify that prefetch and readv don't conflict with each other.
|
verify that prefetch and readv don't conflict with each other.
|
||||||
"""
|
"""
|
||||||
sftp = get_sftp()
|
sftp = get_sftp()
|
||||||
kblob = ''.join([struct.pack('>H', n) for n in xrange(512)])
|
kblob = ''.join([struct.pack('>H', n) for n in range(512)])
|
||||||
try:
|
try:
|
||||||
f = sftp.open('%s/hongry.txt' % FOLDER, 'w')
|
f = sftp.open('%s/hongry.txt' % FOLDER, 'w')
|
||||||
f.set_pipelined(True)
|
f.set_pipelined(True)
|
||||||
|
@ -318,7 +318,7 @@ class BigSFTPTest (unittest.TestCase):
|
||||||
returned as a single blob.
|
returned as a single blob.
|
||||||
"""
|
"""
|
||||||
sftp = get_sftp()
|
sftp = get_sftp()
|
||||||
kblob = ''.join([struct.pack('>H', n) for n in xrange(512)])
|
kblob = ''.join([struct.pack('>H', n) for n in range(512)])
|
||||||
try:
|
try:
|
||||||
f = sftp.open('%s/hongry.txt' % FOLDER, 'w')
|
f = sftp.open('%s/hongry.txt' % FOLDER, 'w')
|
||||||
f.set_pipelined(True)
|
f.set_pipelined(True)
|
||||||
|
@ -367,7 +367,7 @@ class BigSFTPTest (unittest.TestCase):
|
||||||
k32blob = (32 * 1024 * 'x')
|
k32blob = (32 * 1024 * 'x')
|
||||||
try:
|
try:
|
||||||
f = sftp.open('%s/hongry.txt' % FOLDER, 'w', 128 * 1024)
|
f = sftp.open('%s/hongry.txt' % FOLDER, 'w', 128 * 1024)
|
||||||
for i in xrange(32):
|
for i in range(32):
|
||||||
f.write(k32blob)
|
f.write(k32blob)
|
||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
|
|
|
@ -158,7 +158,7 @@ class TransportTest(ParamikoTest):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def test_2_compute_key(self):
|
def test_2_compute_key(self):
|
||||||
self.tc.K = 123281095979686581523377256114209720774539068973101330872763622971399429481072519713536292772709507296759612401802191955568143056534122385270077606457721553469730659233569339356140085284052436697480759510519672848743794433460113118986816826624865291116513647975790797391795651716378444844877749505443714557929L
|
self.tc.K = 123281095979686581523377256114209720774539068973101330872763622971399429481072519713536292772709507296759612401802191955568143056534122385270077606457721553469730659233569339356140085284052436697480759510519672848743794433460113118986816826624865291116513647975790797391795651716378444844877749505443714557929
|
||||||
self.tc.H = unhexlify('0C8307CDE6856FF30BA93684EB0F04C2520E9ED3')
|
self.tc.H = unhexlify('0C8307CDE6856FF30BA93684EB0F04C2520E9ED3')
|
||||||
self.tc.session_id = self.tc.H
|
self.tc.session_id = self.tc.H
|
||||||
key = self.tc._compute_key('C', 32)
|
key = self.tc._compute_key('C', 32)
|
||||||
|
@ -406,7 +406,7 @@ class TransportTest(ParamikoTest):
|
||||||
chan.close()
|
chan.close()
|
||||||
|
|
||||||
# allow a few seconds for the rekeying to complete
|
# allow a few seconds for the rekeying to complete
|
||||||
for i in xrange(50):
|
for i in range(50):
|
||||||
if self.tc.H != self.tc.session_id:
|
if self.tc.H != self.tc.session_id:
|
||||||
break
|
break
|
||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
|
@ -659,7 +659,7 @@ class TransportTest(ParamikoTest):
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
try:
|
try:
|
||||||
for i in xrange(1, 1+self.iterations):
|
for i in range(1, 1+self.iterations):
|
||||||
if self.done_event.isSet():
|
if self.done_event.isSet():
|
||||||
break
|
break
|
||||||
self.watchdog_event.set()
|
self.watchdog_event.set()
|
||||||
|
|
|
@ -101,7 +101,7 @@ class UtilTest(ParamikoTest):
|
||||||
|
|
||||||
def test_2_parse_config(self):
|
def test_2_parse_config(self):
|
||||||
global test_config_file
|
global test_config_file
|
||||||
f = cStringIO.StringIO(test_config_file)
|
f = StringIO(test_config_file)
|
||||||
config = paramiko.util.parse_ssh_config(f)
|
config = paramiko.util.parse_ssh_config(f)
|
||||||
self.assertEquals(config._config,
|
self.assertEquals(config._config,
|
||||||
[{'host': ['*'], 'config': {}}, {'host': ['*'], 'config': {'identityfile': ['~/.ssh/id_rsa'], 'user': 'robey'}},
|
[{'host': ['*'], 'config': {}}, {'host': ['*'], 'config': {'identityfile': ['~/.ssh/id_rsa'], 'user': 'robey'}},
|
||||||
|
@ -111,7 +111,7 @@ class UtilTest(ParamikoTest):
|
||||||
|
|
||||||
def test_3_host_config(self):
|
def test_3_host_config(self):
|
||||||
global test_config_file
|
global test_config_file
|
||||||
f = cStringIO.StringIO(test_config_file)
|
f = StringIO(test_config_file)
|
||||||
config = paramiko.util.parse_ssh_config(f)
|
config = paramiko.util.parse_ssh_config(f)
|
||||||
|
|
||||||
for host, values in {
|
for host, values in {
|
||||||
|
@ -138,7 +138,7 @@ class UtilTest(ParamikoTest):
|
||||||
|
|
||||||
def test_4_generate_key_bytes(self):
|
def test_4_generate_key_bytes(self):
|
||||||
x = paramiko.util.generate_key_bytes(SHA, 'ABCDEFGH', 'This is my secret passphrase.', 64)
|
x = paramiko.util.generate_key_bytes(SHA, 'ABCDEFGH', 'This is my secret passphrase.', 64)
|
||||||
hex = ''.join(['%02x' % ord(c) for c in x])
|
hex = ''.join(['%02x' % byte_ord(c) for c in x])
|
||||||
self.assertEquals(hex, '9110e2f6793b69363e58173e9436b13a5a4b339005741d5c680e505f57d871347b4239f14fb5c46e857d5e100424873ba849ac699cea98d729e57b3e84378e8b')
|
self.assertEquals(hex, '9110e2f6793b69363e58173e9436b13a5a4b339005741d5c680e505f57d871347b4239f14fb5c46e857d5e100424873ba849ac699cea98d729e57b3e84378e8b')
|
||||||
|
|
||||||
def test_5_host_keys(self):
|
def test_5_host_keys(self):
|
||||||
|
@ -172,7 +172,7 @@ Host *.example.com
|
||||||
Host *
|
Host *
|
||||||
Port 3333
|
Port 3333
|
||||||
"""
|
"""
|
||||||
f = cStringIO.StringIO(test_config_file)
|
f = StringIO(test_config_file)
|
||||||
config = paramiko.util.parse_ssh_config(f)
|
config = paramiko.util.parse_ssh_config(f)
|
||||||
host = 'www13.example.com'
|
host = 'www13.example.com'
|
||||||
self.assertEquals(
|
self.assertEquals(
|
||||||
|
@ -216,7 +216,7 @@ Host space-delimited
|
||||||
Host equals-delimited
|
Host equals-delimited
|
||||||
ProxyCommand=foo bar=biz baz
|
ProxyCommand=foo bar=biz baz
|
||||||
"""
|
"""
|
||||||
f = cStringIO.StringIO(conf)
|
f = StringIO(conf)
|
||||||
config = paramiko.util.parse_ssh_config(f)
|
config = paramiko.util.parse_ssh_config(f)
|
||||||
for host in ('space-delimited', 'equals-delimited'):
|
for host in ('space-delimited', 'equals-delimited'):
|
||||||
self.assertEquals(
|
self.assertEquals(
|
||||||
|
@ -228,7 +228,7 @@ Host equals-delimited
|
||||||
"""
|
"""
|
||||||
ProxyCommand should perform interpolation on the value
|
ProxyCommand should perform interpolation on the value
|
||||||
"""
|
"""
|
||||||
config = paramiko.util.parse_ssh_config(cStringIO.StringIO("""
|
config = paramiko.util.parse_ssh_config(StringIO("""
|
||||||
Host specific
|
Host specific
|
||||||
Port 37
|
Port 37
|
||||||
ProxyCommand host %h port %p lol
|
ProxyCommand host %h port %p lol
|
||||||
|
@ -264,7 +264,7 @@ Host www13.*
|
||||||
Host *
|
Host *
|
||||||
Port 3333
|
Port 3333
|
||||||
"""
|
"""
|
||||||
f = cStringIO.StringIO(test_config_file)
|
f = StringIO(test_config_file)
|
||||||
config = paramiko.util.parse_ssh_config(f)
|
config = paramiko.util.parse_ssh_config(f)
|
||||||
host = 'www13.example.com'
|
host = 'www13.example.com'
|
||||||
self.assertEquals(
|
self.assertEquals(
|
||||||
|
@ -293,7 +293,7 @@ ProxyCommand foo=bar:%h-%p
|
||||||
'foo=bar:proxy-without-equal-divisor-22'}
|
'foo=bar:proxy-without-equal-divisor-22'}
|
||||||
}.items():
|
}.items():
|
||||||
|
|
||||||
f = cStringIO.StringIO(test_config_file)
|
f = StringIO(test_config_file)
|
||||||
config = paramiko.util.parse_ssh_config(f)
|
config = paramiko.util.parse_ssh_config(f)
|
||||||
self.assertEquals(
|
self.assertEquals(
|
||||||
paramiko.util.lookup_ssh_host_config(host, config),
|
paramiko.util.lookup_ssh_host_config(host, config),
|
||||||
|
@ -323,7 +323,7 @@ IdentityFile id_dsa22
|
||||||
'identityfile': ['id_dsa0', 'id_dsa1', 'id_dsa22']}
|
'identityfile': ['id_dsa0', 'id_dsa1', 'id_dsa22']}
|
||||||
}.items():
|
}.items():
|
||||||
|
|
||||||
f = cStringIO.StringIO(test_config_file)
|
f = StringIO(test_config_file)
|
||||||
config = paramiko.util.parse_ssh_config(f)
|
config = paramiko.util.parse_ssh_config(f)
|
||||||
self.assertEquals(
|
self.assertEquals(
|
||||||
paramiko.util.lookup_ssh_host_config(host, config),
|
paramiko.util.lookup_ssh_host_config(host, config),
|
||||||
|
@ -338,5 +338,5 @@ IdentityFile id_dsa22
|
||||||
AddressFamily inet
|
AddressFamily inet
|
||||||
IdentityFile something_%l_using_fqdn
|
IdentityFile something_%l_using_fqdn
|
||||||
"""
|
"""
|
||||||
config = paramiko.util.parse_ssh_config(cStringIO.StringIO(test_config))
|
config = paramiko.util.parse_ssh_config(StringIO(test_config))
|
||||||
assert config.lookup('meh') # will die during lookup() if bug regresses
|
assert config.lookup('meh') # will die during lookup() if bug regresses
|
||||||
|
|
Loading…
Reference in New Issue