bug 300536: allow a really long banner before the SSH handshake.

This commit is contained in:
Robey Pointer 2009-02-17 18:30:48 -08:00
parent 5def112013
commit 74b581c170
3 changed files with 35 additions and 4 deletions

View File

@ -268,11 +268,11 @@ class Packetizer (object):
Read a line from the socket. We assume no data is pending after the Read a line from the socket. We assume no data is pending after the
line, so it's okay to attempt large reads. line, so it's okay to attempt large reads.
""" """
buf = '' buf = self.__remainder
while not '\n' in buf: while not '\n' in buf:
buf += self._read_timeout(timeout) buf += self._read_timeout(timeout)
n = buf.index('\n') n = buf.index('\n')
self.__remainder += buf[n+1:] self.__remainder = buf[n+1:]
buf = buf[:n] buf = buf[:n]
if (len(buf) > 0) and (buf[-1] == '\r'): if (len(buf) > 0) and (buf[-1] == '\r'):
buf = buf[:-1] buf = buf[:-1]

View File

@ -1471,7 +1471,7 @@ class Transport (threading.Thread):
# (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)
@ -1588,7 +1588,7 @@ class Transport (threading.Thread):
def _check_banner(self): def _check_banner(self):
# this is slow, but we only have to do it once # this is slow, but we only have to do it once
for i in range(5): for i in range(100):
# give them 15 seconds for the first line, then just 2 seconds # give them 15 seconds for the first line, then just 2 seconds
# each additional line. (some sites have very high latency.) # each additional line. (some sites have very high latency.)
if i == 0: if i == 0:

View File

@ -38,6 +38,19 @@ from paramiko.message import Message
from loop import LoopSocket from loop import LoopSocket
LONG_BANNER = """\
Welcome to the super-fun-land BBS, where our MOTD is the primary thing we
provide. All rights reserved. Offer void in Tennessee. Stunt drivers were
used. Do not attempt at home. Some restrictions apply.
Happy birthday to Commie the cat!
Note: An SSH banner may eventually appear.
Maybe.
"""
class NullServer (ServerInterface): class NullServer (ServerInterface):
paranoid_did_password = False paranoid_did_password = False
paranoid_did_public_key = False paranoid_did_public_key = False
@ -182,6 +195,24 @@ class TransportTest (unittest.TestCase):
self.assertEquals(True, self.tc.is_authenticated()) self.assertEquals(True, self.tc.is_authenticated())
self.assertEquals(True, self.ts.is_authenticated()) self.assertEquals(True, self.ts.is_authenticated())
def test_3a_long_banner(self):
"""
verify that a long banner doesn't mess up the handshake.
"""
host_key = RSAKey.from_private_key_file('tests/test_rsa.key')
public_host_key = RSAKey(data=str(host_key))
self.ts.add_server_key(host_key)
event = threading.Event()
server = NullServer()
self.assert_(not event.isSet())
self.socks.send(LONG_BANNER)
self.ts.start_server(event, server)
self.tc.connect(hostkey=public_host_key,
username='slowdive', password='pygmalion')
event.wait(1.0)
self.assert_(event.isSet())
self.assert_(self.ts.is_active())
def test_4_special(self): def test_4_special(self):
""" """
verify that the client can demand odd handshake settings, and can verify that the client can demand odd handshake settings, and can