brittspace.
This commit is contained in:
parent
71e872e23a
commit
e0a9f91c14
|
@ -33,7 +33,7 @@ class HostKeyEntry:
|
||||||
"""
|
"""
|
||||||
Representation of a line in an OpenSSH-style "known hosts" file.
|
Representation of a line in an OpenSSH-style "known hosts" file.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, hostnames=None, key=None):
|
def __init__(self, hostnames=None, key=None):
|
||||||
self.valid = (hostnames is not None) and (key is not None)
|
self.valid = (hostnames is not None) and (key is not None)
|
||||||
self.hostnames = hostnames
|
self.hostnames = hostnames
|
||||||
|
@ -83,7 +83,7 @@ class HostKeyEntry:
|
||||||
return '%s %s %s\n' % (','.join(self.hostnames), self.key.get_name(),
|
return '%s %s %s\n' % (','.join(self.hostnames), self.key.get_name(),
|
||||||
self.key.get_base64())
|
self.key.get_base64())
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '<HostKeyEntry %r: %r>' % (self.hostnames, self.key)
|
return '<HostKeyEntry %r: %r>' % (self.hostnames, self.key)
|
||||||
|
|
||||||
|
@ -93,18 +93,18 @@ class HostKeys (UserDict.DictMixin):
|
||||||
Representation of an openssh-style "known hosts" file. Host keys can be
|
Representation of an openssh-style "known hosts" file. Host keys can be
|
||||||
read from one or more files, and then individual hosts can be looked up to
|
read from one or more files, and then individual hosts can be looked up to
|
||||||
verify server keys during SSH negotiation.
|
verify server keys during SSH negotiation.
|
||||||
|
|
||||||
A HostKeys object can be treated like a dict; any dict lookup is equivalent
|
A HostKeys object can be treated like a dict; any dict lookup is equivalent
|
||||||
to calling L{lookup}.
|
to calling L{lookup}.
|
||||||
|
|
||||||
@since: 1.5.3
|
@since: 1.5.3
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, filename=None):
|
def __init__(self, filename=None):
|
||||||
"""
|
"""
|
||||||
Create a new HostKeys object, optionally loading keys from an openssh
|
Create a new HostKeys object, optionally loading keys from an openssh
|
||||||
style host-key file.
|
style host-key file.
|
||||||
|
|
||||||
@param filename: filename to load host keys from, or C{None}
|
@param filename: filename to load host keys from, or C{None}
|
||||||
@type filename: str
|
@type filename: str
|
||||||
"""
|
"""
|
||||||
|
@ -112,12 +112,12 @@ class HostKeys (UserDict.DictMixin):
|
||||||
self._entries = []
|
self._entries = []
|
||||||
if filename is not None:
|
if filename is not None:
|
||||||
self.load(filename)
|
self.load(filename)
|
||||||
|
|
||||||
def add(self, hostname, keytype, key):
|
def add(self, hostname, keytype, key):
|
||||||
"""
|
"""
|
||||||
Add a host key entry to the table. Any existing entry for a
|
Add a host key entry to the table. Any existing entry for a
|
||||||
C{(hostname, keytype)} pair will be replaced.
|
C{(hostname, keytype)} pair will be replaced.
|
||||||
|
|
||||||
@param hostname: the hostname (or IP) to add
|
@param hostname: the hostname (or IP) to add
|
||||||
@type hostname: str
|
@type hostname: str
|
||||||
@param keytype: key type (C{"ssh-rsa"} or C{"ssh-dss"})
|
@param keytype: key type (C{"ssh-rsa"} or C{"ssh-dss"})
|
||||||
|
@ -130,21 +130,21 @@ class HostKeys (UserDict.DictMixin):
|
||||||
e.key = key
|
e.key = key
|
||||||
return
|
return
|
||||||
self._entries.append(HostKeyEntry([hostname], key))
|
self._entries.append(HostKeyEntry([hostname], key))
|
||||||
|
|
||||||
def load(self, filename):
|
def load(self, filename):
|
||||||
"""
|
"""
|
||||||
Read a file of known SSH host keys, in the format used by openssh.
|
Read a file of known SSH host keys, in the format used by openssh.
|
||||||
This type of file unfortunately doesn't exist on Windows, but on
|
This type of file unfortunately doesn't exist on Windows, but on
|
||||||
posix, it will usually be stored in
|
posix, it will usually be stored in
|
||||||
C{os.path.expanduser("~/.ssh/known_hosts")}.
|
C{os.path.expanduser("~/.ssh/known_hosts")}.
|
||||||
|
|
||||||
If this method is called multiple times, the host keys are merged,
|
If this method is called multiple times, the host keys are merged,
|
||||||
not cleared. So multiple calls to C{load} will just call L{add},
|
not cleared. So multiple calls to C{load} will just call L{add},
|
||||||
replacing any existing entries and adding new ones.
|
replacing any existing entries and adding new ones.
|
||||||
|
|
||||||
@param filename: name of the file to read host keys from
|
@param filename: name of the file to read host keys from
|
||||||
@type filename: str
|
@type filename: str
|
||||||
|
|
||||||
@raise IOError: if there was an error reading the file
|
@raise IOError: if there was an error reading the file
|
||||||
"""
|
"""
|
||||||
f = open(filename, 'r')
|
f = open(filename, 'r')
|
||||||
|
@ -156,19 +156,19 @@ class HostKeys (UserDict.DictMixin):
|
||||||
if e is not None:
|
if e is not None:
|
||||||
self._entries.append(e)
|
self._entries.append(e)
|
||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
def save(self, filename):
|
def save(self, filename):
|
||||||
"""
|
"""
|
||||||
Save host keys into a file, in the format used by openssh. The order of
|
Save host keys into a file, in the format used by openssh. The order of
|
||||||
keys in the file will be preserved when possible (if these keys were
|
keys in the file will be preserved when possible (if these keys were
|
||||||
loaded from a file originally). The single exception is that combined
|
loaded from a file originally). The single exception is that combined
|
||||||
lines will be split into individual key lines, which is arguably a bug.
|
lines will be split into individual key lines, which is arguably a bug.
|
||||||
|
|
||||||
@param filename: name of the file to write
|
@param filename: name of the file to write
|
||||||
@type filename: str
|
@type filename: str
|
||||||
|
|
||||||
@raise IOError: if there was an error writing the file
|
@raise IOError: if there was an error writing the file
|
||||||
|
|
||||||
@since: 1.6.1
|
@since: 1.6.1
|
||||||
"""
|
"""
|
||||||
f = open(filename, 'w')
|
f = open(filename, 'w')
|
||||||
|
@ -183,7 +183,7 @@ class HostKeys (UserDict.DictMixin):
|
||||||
Find a hostkey entry for a given hostname or IP. If no entry is found,
|
Find a hostkey entry for a given hostname or IP. If no entry is found,
|
||||||
C{None} is returned. Otherwise a dictionary of keytype to key is
|
C{None} is returned. Otherwise a dictionary of keytype to key is
|
||||||
returned. The keytype will be either C{"ssh-rsa"} or C{"ssh-dss"}.
|
returned. The keytype will be either C{"ssh-rsa"} or C{"ssh-dss"}.
|
||||||
|
|
||||||
@param hostname: the hostname (or IP) to lookup
|
@param hostname: the hostname (or IP) to lookup
|
||||||
@type hostname: str
|
@type hostname: str
|
||||||
@return: keys associated with this host (or C{None})
|
@return: keys associated with this host (or C{None})
|
||||||
|
@ -194,13 +194,13 @@ class HostKeys (UserDict.DictMixin):
|
||||||
self._hostname = hostname
|
self._hostname = hostname
|
||||||
self._entries = entries
|
self._entries = entries
|
||||||
self._hostkeys = hostkeys
|
self._hostkeys = hostkeys
|
||||||
|
|
||||||
def __getitem__(self, key):
|
def __getitem__(self, key):
|
||||||
for e in self._entries:
|
for e in self._entries:
|
||||||
if e.key.get_name() == key:
|
if e.key.get_name() == key:
|
||||||
return e.key
|
return e.key
|
||||||
raise KeyError(key)
|
raise KeyError(key)
|
||||||
|
|
||||||
def __setitem__(self, key, val):
|
def __setitem__(self, key, val):
|
||||||
for e in self._entries:
|
for e in self._entries:
|
||||||
if e.key is None:
|
if e.key is None:
|
||||||
|
@ -214,7 +214,7 @@ class HostKeys (UserDict.DictMixin):
|
||||||
e = HostKeyEntry([hostname], val)
|
e = HostKeyEntry([hostname], val)
|
||||||
self._entries.append(e)
|
self._entries.append(e)
|
||||||
self._hostkeys._entries.append(e)
|
self._hostkeys._entries.append(e)
|
||||||
|
|
||||||
def keys(self):
|
def keys(self):
|
||||||
return [e.key.get_name() for e in self._entries if e.key is not None]
|
return [e.key.get_name() for e in self._entries if e.key is not None]
|
||||||
|
|
||||||
|
@ -226,12 +226,12 @@ class HostKeys (UserDict.DictMixin):
|
||||||
if len(entries) == 0:
|
if len(entries) == 0:
|
||||||
return None
|
return None
|
||||||
return SubDict(hostname, entries, self)
|
return SubDict(hostname, entries, self)
|
||||||
|
|
||||||
def check(self, hostname, key):
|
def check(self, hostname, key):
|
||||||
"""
|
"""
|
||||||
Return True if the given key is associated with the given hostname
|
Return True if the given key is associated with the given hostname
|
||||||
in this dictionary.
|
in this dictionary.
|
||||||
|
|
||||||
@param hostname: hostname (or IP) of the SSH server
|
@param hostname: hostname (or IP) of the SSH server
|
||||||
@type hostname: str
|
@type hostname: str
|
||||||
@param key: the key to check
|
@param key: the key to check
|
||||||
|
@ -253,13 +253,13 @@ class HostKeys (UserDict.DictMixin):
|
||||||
Remove all host keys from the dictionary.
|
Remove all host keys from the dictionary.
|
||||||
"""
|
"""
|
||||||
self._entries = []
|
self._entries = []
|
||||||
|
|
||||||
def __getitem__(self, key):
|
def __getitem__(self, key):
|
||||||
ret = self.lookup(key)
|
ret = self.lookup(key)
|
||||||
if ret is None:
|
if ret is None:
|
||||||
raise KeyError(key)
|
raise KeyError(key)
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def __setitem__(self, hostname, entry):
|
def __setitem__(self, hostname, entry):
|
||||||
# don't use this please.
|
# don't use this please.
|
||||||
if len(entry) == 0:
|
if len(entry) == 0:
|
||||||
|
@ -274,7 +274,7 @@ class HostKeys (UserDict.DictMixin):
|
||||||
found = True
|
found = True
|
||||||
if not found:
|
if not found:
|
||||||
self._entries.append(HostKeyEntry([hostname], entry[key_type]))
|
self._entries.append(HostKeyEntry([hostname], entry[key_type]))
|
||||||
|
|
||||||
def keys(self):
|
def keys(self):
|
||||||
# python 2.4 sets would be nice here.
|
# python 2.4 sets would be nice here.
|
||||||
ret = []
|
ret = []
|
||||||
|
@ -294,7 +294,7 @@ class HostKeys (UserDict.DictMixin):
|
||||||
"""
|
"""
|
||||||
Return a "hashed" form of the hostname, as used by openssh when storing
|
Return a "hashed" form of the hostname, as used by openssh when storing
|
||||||
hashed hostnames in the known_hosts file.
|
hashed hostnames in the known_hosts file.
|
||||||
|
|
||||||
@param hostname: the hostname to hash
|
@param hostname: the hostname to hash
|
||||||
@type hostname: str
|
@type hostname: str
|
||||||
@param salt: optional salt to use when hashing (must be 20 bytes long)
|
@param salt: optional salt to use when hashing (must be 20 bytes long)
|
||||||
|
|
|
@ -43,7 +43,7 @@ def open_rng_device(device_path=None):
|
||||||
|
|
||||||
f = None
|
f = None
|
||||||
g = None
|
g = None
|
||||||
|
|
||||||
if device_path is None:
|
if device_path is None:
|
||||||
device_path = "/dev/urandom"
|
device_path = "/dev/urandom"
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ def open_rng_device(device_path=None):
|
||||||
f = open(device_path, "rb", 0)
|
f = open(device_path, "rb", 0)
|
||||||
except EnvironmentError:
|
except EnvironmentError:
|
||||||
raise error("Unable to open /dev/urandom")
|
raise error("Unable to open /dev/urandom")
|
||||||
|
|
||||||
# Open a second file descriptor for sanity checking later.
|
# Open a second file descriptor for sanity checking later.
|
||||||
try:
|
try:
|
||||||
g = open(device_path, "rb", 0)
|
g = open(device_path, "rb", 0)
|
||||||
|
@ -65,17 +65,17 @@ def open_rng_device(device_path=None):
|
||||||
st = os.fstat(f.fileno()) # f
|
st = os.fstat(f.fileno()) # f
|
||||||
if stat.S_ISREG(st.st_mode) or not stat.S_ISCHR(st.st_mode):
|
if stat.S_ISREG(st.st_mode) or not stat.S_ISCHR(st.st_mode):
|
||||||
raise error("/dev/urandom is not a character special device")
|
raise error("/dev/urandom is not a character special device")
|
||||||
|
|
||||||
st = os.fstat(g.fileno()) # g
|
st = os.fstat(g.fileno()) # g
|
||||||
if stat.S_ISREG(st.st_mode) or not stat.S_ISCHR(st.st_mode):
|
if stat.S_ISREG(st.st_mode) or not stat.S_ISCHR(st.st_mode):
|
||||||
raise error("/dev/urandom is not a character special device")
|
raise error("/dev/urandom is not a character special device")
|
||||||
|
|
||||||
# Check that /dev/urandom always returns the number of bytes requested
|
# Check that /dev/urandom always returns the number of bytes requested
|
||||||
x = f.read(20)
|
x = f.read(20)
|
||||||
y = g.read(20)
|
y = g.read(20)
|
||||||
if len(x) != 20 or len(y) != 20:
|
if len(x) != 20 or len(y) != 20:
|
||||||
raise error("Error reading from /dev/urandom: input truncated")
|
raise error("Error reading from /dev/urandom: input truncated")
|
||||||
|
|
||||||
# Check that different reads return different data
|
# Check that different reads return different data
|
||||||
if x == y:
|
if x == y:
|
||||||
raise error("/dev/urandom is broken; returning identical data: %r == %r" % (x, y))
|
raise error("/dev/urandom is broken; returning identical data: %r == %r" % (x, y))
|
||||||
|
|
|
@ -103,7 +103,7 @@ class SecurityOptions (object):
|
||||||
|
|
||||||
def _get_kex(self):
|
def _get_kex(self):
|
||||||
return self._transport._preferred_kex
|
return self._transport._preferred_kex
|
||||||
|
|
||||||
def _get_compression(self):
|
def _get_compression(self):
|
||||||
return self._transport._preferred_compression
|
return self._transport._preferred_compression
|
||||||
|
|
||||||
|
@ -129,7 +129,7 @@ class SecurityOptions (object):
|
||||||
|
|
||||||
def _set_kex(self, x):
|
def _set_kex(self, x):
|
||||||
self._set('_preferred_kex', '_kex_info', x)
|
self._set('_preferred_kex', '_kex_info', x)
|
||||||
|
|
||||||
def _set_compression(self, x):
|
def _set_compression(self, x):
|
||||||
self._set('_preferred_compression', '_compression_info', x)
|
self._set('_preferred_compression', '_compression_info', x)
|
||||||
|
|
||||||
|
@ -156,14 +156,14 @@ class ChannelMap (object):
|
||||||
self._map[chanid] = chan
|
self._map[chanid] = chan
|
||||||
finally:
|
finally:
|
||||||
self._lock.release()
|
self._lock.release()
|
||||||
|
|
||||||
def get(self, chanid):
|
def get(self, chanid):
|
||||||
self._lock.acquire()
|
self._lock.acquire()
|
||||||
try:
|
try:
|
||||||
return self._map.get(chanid, None)
|
return self._map.get(chanid, None)
|
||||||
finally:
|
finally:
|
||||||
self._lock.release()
|
self._lock.release()
|
||||||
|
|
||||||
def delete(self, chanid):
|
def delete(self, chanid):
|
||||||
self._lock.acquire()
|
self._lock.acquire()
|
||||||
try:
|
try:
|
||||||
|
@ -173,14 +173,14 @@ class ChannelMap (object):
|
||||||
pass
|
pass
|
||||||
finally:
|
finally:
|
||||||
self._lock.release()
|
self._lock.release()
|
||||||
|
|
||||||
def values(self):
|
def values(self):
|
||||||
self._lock.acquire()
|
self._lock.acquire()
|
||||||
try:
|
try:
|
||||||
return self._map.values()
|
return self._map.values()
|
||||||
finally:
|
finally:
|
||||||
self._lock.release()
|
self._lock.release()
|
||||||
|
|
||||||
def __len__(self):
|
def __len__(self):
|
||||||
self._lock.acquire()
|
self._lock.acquire()
|
||||||
try:
|
try:
|
||||||
|
@ -206,7 +206,7 @@ class Transport (threading.Thread):
|
||||||
_preferred_keys = ( 'ssh-rsa', 'ssh-dss' )
|
_preferred_keys = ( 'ssh-rsa', 'ssh-dss' )
|
||||||
_preferred_kex = ( 'diffie-hellman-group1-sha1', 'diffie-hellman-group-exchange-sha1' )
|
_preferred_kex = ( 'diffie-hellman-group1-sha1', 'diffie-hellman-group-exchange-sha1' )
|
||||||
_preferred_compression = ( 'none', )
|
_preferred_compression = ( 'none', )
|
||||||
|
|
||||||
_cipher_info = {
|
_cipher_info = {
|
||||||
'aes128-ctr': { 'class': AES, 'mode': AES.MODE_CTR, 'block-size': 16, 'key-size': 16 },
|
'aes128-ctr': { 'class': AES, 'mode': AES.MODE_CTR, 'block-size': 16, 'key-size': 16 },
|
||||||
'aes256-ctr': { 'class': AES, 'mode': AES.MODE_CTR, 'block-size': 16, 'key-size': 32 },
|
'aes256-ctr': { 'class': AES, 'mode': AES.MODE_CTR, 'block-size': 16, 'key-size': 32 },
|
||||||
|
@ -234,7 +234,7 @@ class Transport (threading.Thread):
|
||||||
'diffie-hellman-group1-sha1': KexGroup1,
|
'diffie-hellman-group1-sha1': KexGroup1,
|
||||||
'diffie-hellman-group-exchange-sha1': KexGex,
|
'diffie-hellman-group-exchange-sha1': KexGex,
|
||||||
}
|
}
|
||||||
|
|
||||||
_compression_info = {
|
_compression_info = {
|
||||||
# zlib@openssh.com is just zlib, but only turned on after a successful
|
# zlib@openssh.com is just zlib, but only turned on after a successful
|
||||||
# authentication. openssh servers may only offer this type because
|
# authentication. openssh servers may only offer this type because
|
||||||
|
@ -319,7 +319,7 @@ class Transport (threading.Thread):
|
||||||
self.session_id = None
|
self.session_id = None
|
||||||
self.host_key_type = None
|
self.host_key_type = None
|
||||||
self.host_key = None
|
self.host_key = None
|
||||||
|
|
||||||
# state used during negotiation
|
# state used during negotiation
|
||||||
self.kex_engine = None
|
self.kex_engine = None
|
||||||
self.H = None
|
self.H = None
|
||||||
|
@ -383,7 +383,7 @@ class Transport (threading.Thread):
|
||||||
out += ' (connecting)'
|
out += ' (connecting)'
|
||||||
out += '>'
|
out += '>'
|
||||||
return out
|
return out
|
||||||
|
|
||||||
def atfork(self):
|
def atfork(self):
|
||||||
"""
|
"""
|
||||||
Terminate this Transport without closing the session. On posix
|
Terminate this Transport without closing the session. On posix
|
||||||
|
@ -391,7 +391,7 @@ class Transport (threading.Thread):
|
||||||
and child will share the underlying socket, but only one process can
|
and child will share the underlying socket, but only one process can
|
||||||
use the connection (without corrupting the session). Use this method
|
use the connection (without corrupting the session). Use this method
|
||||||
to clean up a Transport object without disrupting the other process.
|
to clean up a Transport object without disrupting the other process.
|
||||||
|
|
||||||
@since: 1.5.3
|
@since: 1.5.3
|
||||||
"""
|
"""
|
||||||
self.sock.close()
|
self.sock.close()
|
||||||
|
@ -414,11 +414,11 @@ class Transport (threading.Thread):
|
||||||
Negotiate a new SSH2 session as a client. This is the first step after
|
Negotiate a new SSH2 session as a client. This is the first step after
|
||||||
creating a new L{Transport}. A separate thread is created for protocol
|
creating a new L{Transport}. A separate thread is created for protocol
|
||||||
negotiation.
|
negotiation.
|
||||||
|
|
||||||
If an event is passed in, this method returns immediately. When
|
If an event is passed in, this method returns immediately. When
|
||||||
negotiation is done (successful or not), the given C{Event} will
|
negotiation is done (successful or not), the given C{Event} will
|
||||||
be triggered. On failure, L{is_active} will return C{False}.
|
be triggered. On failure, L{is_active} will return C{False}.
|
||||||
|
|
||||||
(Since 1.4) If C{event} is C{None}, this method will not return until
|
(Since 1.4) If C{event} is C{None}, this method will not return until
|
||||||
negotation is done. On success, the method returns normally.
|
negotation is done. On success, the method returns normally.
|
||||||
Otherwise an SSHException is raised.
|
Otherwise an SSHException is raised.
|
||||||
|
@ -428,7 +428,7 @@ class Transport (threading.Thread):
|
||||||
L{auth_publickey <Transport.auth_publickey>}.
|
L{auth_publickey <Transport.auth_publickey>}.
|
||||||
|
|
||||||
@note: L{connect} is a simpler method for connecting as a client.
|
@note: L{connect} is a simpler method for connecting as a client.
|
||||||
|
|
||||||
@note: After calling this method (or L{start_server} or L{connect}),
|
@note: After calling this method (or L{start_server} or L{connect}),
|
||||||
you should no longer directly read from or write to the original
|
you should no longer directly read from or write to the original
|
||||||
socket object.
|
socket object.
|
||||||
|
@ -465,11 +465,11 @@ class Transport (threading.Thread):
|
||||||
Negotiate a new SSH2 session as a server. This is the first step after
|
Negotiate a new SSH2 session as a server. This is the first step after
|
||||||
creating a new L{Transport} and setting up your server host key(s). A
|
creating a new L{Transport} and setting up your server host key(s). A
|
||||||
separate thread is created for protocol negotiation.
|
separate thread is created for protocol negotiation.
|
||||||
|
|
||||||
If an event is passed in, this method returns immediately. When
|
If an event is passed in, this method returns immediately. When
|
||||||
negotiation is done (successful or not), the given C{Event} will
|
negotiation is done (successful or not), the given C{Event} will
|
||||||
be triggered. On failure, L{is_active} will return C{False}.
|
be triggered. On failure, L{is_active} will return C{False}.
|
||||||
|
|
||||||
(Since 1.4) If C{event} is C{None}, this method will not return until
|
(Since 1.4) If C{event} is C{None}, this method will not return until
|
||||||
negotation is done. On success, the method returns normally.
|
negotation is done. On success, the method returns normally.
|
||||||
Otherwise an SSHException is raised.
|
Otherwise an SSHException is raised.
|
||||||
|
@ -532,7 +532,7 @@ class Transport (threading.Thread):
|
||||||
we are. Because this is used for signing, the key must contain private
|
we are. Because this is used for signing, the key must contain private
|
||||||
key info, not just the public half. Only one key of each type (RSA or
|
key info, not just the public half. Only one key of each type (RSA or
|
||||||
DSS) is kept.
|
DSS) is kept.
|
||||||
|
|
||||||
@param key: the host key to add, usually an L{RSAKey <rsakey.RSAKey>} or
|
@param key: the host key to add, usually an L{RSAKey <rsakey.RSAKey>} or
|
||||||
L{DSSKey <dsskey.DSSKey>}.
|
L{DSSKey <dsskey.DSSKey>}.
|
||||||
@type key: L{PKey <pkey.PKey>}
|
@type key: L{PKey <pkey.PKey>}
|
||||||
|
@ -582,7 +582,7 @@ class Transport (threading.Thread):
|
||||||
@return: True if a moduli file was successfully loaded; False
|
@return: True if a moduli file was successfully loaded; False
|
||||||
otherwise.
|
otherwise.
|
||||||
@rtype: bool
|
@rtype: bool
|
||||||
|
|
||||||
@note: This has no effect when used in client mode.
|
@note: This has no effect when used in client mode.
|
||||||
"""
|
"""
|
||||||
Transport._modulus_pack = ModulusPack(randpool)
|
Transport._modulus_pack = ModulusPack(randpool)
|
||||||
|
@ -623,7 +623,7 @@ class Transport (threading.Thread):
|
||||||
C{str(key)} for the key string.
|
C{str(key)} for the key string.
|
||||||
|
|
||||||
@raise SSHException: if no session is currently active.
|
@raise SSHException: if no session is currently active.
|
||||||
|
|
||||||
@return: public key of the remote server
|
@return: public key of the remote server
|
||||||
@rtype: L{PKey <pkey.PKey>}
|
@rtype: L{PKey <pkey.PKey>}
|
||||||
"""
|
"""
|
||||||
|
@ -648,7 +648,7 @@ class Transport (threading.Thread):
|
||||||
|
|
||||||
@return: a new L{Channel}
|
@return: a new L{Channel}
|
||||||
@rtype: L{Channel}
|
@rtype: L{Channel}
|
||||||
|
|
||||||
@raise SSHException: if the request is rejected or the session ends
|
@raise SSHException: if the request is rejected or the session ends
|
||||||
prematurely
|
prematurely
|
||||||
"""
|
"""
|
||||||
|
@ -664,25 +664,25 @@ class Transport (threading.Thread):
|
||||||
@type src_addr: (str, int)
|
@type src_addr: (str, int)
|
||||||
@return: a new L{Channel}
|
@return: a new L{Channel}
|
||||||
@rtype: L{Channel}
|
@rtype: L{Channel}
|
||||||
|
|
||||||
@raise SSHException: if the request is rejected or the session ends
|
@raise SSHException: if the request is rejected or the session ends
|
||||||
prematurely
|
prematurely
|
||||||
"""
|
"""
|
||||||
return self.open_channel('x11', src_addr=src_addr)
|
return self.open_channel('x11', src_addr=src_addr)
|
||||||
|
|
||||||
def open_forwarded_tcpip_channel(self, (src_addr, src_port), (dest_addr, dest_port)):
|
def open_forwarded_tcpip_channel(self, (src_addr, src_port), (dest_addr, dest_port)):
|
||||||
"""
|
"""
|
||||||
Request a new channel back to the client, of type C{"forwarded-tcpip"}.
|
Request a new channel back to the client, of type C{"forwarded-tcpip"}.
|
||||||
This is used after a client has requested port forwarding, for sending
|
This is used after a client has requested port forwarding, for sending
|
||||||
incoming connections back to the client.
|
incoming connections back to the client.
|
||||||
|
|
||||||
@param src_addr: originator's address
|
@param src_addr: originator's address
|
||||||
@param src_port: originator's port
|
@param src_port: originator's port
|
||||||
@param dest_addr: local (server) connected address
|
@param dest_addr: local (server) connected address
|
||||||
@param dest_port: local (server) connected port
|
@param dest_port: local (server) connected port
|
||||||
"""
|
"""
|
||||||
return self.open_channel('forwarded-tcpip', (dest_addr, dest_port), (src_addr, src_port))
|
return self.open_channel('forwarded-tcpip', (dest_addr, dest_port), (src_addr, src_port))
|
||||||
|
|
||||||
def open_channel(self, kind, dest_addr=None, src_addr=None):
|
def open_channel(self, kind, dest_addr=None, src_addr=None):
|
||||||
"""
|
"""
|
||||||
Request a new channel to the server. L{Channel}s are socket-like
|
Request a new channel to the server. L{Channel}s are socket-like
|
||||||
|
@ -757,19 +757,19 @@ class Transport (threading.Thread):
|
||||||
"""
|
"""
|
||||||
Ask the server to forward TCP connections from a listening port on
|
Ask the server to forward TCP connections from a listening port on
|
||||||
the server, across this SSH session.
|
the server, across this SSH session.
|
||||||
|
|
||||||
If a handler is given, that handler is called from a different thread
|
If a handler is given, that handler is called from a different thread
|
||||||
whenever a forwarded connection arrives. The handler parameters are::
|
whenever a forwarded connection arrives. The handler parameters are::
|
||||||
|
|
||||||
handler(channel, (origin_addr, origin_port), (server_addr, server_port))
|
handler(channel, (origin_addr, origin_port), (server_addr, server_port))
|
||||||
|
|
||||||
where C{server_addr} and C{server_port} are the address and port that
|
where C{server_addr} and C{server_port} are the address and port that
|
||||||
the server was listening on.
|
the server was listening on.
|
||||||
|
|
||||||
If no handler is set, the default behavior is to send new incoming
|
If no handler is set, the default behavior is to send new incoming
|
||||||
forwarded connections into the accept queue, to be picked up via
|
forwarded connections into the accept queue, to be picked up via
|
||||||
L{accept}.
|
L{accept}.
|
||||||
|
|
||||||
@param address: the address to bind when forwarding
|
@param address: the address to bind when forwarding
|
||||||
@type address: str
|
@type address: str
|
||||||
@param port: the port to forward, or 0 to ask the server to allocate
|
@param port: the port to forward, or 0 to ask the server to allocate
|
||||||
|
@ -779,7 +779,7 @@ class Transport (threading.Thread):
|
||||||
@type handler: function(Channel, (str, int), (str, int))
|
@type handler: function(Channel, (str, int), (str, int))
|
||||||
@return: the port # allocated by the server
|
@return: the port # allocated by the server
|
||||||
@rtype: int
|
@rtype: int
|
||||||
|
|
||||||
@raise SSHException: if the server refused the TCP forward request
|
@raise SSHException: if the server refused the TCP forward request
|
||||||
"""
|
"""
|
||||||
if not self.active:
|
if not self.active:
|
||||||
|
@ -803,7 +803,7 @@ class Transport (threading.Thread):
|
||||||
Ask the server to cancel a previous port-forwarding request. No more
|
Ask the server to cancel a previous port-forwarding request. No more
|
||||||
connections to the given address & port will be forwarded across this
|
connections to the given address & port will be forwarded across this
|
||||||
ssh connection.
|
ssh connection.
|
||||||
|
|
||||||
@param address: the address to stop forwarding
|
@param address: the address to stop forwarding
|
||||||
@type address: str
|
@type address: str
|
||||||
@param port: the port to stop forwarding
|
@param port: the port to stop forwarding
|
||||||
|
@ -813,7 +813,7 @@ class Transport (threading.Thread):
|
||||||
return
|
return
|
||||||
self._tcp_handler = None
|
self._tcp_handler = None
|
||||||
self.global_request('cancel-tcpip-forward', (address, port), wait=True)
|
self.global_request('cancel-tcpip-forward', (address, port), wait=True)
|
||||||
|
|
||||||
def open_sftp_client(self):
|
def open_sftp_client(self):
|
||||||
"""
|
"""
|
||||||
Create an SFTP client channel from an open transport. On success,
|
Create an SFTP client channel from an open transport. On success,
|
||||||
|
@ -876,7 +876,7 @@ class Transport (threading.Thread):
|
||||||
C{interval} seconds without sending any data over the connection, a
|
C{interval} seconds without sending any data over the connection, a
|
||||||
"keepalive" packet will be sent (and ignored by the remote host). This
|
"keepalive" packet will be sent (and ignored by the remote host). This
|
||||||
can be useful to keep connections alive over a NAT, for example.
|
can be useful to keep connections alive over a NAT, for example.
|
||||||
|
|
||||||
@param interval: seconds to wait before sending a keepalive packet (or
|
@param interval: seconds to wait before sending a keepalive packet (or
|
||||||
0 to disable keepalives).
|
0 to disable keepalives).
|
||||||
@type interval: int
|
@type interval: int
|
||||||
|
@ -927,7 +927,7 @@ class Transport (threading.Thread):
|
||||||
Return the next channel opened by the client over this transport, in
|
Return the next channel opened by the client over this transport, in
|
||||||
server mode. If no channel is opened before the given timeout, C{None}
|
server mode. If no channel is opened before the given timeout, C{None}
|
||||||
is returned.
|
is returned.
|
||||||
|
|
||||||
@param timeout: seconds to wait for a channel, or C{None} to wait
|
@param timeout: seconds to wait for a channel, or C{None} to wait
|
||||||
forever
|
forever
|
||||||
@type timeout: int
|
@type timeout: int
|
||||||
|
@ -979,7 +979,7 @@ class Transport (threading.Thread):
|
||||||
@param pkey: a private key to use for authentication, if you want to
|
@param pkey: a private key to use for authentication, if you want to
|
||||||
use private key authentication; otherwise C{None}.
|
use private key authentication; otherwise C{None}.
|
||||||
@type pkey: L{PKey<pkey.PKey>}
|
@type pkey: L{PKey<pkey.PKey>}
|
||||||
|
|
||||||
@raise SSHException: if the SSH2 negotiation fails, the host key
|
@raise SSHException: if the SSH2 negotiation fails, the host key
|
||||||
supplied by the server is incorrect, or authentication fails.
|
supplied by the server is incorrect, or authentication fails.
|
||||||
"""
|
"""
|
||||||
|
@ -1007,17 +1007,17 @@ class Transport (threading.Thread):
|
||||||
self.auth_publickey(username, pkey)
|
self.auth_publickey(username, pkey)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def get_exception(self):
|
def get_exception(self):
|
||||||
"""
|
"""
|
||||||
Return any exception that happened during the last server request.
|
Return any exception that happened during the last server request.
|
||||||
This can be used to fetch more specific error information after using
|
This can be used to fetch more specific error information after using
|
||||||
calls like L{start_client}. The exception (if any) is cleared after
|
calls like L{start_client}. The exception (if any) is cleared after
|
||||||
this call.
|
this call.
|
||||||
|
|
||||||
@return: an exception, or C{None} if there is no stored exception.
|
@return: an exception, or C{None} if there is no stored exception.
|
||||||
@rtype: Exception
|
@rtype: Exception
|
||||||
|
|
||||||
@since: 1.1
|
@since: 1.1
|
||||||
"""
|
"""
|
||||||
self.lock.acquire()
|
self.lock.acquire()
|
||||||
|
@ -1049,7 +1049,7 @@ class Transport (threading.Thread):
|
||||||
self.subsystem_table[name] = (handler, larg, kwarg)
|
self.subsystem_table[name] = (handler, larg, kwarg)
|
||||||
finally:
|
finally:
|
||||||
self.lock.release()
|
self.lock.release()
|
||||||
|
|
||||||
def is_authenticated(self):
|
def is_authenticated(self):
|
||||||
"""
|
"""
|
||||||
Return true if this session is active and authenticated.
|
Return true if this session is active and authenticated.
|
||||||
|
@ -1060,7 +1060,7 @@ class Transport (threading.Thread):
|
||||||
@rtype: bool
|
@rtype: bool
|
||||||
"""
|
"""
|
||||||
return self.active and (self.auth_handler is not None) and self.auth_handler.is_authenticated()
|
return self.active and (self.auth_handler is not None) and self.auth_handler.is_authenticated()
|
||||||
|
|
||||||
def get_username(self):
|
def get_username(self):
|
||||||
"""
|
"""
|
||||||
Return the username this connection is authenticated for. If the
|
Return the username this connection is authenticated for. If the
|
||||||
|
@ -1080,7 +1080,7 @@ class Transport (threading.Thread):
|
||||||
This will almost always fail. It may be useful for determining the
|
This will almost always fail. It may be useful for determining the
|
||||||
list of authentication types supported by the server, by catching the
|
list of authentication types supported by the server, by catching the
|
||||||
L{BadAuthenticationType} exception raised.
|
L{BadAuthenticationType} exception raised.
|
||||||
|
|
||||||
@param username: the username to authenticate as
|
@param username: the username to authenticate as
|
||||||
@type username: string
|
@type username: string
|
||||||
@return: list of auth types permissible for the next stage of
|
@return: list of auth types permissible for the next stage of
|
||||||
|
@ -1091,7 +1091,7 @@ class Transport (threading.Thread):
|
||||||
by the server for this user
|
by the server for this user
|
||||||
@raise SSHException: if the authentication failed due to a network
|
@raise SSHException: if the authentication failed due to a network
|
||||||
error
|
error
|
||||||
|
|
||||||
@since: 1.5
|
@since: 1.5
|
||||||
"""
|
"""
|
||||||
if (not self.active) or (not self.initial_kex_done):
|
if (not self.active) or (not self.initial_kex_done):
|
||||||
|
@ -1105,7 +1105,7 @@ class Transport (threading.Thread):
|
||||||
"""
|
"""
|
||||||
Authenticate to the server using a password. The username and password
|
Authenticate to the server using a password. The username and password
|
||||||
are sent over an encrypted link.
|
are sent over an encrypted link.
|
||||||
|
|
||||||
If an C{event} is passed in, this method will return immediately, and
|
If an C{event} is passed in, this method will return immediately, and
|
||||||
the event will be triggered once authentication succeeds or fails. On
|
the event will be triggered once authentication succeeds or fails. On
|
||||||
success, L{is_authenticated} will return C{True}. On failure, you may
|
success, L{is_authenticated} will return C{True}. On failure, you may
|
||||||
|
@ -1114,7 +1114,7 @@ class Transport (threading.Thread):
|
||||||
Since 1.1, if no event is passed, this method will block until the
|
Since 1.1, if no event is passed, this method will block until the
|
||||||
authentication succeeds or fails. On failure, an exception is raised.
|
authentication succeeds or fails. On failure, an exception is raised.
|
||||||
Otherwise, the method simply returns.
|
Otherwise, the method simply returns.
|
||||||
|
|
||||||
Since 1.5, if no event is passed and C{fallback} is C{True} (the
|
Since 1.5, if no event is passed and C{fallback} is C{True} (the
|
||||||
default), if the server doesn't support plain password authentication
|
default), if the server doesn't support plain password authentication
|
||||||
but does support so-called "keyboard-interactive" mode, an attempt
|
but does support so-called "keyboard-interactive" mode, an attempt
|
||||||
|
@ -1123,11 +1123,11 @@ class Transport (threading.Thread):
|
||||||
made. This is useful for some recent Gentoo and Debian distributions,
|
made. This is useful for some recent Gentoo and Debian distributions,
|
||||||
which turn off plain password authentication in a misguided belief
|
which turn off plain password authentication in a misguided belief
|
||||||
that interactive authentication is "more secure". (It's not.)
|
that interactive authentication is "more secure". (It's not.)
|
||||||
|
|
||||||
If the server requires multi-step authentication (which is very rare),
|
If the server requires multi-step authentication (which is very rare),
|
||||||
this method will return a list of auth types permissible for the next
|
this method will return a list of auth types permissible for the next
|
||||||
step. Otherwise, in the normal case, an empty list is returned.
|
step. Otherwise, in the normal case, an empty list is returned.
|
||||||
|
|
||||||
@param username: the username to authenticate as
|
@param username: the username to authenticate as
|
||||||
@type username: str
|
@type username: str
|
||||||
@param password: the password to authenticate with
|
@param password: the password to authenticate with
|
||||||
|
@ -1142,7 +1142,7 @@ class Transport (threading.Thread):
|
||||||
@return: list of auth types permissible for the next stage of
|
@return: list of auth types permissible for the next stage of
|
||||||
authentication (normally empty)
|
authentication (normally empty)
|
||||||
@rtype: list
|
@rtype: list
|
||||||
|
|
||||||
@raise BadAuthenticationType: if password authentication isn't
|
@raise BadAuthenticationType: if password authentication isn't
|
||||||
allowed by the server for this user (and no event was passed in)
|
allowed by the server for this user (and no event was passed in)
|
||||||
@raise AuthenticationException: if the authentication failed (and no
|
@raise AuthenticationException: if the authentication failed (and no
|
||||||
|
@ -1188,12 +1188,12 @@ class Transport (threading.Thread):
|
||||||
"""
|
"""
|
||||||
Authenticate to the server using a private key. The key is used to
|
Authenticate to the server using a private key. The key is used to
|
||||||
sign data from the server, so it must include the private part.
|
sign data from the server, so it must include the private part.
|
||||||
|
|
||||||
If an C{event} is passed in, this method will return immediately, and
|
If an C{event} is passed in, this method will return immediately, and
|
||||||
the event will be triggered once authentication succeeds or fails. On
|
the event will be triggered once authentication succeeds or fails. On
|
||||||
success, L{is_authenticated} will return C{True}. On failure, you may
|
success, L{is_authenticated} will return C{True}. On failure, you may
|
||||||
use L{get_exception} to get more detailed error information.
|
use L{get_exception} to get more detailed error information.
|
||||||
|
|
||||||
Since 1.1, if no event is passed, this method will block until the
|
Since 1.1, if no event is passed, this method will block until the
|
||||||
authentication succeeds or fails. On failure, an exception is raised.
|
authentication succeeds or fails. On failure, an exception is raised.
|
||||||
Otherwise, the method simply returns.
|
Otherwise, the method simply returns.
|
||||||
|
@ -1212,7 +1212,7 @@ class Transport (threading.Thread):
|
||||||
@return: list of auth types permissible for the next stage of
|
@return: list of auth types permissible for the next stage of
|
||||||
authentication (normally empty)
|
authentication (normally empty)
|
||||||
@rtype: list
|
@rtype: list
|
||||||
|
|
||||||
@raise BadAuthenticationType: if public-key authentication isn't
|
@raise BadAuthenticationType: if public-key authentication isn't
|
||||||
allowed by the server for this user (and no event was passed in)
|
allowed by the server for this user (and no event was passed in)
|
||||||
@raise AuthenticationException: if the authentication failed (and no
|
@raise AuthenticationException: if the authentication failed (and no
|
||||||
|
@ -1232,18 +1232,18 @@ class Transport (threading.Thread):
|
||||||
# caller wants to wait for event themselves
|
# caller wants to wait for event themselves
|
||||||
return []
|
return []
|
||||||
return self.auth_handler.wait_for_response(my_event)
|
return self.auth_handler.wait_for_response(my_event)
|
||||||
|
|
||||||
def auth_interactive(self, username, handler, submethods=''):
|
def auth_interactive(self, username, handler, submethods=''):
|
||||||
"""
|
"""
|
||||||
Authenticate to the server interactively. A handler is used to answer
|
Authenticate to the server interactively. A handler is used to answer
|
||||||
arbitrary questions from the server. On many servers, this is just a
|
arbitrary questions from the server. On many servers, this is just a
|
||||||
dumb wrapper around PAM.
|
dumb wrapper around PAM.
|
||||||
|
|
||||||
This method will block until the authentication succeeds or fails,
|
This method will block until the authentication succeeds or fails,
|
||||||
peroidically calling the handler asynchronously to get answers to
|
peroidically calling the handler asynchronously to get answers to
|
||||||
authentication questions. The handler may be called more than once
|
authentication questions. The handler may be called more than once
|
||||||
if the server continues to ask questions.
|
if the server continues to ask questions.
|
||||||
|
|
||||||
The handler is expected to be a callable that will handle calls of the
|
The handler is expected to be a callable that will handle calls of the
|
||||||
form: C{handler(title, instructions, prompt_list)}. The C{title} is
|
form: C{handler(title, instructions, prompt_list)}. The C{title} is
|
||||||
meant to be a dialog-window title, and the C{instructions} are user
|
meant to be a dialog-window title, and the C{instructions} are user
|
||||||
|
@ -1251,13 +1251,13 @@ class Transport (threading.Thread):
|
||||||
prompts, each prompt being a tuple of C{(str, bool)}. The string is
|
prompts, each prompt being a tuple of C{(str, bool)}. The string is
|
||||||
the prompt and the boolean indicates whether the user text should be
|
the prompt and the boolean indicates whether the user text should be
|
||||||
echoed.
|
echoed.
|
||||||
|
|
||||||
A sample call would thus be:
|
A sample call would thus be:
|
||||||
C{handler('title', 'instructions', [('Password:', False)])}.
|
C{handler('title', 'instructions', [('Password:', False)])}.
|
||||||
|
|
||||||
The handler should return a list or tuple of answers to the server's
|
The handler should return a list or tuple of answers to the server's
|
||||||
questions.
|
questions.
|
||||||
|
|
||||||
If the server requires multi-step authentication (which is very rare),
|
If the server requires multi-step authentication (which is very rare),
|
||||||
this method will return a list of auth types permissible for the next
|
this method will return a list of auth types permissible for the next
|
||||||
step. Otherwise, in the normal case, an empty list is returned.
|
step. Otherwise, in the normal case, an empty list is returned.
|
||||||
|
@ -1271,12 +1271,12 @@ class Transport (threading.Thread):
|
||||||
@return: list of auth types permissible for the next stage of
|
@return: list of auth types permissible for the next stage of
|
||||||
authentication (normally empty).
|
authentication (normally empty).
|
||||||
@rtype: list
|
@rtype: list
|
||||||
|
|
||||||
@raise BadAuthenticationType: if public-key authentication isn't
|
@raise BadAuthenticationType: if public-key authentication isn't
|
||||||
allowed by the server for this user
|
allowed by the server for this user
|
||||||
@raise AuthenticationException: if the authentication failed
|
@raise AuthenticationException: if the authentication failed
|
||||||
@raise SSHException: if there was a network error
|
@raise SSHException: if there was a network error
|
||||||
|
|
||||||
@since: 1.5
|
@since: 1.5
|
||||||
"""
|
"""
|
||||||
if (not self.active) or (not self.initial_kex_done):
|
if (not self.active) or (not self.initial_kex_done):
|
||||||
|
@ -1325,43 +1325,43 @@ class Transport (threading.Thread):
|
||||||
@type hexdump: bool
|
@type hexdump: bool
|
||||||
"""
|
"""
|
||||||
self.packetizer.set_hexdump(hexdump)
|
self.packetizer.set_hexdump(hexdump)
|
||||||
|
|
||||||
def get_hexdump(self):
|
def get_hexdump(self):
|
||||||
"""
|
"""
|
||||||
Return C{True} if the transport is currently logging hex dumps of
|
Return C{True} if the transport is currently logging hex dumps of
|
||||||
protocol traffic.
|
protocol traffic.
|
||||||
|
|
||||||
@return: C{True} if hex dumps are being logged
|
@return: C{True} if hex dumps are being logged
|
||||||
@rtype: bool
|
@rtype: bool
|
||||||
|
|
||||||
@since: 1.4
|
@since: 1.4
|
||||||
"""
|
"""
|
||||||
return self.packetizer.get_hexdump()
|
return self.packetizer.get_hexdump()
|
||||||
|
|
||||||
def use_compression(self, compress=True):
|
def use_compression(self, compress=True):
|
||||||
"""
|
"""
|
||||||
Turn on/off compression. This will only have an affect before starting
|
Turn on/off compression. This will only have an affect before starting
|
||||||
the transport (ie before calling L{connect}, etc). By default,
|
the transport (ie before calling L{connect}, etc). By default,
|
||||||
compression is off since it negatively affects interactive sessions.
|
compression is off since it negatively affects interactive sessions.
|
||||||
|
|
||||||
@param compress: C{True} to ask the remote client/server to compress
|
@param compress: C{True} to ask the remote client/server to compress
|
||||||
traffic; C{False} to refuse compression
|
traffic; C{False} to refuse compression
|
||||||
@type compress: bool
|
@type compress: bool
|
||||||
|
|
||||||
@since: 1.5.2
|
@since: 1.5.2
|
||||||
"""
|
"""
|
||||||
if compress:
|
if compress:
|
||||||
self._preferred_compression = ( 'zlib@openssh.com', 'zlib', 'none' )
|
self._preferred_compression = ( 'zlib@openssh.com', 'zlib', 'none' )
|
||||||
else:
|
else:
|
||||||
self._preferred_compression = ( 'none', )
|
self._preferred_compression = ( 'none', )
|
||||||
|
|
||||||
def getpeername(self):
|
def getpeername(self):
|
||||||
"""
|
"""
|
||||||
Return the address of the remote side of this Transport, if possible.
|
Return the address of the remote side of this Transport, if possible.
|
||||||
This is effectively a wrapper around C{'getpeername'} on the underlying
|
This is effectively a wrapper around C{'getpeername'} on the underlying
|
||||||
socket. If the socket-like object has no C{'getpeername'} method,
|
socket. If the socket-like object has no C{'getpeername'} method,
|
||||||
then C{("unknown", 0)} is returned.
|
then C{("unknown", 0)} is returned.
|
||||||
|
|
||||||
@return: the address if the remote host, if known
|
@return: the address if the remote host, if known
|
||||||
@rtype: tuple(str, int)
|
@rtype: tuple(str, int)
|
||||||
"""
|
"""
|
||||||
|
@ -1377,7 +1377,7 @@ class Transport (threading.Thread):
|
||||||
|
|
||||||
### internals...
|
### internals...
|
||||||
|
|
||||||
|
|
||||||
def _log(self, level, msg, *args):
|
def _log(self, level, msg, *args):
|
||||||
if issubclass(type(msg), list):
|
if issubclass(type(msg), list):
|
||||||
for m in msg:
|
for m in msg:
|
||||||
|
@ -1498,13 +1498,13 @@ class Transport (threading.Thread):
|
||||||
self.server_accept_cv.notify()
|
self.server_accept_cv.notify()
|
||||||
finally:
|
finally:
|
||||||
self.lock.release()
|
self.lock.release()
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
# (use the exposed "run" method, because if we specify a thread target
|
# (use the exposed "run" method, because if we specify a thread target
|
||||||
# of a private method, threading.Thread will keep a reference to it
|
# of a private method, threading.Thread will keep a reference to it
|
||||||
# indefinitely, creating a GC cycle and not letting Transport ever be
|
# indefinitely, creating a GC cycle and not letting Transport ever be
|
||||||
# GC'd. it's a bug in Thread.)
|
# GC'd. it's a bug in 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:
|
||||||
|
@ -1929,7 +1929,7 @@ class Transport (threading.Thread):
|
||||||
self.global_response = m
|
self.global_response = m
|
||||||
if self.completion_event is not None:
|
if self.completion_event is not None:
|
||||||
self.completion_event.set()
|
self.completion_event.set()
|
||||||
|
|
||||||
def _parse_request_failure(self, m):
|
def _parse_request_failure(self, m):
|
||||||
self._log(DEBUG, 'Global request denied.')
|
self._log(DEBUG, 'Global request denied.')
|
||||||
self.global_response = None
|
self.global_response = None
|
||||||
|
@ -2018,7 +2018,7 @@ class Transport (threading.Thread):
|
||||||
origin_addr = m.get_string()
|
origin_addr = m.get_string()
|
||||||
origin_port = m.get_int()
|
origin_port = m.get_int()
|
||||||
reason = self.server_object.check_channel_direct_tcpip_request(
|
reason = self.server_object.check_channel_direct_tcpip_request(
|
||||||
my_chanid, (origin_addr, origin_port),
|
my_chanid, (origin_addr, origin_port),
|
||||||
(dest_addr, dest_port))
|
(dest_addr, dest_port))
|
||||||
else:
|
else:
|
||||||
reason = self.server_object.check_channel_request(kind, my_chanid)
|
reason = self.server_object.check_channel_request(kind, my_chanid)
|
||||||
|
@ -2034,7 +2034,7 @@ class Transport (threading.Thread):
|
||||||
msg.add_string('en')
|
msg.add_string('en')
|
||||||
self._send_message(msg)
|
self._send_message(msg)
|
||||||
return
|
return
|
||||||
|
|
||||||
chan = Channel(my_chanid)
|
chan = Channel(my_chanid)
|
||||||
self.lock.acquire()
|
self.lock.acquire()
|
||||||
try:
|
try:
|
||||||
|
|
Loading…
Reference in New Issue