summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--dev-requirements.txt2
-rw-r--r--paramiko/__init__.py2
-rw-r--r--paramiko/file.py2
-rw-r--r--paramiko/packet.py1
-rw-r--r--paramiko/proxy.py33
-rw-r--r--paramiko/server.py2
-rw-r--r--paramiko/sftp_client.py2
-rw-r--r--paramiko/transport.py17
-rw-r--r--setup.py45
-rw-r--r--sites/www/changelog.rst37
10 files changed, 104 insertions, 39 deletions
diff --git a/dev-requirements.txt b/dev-requirements.txt
index 26d7aac3..e4dd942d 100644
--- a/dev-requirements.txt
+++ b/dev-requirements.txt
@@ -1,3 +1,5 @@
+# Older junk
+tox>=1.4,<1.5
# For newer tasks like building Sphinx docs.
# NOTE: Requires Python >=2.6
invoke>=0.7.0
diff --git a/paramiko/__init__.py b/paramiko/__init__.py
index b0d691c5..ce3f0cf9 100644
--- a/paramiko/__init__.py
+++ b/paramiko/__init__.py
@@ -23,7 +23,7 @@ if sys.version_info < (2, 5):
__author__ = "Jeff Forcier <jeff@bitprophet.org>"
-__version__ = "1.10.7"
+__version__ = "1.11.5"
__version_info__ = tuple([ int(d) for d in __version__.split(".") ])
__license__ = "GNU Lesser General Public License (LGPL)"
diff --git a/paramiko/file.py b/paramiko/file.py
index 253ffcd0..571ee6e9 100644
--- a/paramiko/file.py
+++ b/paramiko/file.py
@@ -436,7 +436,7 @@ class BufferedFile (object):
return
if self.newlines is None:
self.newlines = newline
- elif (type(self.newlines) is str) and (self.newlines != newline):
+ elif isinstance(self.newlines, basestring) and (self.newlines != newline):
self.newlines = (self.newlines, newline)
elif newline not in self.newlines:
self.newlines += (newline,)
diff --git a/paramiko/packet.py b/paramiko/packet.py
index 397193cd..62cda219 100644
--- a/paramiko/packet.py
+++ b/paramiko/packet.py
@@ -152,7 +152,6 @@ class Packetizer (object):
def close(self):
self.__closed = True
- self.__socket.close()
def set_hexdump(self, hexdump):
self.__dump_packets = hexdump
diff --git a/paramiko/proxy.py b/paramiko/proxy.py
index 30d596ba..10f0728f 100644
--- a/paramiko/proxy.py
+++ b/paramiko/proxy.py
@@ -17,10 +17,13 @@
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+from datetime import datetime
import os
from shlex import split as shlsplit
import signal
from subprocess import Popen, PIPE
+from select import select
+import socket
from paramiko.ssh_exception import ProxyCommandFailure
@@ -44,6 +47,8 @@ class ProxyCommand(object):
"""
self.cmd = shlsplit(command_line)
self.process = Popen(self.cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE)
+ self.timeout = None
+ self.buffer = []
def send(self, content):
"""
@@ -59,7 +64,7 @@ class ProxyCommand(object):
# died and we can't proceed. The best option here is to
# raise an exception informing the user that the informed
# ProxyCommand is not working.
- raise BadProxyCommand(' '.join(self.cmd), e.strerror)
+ raise ProxyCommandFailure(' '.join(self.cmd), e.strerror)
return len(content)
def recv(self, size):
@@ -71,14 +76,30 @@ class ProxyCommand(object):
:return: the length of the read content, as an `int`
"""
try:
- return os.read(self.process.stdout.fileno(), size)
+ start = datetime.now()
+ while len(self.buffer) < size:
+ if self.timeout is not None:
+ elapsed = (datetime.now() - start).microseconds
+ timeout = self.timeout * 1000 * 1000 # to microseconds
+ if elapsed >= timeout:
+ raise socket.timeout()
+ r, w, x = select([self.process.stdout], [], [], 0.0)
+ if r and r[0] == self.process.stdout:
+ b = os.read(self.process.stdout.fileno(), 1)
+ # Store in class-level buffer for persistence across
+ # timeouts; this makes us act more like a real socket
+ # (where timeouts don't actually drop data.)
+ self.buffer.append(b)
+ result = ''.join(self.buffer)
+ self.buffer = []
+ return result
+ except socket.timeout:
+ raise # socket.timeout is a subclass of IOError
except IOError, e:
- raise BadProxyCommand(' '.join(self.cmd), e.strerror)
+ raise ProxyCommandFailure(' '.join(self.cmd), e.strerror)
def close(self):
os.kill(self.process.pid, signal.SIGTERM)
def settimeout(self, timeout):
- # Timeouts are meaningless for this implementation, but are part of the
- # spec, so must be present.
- pass
+ self.timeout = timeout
diff --git a/paramiko/server.py b/paramiko/server.py
index c3f3a0c4..738cad1a 100644
--- a/paramiko/server.py
+++ b/paramiko/server.py
@@ -493,7 +493,7 @@ class InteractiveQuery (object):
self.instructions = instructions
self.prompts = []
for x in prompts:
- if (type(x) is str) or (type(x) is unicode):
+ if isinstance(x, basestring):
self.add_prompt(x)
else:
self.add_prompt(x[0], x[1])
diff --git a/paramiko/sftp_client.py b/paramiko/sftp_client.py
index 0580bc43..13e830c4 100644
--- a/paramiko/sftp_client.py
+++ b/paramiko/sftp_client.py
@@ -660,7 +660,7 @@ class SFTPClient(BaseSFTP):
msg.add_int(item)
elif isinstance(item, long):
msg.add_int64(item)
- elif isinstance(item, str):
+ elif isinstance(item, basestring):
msg.add_string(item)
elif isinstance(item, SFTPAttributes):
item._pack(msg)
diff --git a/paramiko/transport.py b/paramiko/transport.py
index dfb3df81..6f3e3f4b 100644
--- a/paramiko/transport.py
+++ b/paramiko/transport.py
@@ -277,7 +277,6 @@ class Transport (threading.Thread):
.. versionadded:: 1.5.3
"""
- self.sock.close()
self.close()
def get_security_options(self):
@@ -487,11 +486,10 @@ class Transport (threading.Thread):
"""
if not self.active:
return
- self.active = False
- self.packetizer.close()
- self.join()
+ self.stop_thread()
for chan in self._channels.values():
chan._unlink()
+ self.sock.close()
def get_remote_server_key(self):
"""
@@ -1239,6 +1237,8 @@ class Transport (threading.Thread):
def stop_thread(self):
self.active = False
self.packetizer.close()
+ while self.isAlive():
+ self.join(10)
### internals...
@@ -1387,10 +1387,6 @@ class Transport (threading.Thread):
# containers.
Random.atfork()
- # Hold reference to 'sys' so we can test sys.modules to detect
- # interpreter shutdown.
- self.sys = sys
-
# active=True occurs before the thread is launched, to avoid a race
_active_threads.append(self)
if self.server_mode:
@@ -1460,7 +1456,10 @@ class Transport (threading.Thread):
self.saved_exception = e
except socket.error, e:
if type(e.args) is tuple:
- emsg = '%s (%d)' % (e.args[1], e.args[0])
+ if e.args:
+ emsg = '%s (%d)' % (e.args[1], e.args[0])
+ else: # empty tuple, e.g. socket.timeout
+ emsg = str(e) or repr(e)
else:
emsg = e.args
self._log(ERROR, 'Socket exception: ' + emsg)
diff --git a/setup.py b/setup.py
index 7dc5c61e..6222a7b0 100644
--- a/setup.py
+++ b/setup.py
@@ -51,21 +51,30 @@ if sys.platform == 'darwin':
setup_helper.install_custom_make_tarball()
-setup(name = "paramiko",
- version = "1.10.7",
- description = "SSH2 protocol library",
- author = "Jeff Forcier",
- author_email = "jeff@bitprophet.org",
- url = "https://github.com/paramiko/paramiko/",
- packages = [ 'paramiko' ],
- license = 'LGPL',
- platforms = 'Posix; MacOS X; Windows',
- classifiers = [ 'Development Status :: 5 - Production/Stable',
- 'Intended Audience :: Developers',
- 'License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)',
- 'Operating System :: OS Independent',
- 'Topic :: Internet',
- 'Topic :: Security :: Cryptography' ],
- long_description = longdesc,
- **kw
- )
+setup(
+ name = "paramiko",
+ version = "1.11.5",
+ description = "SSH2 protocol library",
+ long_description = longdesc,
+ author = "Jeff Forcier",
+ author_email = "jeff@bitprophet.org",
+ url = "https://github.com/paramiko/paramiko/",
+ packages = [ 'paramiko' ],
+ license = 'LGPL',
+ platforms = 'Posix; MacOS X; Windows',
+ classifiers = [
+ 'Development Status :: 5 - Production/Stable',
+ 'Intended Audience :: Developers',
+ 'License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)',
+ 'Operating System :: OS Independent',
+ 'Topic :: Internet',
+ 'Topic :: Security :: Cryptography',
+ 'Programming Language :: Python',
+ 'Programming Language :: Python :: 2',
+ 'Programming Language :: Python :: 2.5',
+ 'Programming Language :: Python :: 2.6',
+ 'Programming Language :: Python :: 2.7',
+ 'Programming Language :: Python :: 2 :: Only',
+ ],
+ **kw
+)
diff --git a/sites/www/changelog.rst b/sites/www/changelog.rst
index 87b05a87..cf5c142b 100644
--- a/sites/www/changelog.rst
+++ b/sites/www/changelog.rst
@@ -2,6 +2,12 @@
Changelog
=========
+* :support:`284` Add Python language trove identifiers to ``setup.py``. Thanks
+ to Alex Gaynor for catch & patch.
+* :bug:`235` Improve string type testing in a handful of spots (e.g. ``s/if
+ type(x) is str/if isinstance(x, basestring)/g``.) Thanks to ``@ksamuel`` for
+ the report.
+* :release:`1.11.5 <2014-03-13>`
* :release:`1.10.7 <2014-03-13>`
* :support:`256 backported` Convert API documentation to Sphinx, yielding a new
API docs website to replace the old Epydoc one. Thanks to Olle Lundberg for
@@ -10,18 +16,31 @@ Changelog
protect against `timing-based attacks
<http://codahale.com/a-lesson-in-timing-attacks/>`_. Thanks to Alex Gaynor
for the patch.
+* :release:`1.11.4 <2014-02-14>`
* :release:`1.10.6 <2014-02-14>`
+* :bug:`252` (`Fabric #1020 <https://github.com/fabric/fabric/issues/1020>`_)
+ Enhanced the implementation of ``ProxyCommand`` to avoid a deadlock/hang
+ condition that frequently occurs at ``Transport`` shutdown time. Thanks to
+ Mateusz Kobos, Matthijs van der Vleuten and Guillaume Zitta for the original
+ reports and to Marius Gedminas for helping test nontrivial use cases.
+* :bug:`268` Fix some missed renames of ``ProxyCommand`` related error classes.
+ Thanks to Marius Gedminas for catch & patch.
* :bug:`34` (PR :issue:`35`) Fix SFTP prefetching incompatibility with some
SFTP servers regarding request/response ordering. Thanks to Richard
- Kettlewell for catch & patch.
+ Kettlewell.
* :bug:`193` (and its attentant PRs :issue:`230` & :issue:`253`) Fix SSH agent
problems present on Windows. Thanks to David Hobbs for initial report and to
Aarni Koskela & Olle Lundberg for the patches.
+* :release:`1.11.3 <2014-01-08>`
* :release:`1.10.5 <2014-01-08>`
* :bug:`176` Fix AttributeError bugs in known_hosts file (re)loading. Thanks
to Nathan Scowcroft for the patch & Martin Blumenstingl for the initial test
case.
+* :release:`1.11.2 <2013-09-27>`
* :release:`1.10.4 <2013-09-27>`
+* :bug:`156 (1.11+)` Fix potential deadlock condition when using Channel
+ objects as sockets (e.g. when using SSH gatewaying). Thanks to Steven Noonan
+ and Frank Arnold for catch & patch.
* :bug:`179` Fix a missing variable causing errors when an ssh_config file has
a non-default AddressFamily set. Thanks to Ed Marshall & Tomaz Muraus for
catch & patch.
@@ -29,6 +48,7 @@ Changelog
Buchanan for catch & Dave Foster for patch.
* :bug:`199` Typo fix in the license header cross-project. Thanks to Armin
Ronacher for catch & patch.
+* :release:`1.11.1 <2013-09-20>`
* :release:`1.10.3 <2013-09-20>`
* :bug:`162` Clean up HMAC module import to avoid deadlocks in certain uses of
SSHClient. Thanks to Gernot Hillier for the catch & suggested fix.
@@ -36,7 +56,22 @@ Changelog
Thanks to Jonathan Halcrow for catch & patch.
* :bug:`168` Update config handling to properly handle multiple 'localforward'
and 'remoteforward' keys. Thanks to Emre Yılmaz for the patch.
+* :release:`1.11.0 <2013-07-26>`
* :release:`1.10.2 <2013-07-26>`
+* :bug:`98 major` On Windows, when interacting with the PuTTY PAgeant, Paramiko
+ now creates the shared memory map with explicit Security Attributes of the
+ user, which is the same technique employed by the canonical PuTTY library to
+ avoid permissions issues when Paramiko is running under a different UAC
+ context than the PuTTY Ageant process. Thanks to Jason R. Coombs for the
+ patch.
+* :support:`100` Remove use of PyWin32 in ``win_pageant`` module. Module was
+ already dependent on ctypes for constructing appropriate structures and had
+ ctypes implementations of all functionality. Thanks to Jason R. Coombs for
+ the patch.
+* :bug:`87 major` Ensure updates to ``known_hosts`` files account for any
+ updates to said files after Paramiko initially read them. (Includes related
+ fix to guard against duplicate entries during subsequent ``known_hosts``
+ loads.) Thanks to ``@sunweaver`` for the contribution.
* :bug:`153` (also :issue:`67`) Warn on parse failure when reading known_hosts
file. Thanks to ``@glasserc`` for patch.
* :bug:`146` Indentation fixes for readability. Thanks to Abhinav Upadhyay for