summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJeff Forcier <jeff@bitprophet.org>2014-12-17 14:29:18 -0800
committerJeff Forcier <jeff@bitprophet.org>2014-12-17 14:29:18 -0800
commit92d91a0222394650d6f5943bad7059834a611826 (patch)
treee0875935ade262e16d0a68e26d0443ad9dfddc47
parentc5836ad5524e52df87801ddd4f3a5187afae785f (diff)
parent40f9b9c7bc110523f7a6c18208e2c20220c1aeb4 (diff)
Merge branch 'master' into 419-int
-rw-r--r--paramiko/agent.py3
-rw-r--r--paramiko/transport.py6
-rw-r--r--paramiko/util.py9
-rw-r--r--sites/www/changelog.rst11
-rw-r--r--tests/test_util.py15
5 files changed, 35 insertions, 9 deletions
diff --git a/paramiko/agent.py b/paramiko/agent.py
index 4f463449..a75ac59e 100644
--- a/paramiko/agent.py
+++ b/paramiko/agent.py
@@ -73,7 +73,8 @@ class AgentSSH(object):
self._keys = tuple(keys)
def _close(self):
- #self._conn.close()
+ if self._conn is not None:
+ self._conn.close()
self._conn = None
self._keys = ()
diff --git a/paramiko/transport.py b/paramiko/transport.py
index 3b26f0b8..cf2c49f5 100644
--- a/paramiko/transport.py
+++ b/paramiko/transport.py
@@ -277,7 +277,7 @@ class Transport (threading.Thread, ClosingContextManager):
self._channels = ChannelMap()
self.channel_events = {} # (id -> Event)
self.channels_seen = {} # (id -> True)
- self._channel_counter = 1
+ self._channel_counter = 0
self.default_max_packet_size = default_max_packet_size
self.default_window_size = default_window_size
self._forward_agent_handler = None
@@ -1074,6 +1074,8 @@ class Transport (threading.Thread, ClosingContextManager):
supplied, this method returns ``None``.
:returns: server supplied banner (`str`), or ``None``.
+
+ .. versionadded:: 1.13
"""
if not self.active or (self.auth_handler is None):
return None
@@ -2149,7 +2151,7 @@ class Transport (threading.Thread, ClosingContextManager):
always_display = m.get_boolean()
msg = m.get_string()
lang = m.get_string()
- self._log(DEBUG, 'Debug msg: ' + util.safe_string(msg))
+ self._log(DEBUG, 'Debug msg: {0}'.format(util.safe_string(msg)))
def _get_subsystem_handler(self, name):
try:
diff --git a/paramiko/util.py b/paramiko/util.py
index 2b3389a8..9befc63b 100644
--- a/paramiko/util.py
+++ b/paramiko/util.py
@@ -115,12 +115,13 @@ def unhexify(s):
def safe_string(s):
- out = ''
+ out = b('')
for c in s:
- if (byte_ord(c) >= 32) and (byte_ord(c) <= 127):
- out += c
+ i = byte_ord(c)
+ if 32 <= i <= 127:
+ out += byte_chr(i)
else:
- out += '%%%02X' % byte_ord(c)
+ out += b('%%%02X' % i)
return out
diff --git a/sites/www/changelog.rst b/sites/www/changelog.rst
index 156abb3f..79cf318b 100644
--- a/sites/www/changelog.rst
+++ b/sites/www/changelog.rst
@@ -2,6 +2,17 @@
Changelog
=========
+* :bug:`266` Change numbering of `~paramiko.transport.Transport` channels to
+ start at 0 instead of 1 for better compatibility with OpenSSH & certain
+ server implementations which break on 1-indexed channels. Thanks to
+ ``@egroeper`` for catch & patch.
+* :bug:`459` Tighten up agent connection closure behavior to avoid spurious
+ ``ResourceWarning`` display in some situations. Thanks to ``@tkrapp`` for the
+ catch.
+* :bug:`429` Server-level debug message logging was overlooked during the
+ Python 3 compatibility update; Python 3 clients attempting to log SSH debug
+ packets encountered type errors. This is now fixed. Thanks to ``@mjmaenpaa``
+ for the catch.
* :bug:`320` Update our win_pageant module to be Python 3 compatible. Thanks to
``@sherbang`` and ``@adamkerz`` for the patches.
* :release:`1.15.1 <2014-09-22>`
diff --git a/tests/test_util.py b/tests/test_util.py
index f961fbbc..7f68de21 100644
--- a/tests/test_util.py
+++ b/tests/test_util.py
@@ -27,8 +27,8 @@ from hashlib import sha1
import unittest
import paramiko.util
-from paramiko.util import lookup_ssh_host_config as host_config
-from paramiko.py3compat import StringIO, byte_ord
+from paramiko.util import lookup_ssh_host_config as host_config, safe_string
+from paramiko.py3compat import StringIO, byte_ord, b
test_config_file = """\
Host *
@@ -453,3 +453,14 @@ Host param3 parara
)
for host in incorrect_data:
self.assertRaises(Exception, conf._get_hosts, host)
+
+ def test_safe_string(self):
+ vanilla = b("vanilla")
+ has_bytes = b("has \7\3 bytes")
+ safe_vanilla = safe_string(vanilla)
+ safe_has_bytes = safe_string(has_bytes)
+ expected_bytes = b("has %07%03 bytes")
+ err = "{0!r} != {1!r}"
+ assert safe_vanilla == vanilla, err.format(safe_vanilla, vanilla)
+ assert safe_has_bytes == expected_bytes, \
+ err.format(safe_has_bytes, expected_bytes)