From b96e7e41322e0c71d379cc04a524287a1c5fae4d Mon Sep 17 00:00:00 2001 From: Ivan Barria Date: Tue, 9 Apr 2013 02:14:51 -0300 Subject: [PATCH 01/36] Update demo.py why import threading? --- demos/demo.py | 1 - 1 file changed, 1 deletion(-) diff --git a/demos/demo.py b/demos/demo.py index 05524d3..c21a926 100755 --- a/demos/demo.py +++ b/demos/demo.py @@ -26,7 +26,6 @@ import os import select import socket import sys -import threading import time import traceback From 4f481a57a291316e75b0ce0b5f159e66b49ffe3a Mon Sep 17 00:00:00 2001 From: Mike Gabriel Date: Fri, 12 Oct 2012 09:36:42 +0200 Subject: [PATCH 02/36] Store hostname hashes in memory rathen than the non-hashed host entries. Also assures that the host entries in known_hosts get saved in hashed format as it is currently standard in OpenSSH. --- paramiko/hostkeys.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/paramiko/hostkeys.py b/paramiko/hostkeys.py index e739312..da5b66c 100644 --- a/paramiko/hostkeys.py +++ b/paramiko/hostkeys.py @@ -141,6 +141,8 @@ class HostKeys (UserDict.DictMixin): if (hostname in e.hostnames) and (e.key.get_name() == keytype): e.key = key return + if not hostname.startswith('|1|') and hash_hostname: + hostname = self.hash_host(hostname) self._entries.append(HostKeyEntry([hostname], key)) def load(self, filename): From 080bece2586d348b9791892cd6e5670a7afdb1a9 Mon Sep 17 00:00:00 2001 From: Mike Gabriel Date: Fri, 12 Oct 2012 09:41:52 +0200 Subject: [PATCH 03/36] Assure that host entries in known_hosts files do not duplicate endlessly if keys from known_hosts are loaded via HostKeys.load() more than once (e.g. for refreshing the list of known hosts during runtime). --- paramiko/hostkeys.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/paramiko/hostkeys.py b/paramiko/hostkeys.py index da5b66c..27b9fef 100644 --- a/paramiko/hostkeys.py +++ b/paramiko/hostkeys.py @@ -168,7 +168,12 @@ class HostKeys (UserDict.DictMixin): continue e = HostKeyEntry.from_line(line) if e is not None: - self._entries.append(e) + _hostnames = e.hostnames + for h in _hostnames: + if self.check(h, e.key): + e.hostnames.remove(h) + if len(e.hostnames): + self._entries.append(e) f.close() def save(self, filename): From 81f87f1d5eb4fa89472114f45faa3a994fc7db7d Mon Sep 17 00:00:00 2001 From: Mike Gabriel Date: Fri, 12 Oct 2012 09:50:51 +0200 Subject: [PATCH 04/36] Load host entries from the known_hosts file(s) before writing the file from RAM to disk. Avoids loss of host entries in case other SSH clients have written to the known_hosts file(s) meanwhile. --- paramiko/client.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/paramiko/client.py b/paramiko/client.py index 5b71958..4fa28e5 100644 --- a/paramiko/client.py +++ b/paramiko/client.py @@ -186,6 +186,12 @@ class SSHClient (object): @raise IOError: if the file could not be written """ + + # update local host keys from file (in case other SSH clients + # have written to the known_hosts file meanwhile. + if self.known_hosts is not None: + self.load_host_keys(self.known_hosts) + f = open(filename, 'w') f.write('# SSH host keys collected by paramiko\n') for hostname, keys in self._host_keys.iteritems(): From 1b928df15ec4b95b0f96f26dc3740f1a0a91ca4a Mon Sep 17 00:00:00 2001 From: Mike Gabriel Date: Fri, 12 Oct 2012 09:51:18 +0200 Subject: [PATCH 05/36] do not write ,,garbage'' to known_hosts file(s) --- paramiko/client.py | 1 - 1 file changed, 1 deletion(-) diff --git a/paramiko/client.py b/paramiko/client.py index 4fa28e5..493d548 100644 --- a/paramiko/client.py +++ b/paramiko/client.py @@ -193,7 +193,6 @@ class SSHClient (object): self.load_host_keys(self.known_hosts) f = open(filename, 'w') - f.write('# SSH host keys collected by paramiko\n') for hostname, keys in self._host_keys.iteritems(): for keytype, key in keys.iteritems(): f.write('%s %s %s\n' % (hostname, keytype, key.get_base64())) From 6747d9944af483796890809b37a9cb260e08ee6d Mon Sep 17 00:00:00 2001 From: Jeff Forcier Date: Sat, 27 Apr 2013 20:50:29 -0700 Subject: [PATCH 06/36] Changelog re #87 --- NEWS | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/NEWS b/NEWS index 2bb5341..2b49898 100644 --- a/NEWS +++ b/NEWS @@ -24,6 +24,10 @@ v1.11.0 (DD MM YYYY) dependent on ctypes for constructing appropriate structures and had ctypes implementations of all functionality. Thanks to Jason R. Coombs for the patch. +* #87: 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. v1.10.1 (5th Apr 2013) ---------------------- From f861c2ff48f420b3be16f15bbf36c6ee3f779c38 Mon Sep 17 00:00:00 2001 From: Jeff Forcier Date: Sat, 27 Apr 2013 20:55:50 -0700 Subject: [PATCH 07/36] Back out broken but non-required hostname hash change --- paramiko/hostkeys.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/paramiko/hostkeys.py b/paramiko/hostkeys.py index 27b9fef..1ddb25b 100644 --- a/paramiko/hostkeys.py +++ b/paramiko/hostkeys.py @@ -141,8 +141,6 @@ class HostKeys (UserDict.DictMixin): if (hostname in e.hostnames) and (e.key.get_name() == keytype): e.key = key return - if not hostname.startswith('|1|') and hash_hostname: - hostname = self.hash_host(hostname) self._entries.append(HostKeyEntry([hostname], key)) def load(self, filename): From e6c23f23f4e6b8e6eb577d9b486dc21114b5a398 Mon Sep 17 00:00:00 2001 From: Abhinav Upadhyay Date: Sat, 9 Mar 2013 00:09:20 +0530 Subject: [PATCH 08/36] Fix indentation at few places. --- paramiko/agent.py | 10 +++++----- paramiko/config.py | 4 ++-- paramiko/transport.py | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/paramiko/agent.py b/paramiko/agent.py index 1dd3063..d4ff703 100644 --- a/paramiko/agent.py +++ b/paramiko/agent.py @@ -255,11 +255,11 @@ class AgentServerProxy(AgentSSH): self.close() def connect(self): - conn_sock = self.__t.open_forward_agent_channel() - if conn_sock is None: - raise SSHException('lost ssh-agent') - conn_sock.set_name('auth-agent') - self._connect(conn_sock) + conn_sock = self.__t.open_forward_agent_channel() + if conn_sock is None: + raise SSHException('lost ssh-agent') + conn_sock.set_name('auth-agent') + self._connect(conn_sock) def close(self): """ diff --git a/paramiko/config.py b/paramiko/config.py index e41bae4..31caf29 100644 --- a/paramiko/config.py +++ b/paramiko/config.py @@ -135,7 +135,7 @@ class SSHConfig (object): else: host['config']['identityfile'] = [value] elif key not in host['config']: - host['config'].update({key: value}) + host['config'].update({key: value}) self._config.append(host) def lookup(self, hostname): @@ -252,5 +252,5 @@ class SSHConfig (object): config[k][item] = config[k][item].\ replace(find, str(replace)) else: - config[k] = config[k].replace(find, str(replace)) + config[k] = config[k].replace(find, str(replace)) return config diff --git a/paramiko/transport.py b/paramiko/transport.py index fd6dab7..201a253 100644 --- a/paramiko/transport.py +++ b/paramiko/transport.py @@ -1439,7 +1439,7 @@ class Transport (threading.Thread): break self.clear_to_send_lock.release() if time.time() > start + self.clear_to_send_timeout: - raise SSHException('Key-exchange timed out waiting for key negotiation') + raise SSHException('Key-exchange timed out waiting for key negotiation') try: self._send_message(data) finally: From 3966ac103c988218be02371803817b66b4deab17 Mon Sep 17 00:00:00 2001 From: Jeff Forcier Date: Sat, 27 Apr 2013 22:12:24 -0700 Subject: [PATCH 09/36] Changelog re #146 (also start 10.10.2 section) --- NEWS | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/NEWS b/NEWS index 7a983ba..1bb2d37 100644 --- a/NEWS +++ b/NEWS @@ -12,6 +12,12 @@ Issues noted as "Fabric #NN" can be found at https://github.com/fabric/fabric/. Releases ======== +v1.10.2 (DD MM 2013) +-------------------- + +* #146: Indentation fixes for readability. Thanks to Abhinav Upadhyay for catch + & patch. + v1.10.1 (5th Apr 2013) ---------------------- From aee2355d24277405867a8cb4ce8ce9616fee9d5b Mon Sep 17 00:00:00 2001 From: Ethan Glasser-Camp Date: Mon, 25 Mar 2013 14:35:24 -0400 Subject: [PATCH 10/36] Warn on parse failure when reading known_hosts --- NEWS | 2 ++ paramiko/hostkeys.py | 11 ++++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/NEWS b/NEWS index 1bb2d37..efee92d 100644 --- a/NEWS +++ b/NEWS @@ -15,6 +15,8 @@ Releases v1.10.2 (DD MM 2013) -------------------- +* #153, #67: Warn on parse failure when reading known_hosts + file. Thanks to `@glasserc` for patch. * #146: Indentation fixes for readability. Thanks to Abhinav Upadhyay for catch & patch. diff --git a/paramiko/hostkeys.py b/paramiko/hostkeys.py index e739312..c54d2e7 100644 --- a/paramiko/hostkeys.py +++ b/paramiko/hostkeys.py @@ -28,6 +28,7 @@ import UserDict from paramiko.common import * from paramiko.dsskey import DSSKey from paramiko.rsakey import RSAKey +from paramiko.util import get_logger class InvalidHostKey(Exception): @@ -48,7 +49,7 @@ class HostKeyEntry: self.hostnames = hostnames self.key = key - def from_line(cls, line): + def from_line(cls, line, lineno=None): """ Parses the given line of text to find the names for the host, the type of key, and the key data. The line is expected to be in the @@ -61,9 +62,12 @@ class HostKeyEntry: @param line: a line from an OpenSSH known_hosts file @type line: str """ + log = get_logger('paramiko.hostkeys') fields = line.split(' ') if len(fields) < 3: # Bad number of fields + log.warn("Not enough fields found in known_hosts in line %s (%r)" % + (lineno, line)) return None fields = fields[:3] @@ -78,6 +82,7 @@ class HostKeyEntry: elif keytype == 'ssh-dss': key = DSSKey(data=base64.decodestring(key)) else: + log.warn("Unable to handle key of type %s" % (keytype,)) return None except binascii.Error, e: raise InvalidHostKey(line, e) @@ -160,11 +165,11 @@ class HostKeys (UserDict.DictMixin): @raise IOError: if there was an error reading the file """ f = open(filename, 'r') - for line in f: + for lineno, line in enumerate(f): line = line.strip() if (len(line) == 0) or (line[0] == '#'): continue - e = HostKeyEntry.from_line(line) + e = HostKeyEntry.from_line(line, lineno) if e is not None: self._entries.append(e) f.close() From 8c7f120c2cfb119ece27b4eea375de10ef5df554 Mon Sep 17 00:00:00 2001 From: Ethan Glasser-Camp Date: Mon, 25 Mar 2013 14:35:24 -0400 Subject: [PATCH 11/36] Warn on parse failure when reading known_hosts --- NEWS | 2 ++ paramiko/hostkeys.py | 11 ++++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/NEWS b/NEWS index 1bb2d37..efee92d 100644 --- a/NEWS +++ b/NEWS @@ -15,6 +15,8 @@ Releases v1.10.2 (DD MM 2013) -------------------- +* #153, #67: Warn on parse failure when reading known_hosts + file. Thanks to `@glasserc` for patch. * #146: Indentation fixes for readability. Thanks to Abhinav Upadhyay for catch & patch. diff --git a/paramiko/hostkeys.py b/paramiko/hostkeys.py index e739312..c54d2e7 100644 --- a/paramiko/hostkeys.py +++ b/paramiko/hostkeys.py @@ -28,6 +28,7 @@ import UserDict from paramiko.common import * from paramiko.dsskey import DSSKey from paramiko.rsakey import RSAKey +from paramiko.util import get_logger class InvalidHostKey(Exception): @@ -48,7 +49,7 @@ class HostKeyEntry: self.hostnames = hostnames self.key = key - def from_line(cls, line): + def from_line(cls, line, lineno=None): """ Parses the given line of text to find the names for the host, the type of key, and the key data. The line is expected to be in the @@ -61,9 +62,12 @@ class HostKeyEntry: @param line: a line from an OpenSSH known_hosts file @type line: str """ + log = get_logger('paramiko.hostkeys') fields = line.split(' ') if len(fields) < 3: # Bad number of fields + log.warn("Not enough fields found in known_hosts in line %s (%r)" % + (lineno, line)) return None fields = fields[:3] @@ -78,6 +82,7 @@ class HostKeyEntry: elif keytype == 'ssh-dss': key = DSSKey(data=base64.decodestring(key)) else: + log.warn("Unable to handle key of type %s" % (keytype,)) return None except binascii.Error, e: raise InvalidHostKey(line, e) @@ -160,11 +165,11 @@ class HostKeys (UserDict.DictMixin): @raise IOError: if there was an error reading the file """ f = open(filename, 'r') - for line in f: + for lineno, line in enumerate(f): line = line.strip() if (len(line) == 0) or (line[0] == '#'): continue - e = HostKeyEntry.from_line(line) + e = HostKeyEntry.from_line(line, lineno) if e is not None: self._entries.append(e) f.close() From b2b8d5d0a6e808b385e6f3ec41f3cfef7ee1a6ec Mon Sep 17 00:00:00 2001 From: Jeff Forcier Date: Sun, 28 Apr 2013 18:41:10 -0700 Subject: [PATCH 12/36] Add explicit link to updated API docs. Fixes #160 --- README | 1 + 1 file changed, 1 insertion(+) diff --git a/README b/README index 68e7434..1899819 100644 --- a/README +++ b/README @@ -8,6 +8,7 @@ paramiko :Copyright: Copyright (c) 2013 Jeff Forcier :License: LGPL :Homepage: https://github.com/paramiko/paramiko/ +:API docs: http://docs.paramiko.org What From 777d1576ca825f43d00f699865ead9bc0c37c637 Mon Sep 17 00:00:00 2001 From: Jeff Forcier Date: Sun, 28 Apr 2013 19:01:40 -0700 Subject: [PATCH 13/36] Bump dev version --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index d6caccf..02a71e5 100644 --- a/setup.py +++ b/setup.py @@ -52,7 +52,7 @@ if sys.platform == 'darwin': setup(name = "paramiko", - version = "1.10.1", + version = "1.11.0", description = "SSH2 protocol library", author = "Jeff Forcier", author_email = "jeff@bitprophet.org", From 3c2f01c91f798bc2ecefbd7c3864dc5e8c5af5c8 Mon Sep 17 00:00:00 2001 From: Jeff Forcier Date: Sun, 5 May 2013 13:59:34 -0700 Subject: [PATCH 14/36] Flip bad known_hosts line to INFO from WARN re #153 --- paramiko/hostkeys.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/paramiko/hostkeys.py b/paramiko/hostkeys.py index c54d2e7..93a621d 100644 --- a/paramiko/hostkeys.py +++ b/paramiko/hostkeys.py @@ -66,7 +66,7 @@ class HostKeyEntry: fields = line.split(' ') if len(fields) < 3: # Bad number of fields - log.warn("Not enough fields found in known_hosts in line %s (%r)" % + log.info("Not enough fields found in known_hosts in line %s (%r)" % (lineno, line)) return None fields = fields[:3] @@ -82,7 +82,7 @@ class HostKeyEntry: elif keytype == 'ssh-dss': key = DSSKey(data=base64.decodestring(key)) else: - log.warn("Unable to handle key of type %s" % (keytype,)) + log.info("Unable to handle key of type %s" % (keytype,)) return None except binascii.Error, e: raise InvalidHostKey(line, e) From 3399d519e04c73ea2c16df4037da9de20b5c83f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emre=20Y=C4=B1lmaz?= Date: Tue, 21 May 2013 00:40:28 +0300 Subject: [PATCH 15/36] updated config to be compatible with multiple localforward and remoteforward options. --- paramiko/config.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/paramiko/config.py b/paramiko/config.py index 31caf29..b0be1a8 100644 --- a/paramiko/config.py +++ b/paramiko/config.py @@ -126,14 +126,15 @@ class SSHConfig (object): self._config.append(host) value = value.split() host = {key: value, 'config': {}} - #identityfile is a special case, since it is allowed to be + #identityfile, localforward, remoteforward keys are special cases, since they are allowed to be # specified multiple times and they should be tried in order # of specification. - elif key == 'identityfile': + + elif key in ['identityfile', 'localforward', 'remoteforward']: if key in host['config']: - host['config']['identityfile'].append(value) + host['config'][key].append(value) else: - host['config']['identityfile'] = [value] + host['config'][key] = [value] elif key not in host['config']: host['config'].update({key: value}) self._config.append(host) From 4ee577abc529603414836d9929f75fa8d67bbffb Mon Sep 17 00:00:00 2001 From: Jeff Forcier Date: Wed, 26 Jun 2013 09:02:27 -0700 Subject: [PATCH 16/36] Move reqs.txt to dev-reqs.txt, solidify tox req --- dev-requirements.txt | 1 + requirements.txt | 2 -- tox.ini | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) create mode 100644 dev-requirements.txt delete mode 100644 requirements.txt diff --git a/dev-requirements.txt b/dev-requirements.txt new file mode 100644 index 0000000..84c7697 --- /dev/null +++ b/dev-requirements.txt @@ -0,0 +1 @@ +tox>=1.4,<1.5 diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 75112a2..0000000 --- a/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -pycrypto -tox diff --git a/tox.ini b/tox.ini index 6cb8001..e2a8dcf 100644 --- a/tox.ini +++ b/tox.ini @@ -2,5 +2,5 @@ envlist = py25,py26,py27 [testenv] -commands = pip install --use-mirrors -q -r requirements.txt +commands = pip install --use-mirrors -q -r dev-requirements.txt python test.py From 993ecb31d2a0606cb1e95e85dd29ea2809866663 Mon Sep 17 00:00:00 2001 From: Jeff Forcier Date: Wed, 26 Jun 2013 09:08:42 -0700 Subject: [PATCH 17/36] Port Makefile contents into fabfile --- fabfile.py | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/fabfile.py b/fabfile.py index 29394f9..5218338 100644 --- a/fabfile.py +++ b/fabfile.py @@ -1,5 +1,6 @@ -from fabric.api import task, sudo, env +from fabric.api import task, sudo, env, local from fabric.contrib.project import rsync_project +from fabric.contrib.console import confirm @task @@ -11,3 +12,26 @@ def upload_docs(): sudo("rm -rf %s/*" % target) rsync_project(local_dir='docs/', remote_dir=staging, delete=True) sudo("cp -R %s/* %s/" % (staging, target)) + +@task +def build_docs(): + local("epydoc --no-private -o docs/ paramiko") + +@task +def clean(): + local("rm -rf build dist docs") + local("rm -f MANIFEST *.log demos/*.log") + local("rm -f paramiko/*.pyc") + local("rm -f test.log") + local("rm -rf paramiko.egg-info") + +@task +def test(): + local("python ./test.py") + +@task +def release(): + confirm("Only hit Enter if you remembered to update the version!") + build_docs() + local("python setup.py sdist register upload") + upload_docs() From ba3ce80c14edac24c21c25aec2c0680df5927f00 Mon Sep 17 00:00:00 2001 From: Jeff Forcier Date: Fri, 28 Jun 2013 13:07:18 -0700 Subject: [PATCH 18/36] Add ML link to docs 'index' Fixes #48 --- dev-requirements.txt | 1 + paramiko/__init__.py | 2 ++ 2 files changed, 3 insertions(+) diff --git a/dev-requirements.txt b/dev-requirements.txt index 84c7697..f706c46 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -1 +1,2 @@ tox>=1.4,<1.5 +epydoc>=3.0,<3.1 diff --git a/paramiko/__init__.py b/paramiko/__init__.py index 099314e..b305d9c 100644 --- a/paramiko/__init__.py +++ b/paramiko/__init__.py @@ -46,6 +46,8 @@ Paramiko is written entirely in python (no C or platform-dependent code) and is released under the GNU Lesser General Public License (LGPL). Website: U{https://github.com/paramiko/paramiko/} + +Mailing list: U{paramiko@librelist.com} """ import sys From caf94786ca8c0bc9e3995da0a160c84921a3bfc6 Mon Sep 17 00:00:00 2001 From: Jeff Forcier Date: Sun, 7 Jul 2013 15:40:38 -0700 Subject: [PATCH 19/36] Update doc upload task w/ static hostname --- fabfile.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fabfile.py b/fabfile.py index 5218338..56a2dd1 100644 --- a/fabfile.py +++ b/fabfile.py @@ -1,9 +1,10 @@ -from fabric.api import task, sudo, env, local +from fabric.api import task, sudo, env, local, hosts from fabric.contrib.project import rsync_project from fabric.contrib.console import confirm @task +@hosts("paramiko.org") def upload_docs(): target = "/var/www/paramiko.org" staging = "/tmp/paramiko_docs" From c8b75a489c569ea71b2166c6fbcc7f773397da3b Mon Sep 17 00:00:00 2001 From: Jeff Forcier Date: Fri, 26 Jul 2013 15:04:16 -0700 Subject: [PATCH 20/36] Update changelog for release --- NEWS | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/NEWS b/NEWS index efee92d..0ad9f6b 100644 --- a/NEWS +++ b/NEWS @@ -12,11 +12,11 @@ Issues noted as "Fabric #NN" can be found at https://github.com/fabric/fabric/. Releases ======== -v1.10.2 (DD MM 2013) --------------------- +v1.10.2 (26th Jul 2013) +----------------------- -* #153, #67: Warn on parse failure when reading known_hosts - file. Thanks to `@glasserc` for patch. +* #153, #67: Warn on parse failure when reading known_hosts file. Thanks to + `@glasserc` for patch. * #146: Indentation fixes for readability. Thanks to Abhinav Upadhyay for catch & patch. From 965d00dee951ffaee7458c7f8cb0a3c38ff46b25 Mon Sep 17 00:00:00 2001 From: Jeff Forcier Date: Fri, 26 Jul 2013 15:05:35 -0700 Subject: [PATCH 21/36] Version bump --- paramiko/__init__.py | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/paramiko/__init__.py b/paramiko/__init__.py index 099314e..6094c40 100644 --- a/paramiko/__init__.py +++ b/paramiko/__init__.py @@ -55,7 +55,7 @@ if sys.version_info < (2, 5): __author__ = "Jeff Forcier " -__version__ = "1.10.1" +__version__ = "1.10.2" __license__ = "GNU Lesser General Public License (LGPL)" diff --git a/setup.py b/setup.py index d6caccf..928941d 100644 --- a/setup.py +++ b/setup.py @@ -52,7 +52,7 @@ if sys.platform == 'darwin': setup(name = "paramiko", - version = "1.10.1", + version = "1.10.2", description = "SSH2 protocol library", author = "Jeff Forcier", author_email = "jeff@bitprophet.org", From 2a08a48dd2451e3139735c8b4f29d6d2516b8eb0 Mon Sep 17 00:00:00 2001 From: Jeff Forcier Date: Fri, 26 Jul 2013 15:07:33 -0700 Subject: [PATCH 22/36] Version bump/dumb-fix --- paramiko/__init__.py | 2 +- setup.py | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/paramiko/__init__.py b/paramiko/__init__.py index d720e37..62cd51c 100644 --- a/paramiko/__init__.py +++ b/paramiko/__init__.py @@ -57,7 +57,7 @@ if sys.version_info < (2, 5): __author__ = "Jeff Forcier " -__version__ = "1.10.2" +__version__ = "1.11.0" __license__ = "GNU Lesser General Public License (LGPL)" diff --git a/setup.py b/setup.py index e94b902..02a71e5 100644 --- a/setup.py +++ b/setup.py @@ -52,11 +52,7 @@ if sys.platform == 'darwin': setup(name = "paramiko", -<<<<<<< HEAD version = "1.11.0", -======= - version = "1.10.2", ->>>>>>> 1.10 description = "SSH2 protocol library", author = "Jeff Forcier", author_email = "jeff@bitprophet.org", From e6abab18eeb0b9f6425cd77c564ff59d19d39c98 Mon Sep 17 00:00:00 2001 From: Jeff Forcier Date: Thu, 1 Aug 2013 11:50:46 -0700 Subject: [PATCH 23/36] Tag nag --- fabfile.py | 1 + 1 file changed, 1 insertion(+) diff --git a/fabfile.py b/fabfile.py index 56a2dd1..7883dab 100644 --- a/fabfile.py +++ b/fabfile.py @@ -33,6 +33,7 @@ def test(): @task def release(): confirm("Only hit Enter if you remembered to update the version!") + confirm("Also, did you remember to tag your release?") build_docs() local("python setup.py sdist register upload") upload_docs() From 565eff8274063aa118b9cbe0231766a420de79f3 Mon Sep 17 00:00:00 2001 From: Jeff Forcier Date: Fri, 20 Sep 2013 13:18:26 -0700 Subject: [PATCH 24/36] Apply slightly modified version of patch from #162 --- paramiko/packet.py | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/paramiko/packet.py b/paramiko/packet.py index 38a6d4b..be502e9 100644 --- a/paramiko/packet.py +++ b/paramiko/packet.py @@ -33,17 +33,13 @@ from paramiko.ssh_exception import SSHException, ProxyCommandFailure from paramiko.message import Message -got_r_hmac = False try: - import r_hmac - got_r_hmac = True + from r_hmac import HMAC except ImportError: - pass + from Crypto.Hash.HMAC import HMAC + def compute_hmac(key, message, digest_class): - if got_r_hmac: - return r_hmac.HMAC(key, message, digest_class).digest() - from Crypto.Hash import HMAC - return HMAC.HMAC(key, message, digest_class).digest() + return HMAC(key, message, digest_class).digest() class NeedRekeyException (Exception): From f7d74d03d9f1f6ec10b0f7df3061384afdb61b48 Mon Sep 17 00:00:00 2001 From: Jeff Forcier Date: Fri, 20 Sep 2013 13:44:28 -0700 Subject: [PATCH 25/36] Changelog entry re #162 --- NEWS | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/NEWS b/NEWS index 0ad9f6b..d052ebb 100644 --- a/NEWS +++ b/NEWS @@ -12,6 +12,13 @@ Issues noted as "Fabric #NN" can be found at https://github.com/fabric/fabric/. Releases ======== +v1.10.3 (20th Sep 2013) +----------------------- + +* #162: Clean up HMAC module import to avoid deadlocks in certain uses of + SSHClient. Thanks to Gernot Hillier for the catch & suggested + fix. + v1.10.2 (26th Jul 2013) ----------------------- From 081b04116be29072695a54e52e74ca9879bf03f9 Mon Sep 17 00:00:00 2001 From: Jeff Forcier Date: Fri, 20 Sep 2013 13:58:29 -0700 Subject: [PATCH 26/36] Clone changelog entry for 1.11 --- NEWS | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/NEWS b/NEWS index 7f57663..1c59a93 100644 --- a/NEWS +++ b/NEWS @@ -12,6 +12,13 @@ Issues noted as "Fabric #NN" can be found at https://github.com/fabric/fabric/. Releases ======== +v1.11.1 (20th Sep 2013) +----------------------- + +* #162: Clean up HMAC module import to avoid deadlocks in certain uses of + SSHClient. Thanks to Gernot Hillier for the catch & suggested + fix. + v1.10.3 (20th Sep 2013) ----------------------- From 7ed1e2bccc545d6819f081a12abc854540823e42 Mon Sep 17 00:00:00 2001 From: Jonathan Halcrow Date: Mon, 29 Aug 2011 22:26:14 -0300 Subject: [PATCH 27/36] This fixes a Bad file descriptor error caused by attempting to access the request after it has already been closed. --- demos/forward.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/demos/forward.py b/demos/forward.py index 4e10785..2a4c424 100644 --- a/demos/forward.py +++ b/demos/forward.py @@ -78,9 +78,11 @@ class Handler (SocketServer.BaseRequestHandler): if len(data) == 0: break self.request.send(data) + + peername = self.request.getpeername() chan.close() self.request.close() - verbose('Tunnel closed from %r' % (self.request.getpeername(),)) + verbose('Tunnel closed from %r' % (peername,)) def forward_tunnel(local_port, remote_host, remote_port, transport): From fa61f3c398068895e6a483e3ce1ccc684b18ff49 Mon Sep 17 00:00:00 2001 From: Jeff Forcier Date: Fri, 20 Sep 2013 14:13:08 -0700 Subject: [PATCH 28/36] Changelog re #36 --- NEWS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/NEWS b/NEWS index d052ebb..07ab799 100644 --- a/NEWS +++ b/NEWS @@ -18,6 +18,8 @@ v1.10.3 (20th Sep 2013) * #162: Clean up HMAC module import to avoid deadlocks in certain uses of SSHClient. Thanks to Gernot Hillier for the catch & suggested fix. +* #36: Fix the port-forwarding demo to avoid file descriptor errors. Thanks to + Jonathan Halcrow for catch & patch. v1.10.2 (26th Jul 2013) ----------------------- From db9dfebca801efbfd3743d85d4f7916f3996f4f5 Mon Sep 17 00:00:00 2001 From: Jeff Forcier Date: Fri, 20 Sep 2013 14:46:32 -0700 Subject: [PATCH 29/36] Changelog re #168 --- NEWS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/NEWS b/NEWS index 07ab799..fadd878 100644 --- a/NEWS +++ b/NEWS @@ -20,6 +20,8 @@ v1.10.3 (20th Sep 2013) fix. * #36: Fix the port-forwarding demo to avoid file descriptor errors. Thanks to Jonathan Halcrow for catch & patch. +* #168: Update config handling to properly handle multiple 'localforward' and + 'remoteforward' keys. Thanks to Emre Yılmaz for the patch. v1.10.2 (26th Jul 2013) ----------------------- From b3c0fb463ab2ab7642ce5ddef09f1469887d845c Mon Sep 17 00:00:00 2001 From: Jeff Forcier Date: Fri, 20 Sep 2013 14:47:29 -0700 Subject: [PATCH 30/36] Copy some 1.10.3 changes to 1.11.1 changelog --- NEWS | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/NEWS b/NEWS index 43d3af5..55981dd 100644 --- a/NEWS +++ b/NEWS @@ -18,6 +18,10 @@ v1.11.1 (20th Sep 2013) * #162: Clean up HMAC module import to avoid deadlocks in certain uses of SSHClient. Thanks to Gernot Hillier for the catch & suggested fix. +* #168: Update config handling to properly handle multiple 'localforward' and + 'remoteforward' keys. Thanks to Emre Yılmaz for the patch. +* #36: Fix the port-forwarding demo to avoid file descriptor errors. Thanks to + Jonathan Halcrow for catch & patch. v1.10.3 (20th Sep 2013) ----------------------- From 0ba34035c37d10b0f0b9035d427103da43c1150a Mon Sep 17 00:00:00 2001 From: Jeff Forcier Date: Fri, 20 Sep 2013 17:56:20 -0700 Subject: [PATCH 31/36] Not sure how this got updated :( --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 02a71e5..d7adee9 100644 --- a/setup.py +++ b/setup.py @@ -52,7 +52,7 @@ if sys.platform == 'darwin': setup(name = "paramiko", - version = "1.11.0", + version = "1.10.3", description = "SSH2 protocol library", author = "Jeff Forcier", author_email = "jeff@bitprophet.org", From 2de0784d4e35a1eac5c5d6942dd61b37e6521e19 Mon Sep 17 00:00:00 2001 From: Jeff Forcier Date: Fri, 20 Sep 2013 17:57:23 -0700 Subject: [PATCH 32/36] Versions: hard? --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index d7adee9..64484b1 100644 --- a/setup.py +++ b/setup.py @@ -52,7 +52,7 @@ if sys.platform == 'darwin': setup(name = "paramiko", - version = "1.10.3", + version = "1.11.1", description = "SSH2 protocol library", author = "Jeff Forcier", author_email = "jeff@bitprophet.org", From bea7d9dc8a913b41182755528acfcdcec71e62d2 Mon Sep 17 00:00:00 2001 From: Jeff Forcier Date: Fri, 20 Sep 2013 18:01:42 -0700 Subject: [PATCH 33/36] Christ almighty I hate non-DRY versioning --- paramiko/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/paramiko/__init__.py b/paramiko/__init__.py index 62cd51c..4ba42a2 100644 --- a/paramiko/__init__.py +++ b/paramiko/__init__.py @@ -57,7 +57,7 @@ if sys.version_info < (2, 5): __author__ = "Jeff Forcier " -__version__ = "1.11.0" +__version__ = "1.11.1" __license__ = "GNU Lesser General Public License (LGPL)" From f783d4d818dba93177ac96b95251e18fcfe190cc Mon Sep 17 00:00:00 2001 From: Jeff Forcier Date: Fri, 20 Sep 2013 18:09:59 -0700 Subject: [PATCH 34/36] LOL @ different ordering in different versions. WTB sphinx plz --- NEWS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index 55981dd..8affcd5 100644 --- a/NEWS +++ b/NEWS @@ -18,10 +18,10 @@ v1.11.1 (20th Sep 2013) * #162: Clean up HMAC module import to avoid deadlocks in certain uses of SSHClient. Thanks to Gernot Hillier for the catch & suggested fix. -* #168: Update config handling to properly handle multiple 'localforward' and - 'remoteforward' keys. Thanks to Emre Yılmaz for the patch. * #36: Fix the port-forwarding demo to avoid file descriptor errors. Thanks to Jonathan Halcrow for catch & patch. +* #168: Update config handling to properly handle multiple 'localforward' and + 'remoteforward' keys. Thanks to Emre Yılmaz for the patch. v1.10.3 (20th Sep 2013) ----------------------- From 05abcc40f5eafbd98182a468112bcdf3c8eb56d6 Mon Sep 17 00:00:00 2001 From: Jeff Forcier Date: Fri, 27 Sep 2013 16:08:59 -0700 Subject: [PATCH 35/36] Fix #179 - missing host variable in fqdn evaluation --- paramiko/config.py | 39 ++++++++++++++++++++++++--------------- tests/test_util.py | 11 +++++++++++ 2 files changed, 35 insertions(+), 15 deletions(-) diff --git a/paramiko/config.py b/paramiko/config.py index b0be1a8..520da35 100644 --- a/paramiko/config.py +++ b/paramiko/config.py @@ -35,9 +35,10 @@ class LazyFqdn(object): Returns the host's fqdn on request as string. """ - def __init__(self, config): + def __init__(self, config, host=None): self.fqdn = None self.config = config + self.host = host def __str__(self): if self.fqdn is None: @@ -54,19 +55,27 @@ class LazyFqdn(object): fqdn = None address_family = self.config.get('addressfamily', 'any').lower() if address_family != 'any': - family = socket.AF_INET if address_family == 'inet' \ - else socket.AF_INET6 - results = socket.getaddrinfo(host, - None, - family, - socket.SOCK_DGRAM, - socket.IPPROTO_IP, - socket.AI_CANONNAME) - for res in results: - af, socktype, proto, canonname, sa = res - if canonname and '.' in canonname: - fqdn = canonname - break + try: + family = socket.AF_INET if address_family == 'inet' \ + else socket.AF_INET6 + results = socket.getaddrinfo( + self.host, + None, + family, + socket.SOCK_DGRAM, + socket.IPPROTO_IP, + socket.AI_CANONNAME + ) + for res in results: + af, socktype, proto, canonname, sa = res + if canonname and '.' in canonname: + fqdn = canonname + break + # giaerror -> socket.getaddrinfo() can't resolve self.host + # (which is from socket.gethostname()). Fall back to the + # getfqdn() call below. + except socket.gaierror: + pass # Handle 'any' / unspecified if fqdn is None: fqdn = socket.getfqdn() @@ -216,7 +225,7 @@ class SSHConfig (object): remoteuser = user host = socket.gethostname().split('.')[0] - fqdn = LazyFqdn(config) + fqdn = LazyFqdn(config, host) homedir = os.path.expanduser('~') replacements = {'controlpath': [ diff --git a/tests/test_util.py b/tests/test_util.py index efda9b2..a528224 100644 --- a/tests/test_util.py +++ b/tests/test_util.py @@ -329,3 +329,14 @@ IdentityFile id_dsa22 paramiko.util.lookup_ssh_host_config(host, config), values ) + + def test_12_config_addressfamily_and_lazy_fqdn(self): + """ + Ensure the code path honoring non-'all' AddressFamily doesn't asplode + """ + test_config = """ +AddressFamily inet +IdentityFile something_%l_using_fqdn +""" + config = paramiko.util.parse_ssh_config(cStringIO.StringIO(test_config)) + assert config.lookup('meh') # will die during lookup() if bug regresses From 8b983d9d3d9c91f321c3f18ecc8fa2e9343ce661 Mon Sep 17 00:00:00 2001 From: Jeff Forcier Date: Fri, 27 Sep 2013 16:10:56 -0700 Subject: [PATCH 36/36] Changelog re #179 --- NEWS | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/NEWS b/NEWS index fadd878..28a95ce 100644 --- a/NEWS +++ b/NEWS @@ -12,6 +12,13 @@ Issues noted as "Fabric #NN" can be found at https://github.com/fabric/fabric/. Releases ======== +v1.10.4 (27th Sep 2013) +----------------------- + +* #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. + v1.10.3 (20th Sep 2013) -----------------------