diff --git a/.travis.yml b/.travis.yml index 5de0a5b..291acf9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,5 +11,9 @@ script: python test.py --verbose notifications: irc: channels: "irc.freenode.org#paramiko" + template: + - "%{repository}@%{branch}: %{message} (%{build_url})" on_success: change on_failure: change + use_notice: true + email: false diff --git a/NEWS b/NEWS index 4a3a672..c2d450b 100644 --- a/NEWS +++ b/NEWS @@ -12,6 +12,29 @@ Issues noted as "Fabric #NN" can be found at https://github.com/fabric/fabric/. Releases ======== +v1.12.1 (8th Jan 2014) +---------------------- + +* #176: Fix AttributeError bugs in known_hosts file (re)loading. Thanks to + Nathan Scowcroft for the patch & Martin Blumenstingl for the initial test + case. +* #225: Note ecdsa requirement in README. Thanks to Amaury Rodriguez for the + catch. + +v1.11.3 (8th Jan 2014) +---------------------- + +* #176: Fix AttributeError bugs in known_hosts file (re)loading. Thanks to + Nathan Scowcroft for the patch & Martin Blumenstingl for the initial test + case. + +v1.10.5 (8th Jan 2014) +---------------------- + +* #176: Fix AttributeError bugs in known_hosts file (re)loading. Thanks to + Nathan Scowcroft for the patch & Martin Blumenstingl for the initial test + case. + v1.12.0 (27th Sep 2013) ----------------------- diff --git a/README b/README index ae50a80..666b31a 100644 --- a/README +++ b/README @@ -5,7 +5,7 @@ paramiko :Paramiko: Python SSH module :Copyright: Copyright (c) 2003-2009 Robey Pointer -:Copyright: Copyright (c) 2013 Jeff Forcier +:Copyright: Copyright (c) 2014 Jeff Forcier :License: LGPL :Homepage: https://github.com/paramiko/paramiko/ :API docs: http://docs.paramiko.org @@ -36,6 +36,7 @@ Requirements - python 2.6 or better - pycrypto 2.1 or better + - ecdsa 0.9 or better If you have setuptools, you can build and install paramiko and all its dependencies with this command (as root):: diff --git a/paramiko/client.py b/paramiko/client.py index 7cf897f..40ef7f0 100644 --- a/paramiko/client.py +++ b/paramiko/client.py @@ -189,8 +189,8 @@ class SSHClient (object): # 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) + if self._host_keys_filename is not None: + self.load_host_keys(self._host_keys_filename) with open(filename, 'w') as f: for hostname, keys in self._host_keys.items(): diff --git a/tests/test_client.py b/tests/test_client.py index c508b83..b472484 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -20,12 +20,13 @@ Some unit tests for SSHClient. """ -import os import socket import threading import time import unittest import weakref +import warnings +import os from binascii import hexlify from tests.util import test_path import paramiko @@ -186,7 +187,33 @@ class SSHClientTest (unittest.TestCase): self.assertEqual(1, len(self.tc.get_host_keys())) self.assertEqual(public_host_key, self.tc.get_host_keys()['[%s]:%d' % (self.addr, self.port)]['ssh-rsa']) - def test_5_cleanup(self): + def test_5_save_host_keys(self): + """ + verify that SSHClient correctly saves a known_hosts file. + """ + warnings.filterwarnings('ignore', 'tempnam.*') + + host_key = paramiko.RSAKey.from_private_key_file('tests/test_rsa.key') + public_host_key = paramiko.RSAKey(data=str(host_key)) + localname = os.tempnam() + + client = paramiko.SSHClient() + self.assertEquals(0, len(client.get_host_keys())) + + host_id = '[%s]:%d' % (self.addr, self.port) + + client.get_host_keys().add(host_id, 'ssh-rsa', public_host_key) + self.assertEquals(1, len(client.get_host_keys())) + self.assertEquals(public_host_key, client.get_host_keys()[host_id]['ssh-rsa']) + + client.save_host_keys(localname) + + with open(localname) as fd: + assert host_id in fd.read() + + os.unlink(localname) + + def test_6_cleanup(self): """ verify that when an SSHClient is collected, its transport (and the transport's packetizer) is closed.