Skip to content

Commit

Permalink
Fixup of rc5 bugs (#307)
Browse files Browse the repository at this point in the history
* Fixup of rc5 bugs

* TextFSM processor bug which made it so only one set of parsed commands made it into the results.
* Twister bug which regressed support for less than average ssh server implementations by not initialising keyexchange

* Made some modifications after observing a different kind of failure with the last revision. Looks like kexinit is for the server side of things.

* Applied fix to twister2 which is also affected

* Fix import bug.

* Update changelog and version control
  • Loading branch information
tcuthbert authored and jathanism committed Nov 30, 2016
1 parent 68f47ee commit 4e6b7c7
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 5 deletions.
2 changes: 2 additions & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ Backwards-incompatible changes
`~trigger.conf` library.
+ Documentation created for experimental features.
+ Docstrings created for endpoint code.
+ Bugfixes for handling esoteric ssh server implementations
+ Bugfixes for the TextFSM parsed results bucket

Enhancements
------------
Expand Down
2 changes: 1 addition & 1 deletion trigger/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
__version__ = (1, 6, 'rc5')
__version__ = (1, 6, 'rc6')

full_version = '.'.join(str(x) for x in __version__[0:3]) + \
''.join(__version__[3:])
Expand Down
8 changes: 5 additions & 3 deletions trigger/cmds.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ def __init__(self, devices=None, commands=None, creds=None,
# Always fallback to {} for these
self.errors = self.errors if self.errors is not None else {}
self.results = self.results if self.results is not None else {}
self.parsed_results = self.parsed_results if self.parsed_results is not None else collections.defaultdict(dict)
self.parsed_results = self.parsed_results if self.parsed_results is not None else {}

#self.deferrals = []
self.supported_platforms = self._validate_platforms()
Expand Down Expand Up @@ -446,7 +446,6 @@ def parse_template(self, results, device, commands=None):

ret.append(results[idx])

self.parsed_results = dict(self.parsed_results)
return ret

def parse(self, results, device, commands=None):
Expand Down Expand Up @@ -528,7 +527,10 @@ def append_parsed_results(self, device, results):
"""
devname = str(device)
log.msg("Appending results for %r: %r" % (devname, results))
self.parsed_results[devname] = results
if self.parsed_results.get(devname):
self.parsed_results[devname].update(results)
else:
self.parsed_results[devname] = results
return True

def store_results(self, device, results):
Expand Down
16 changes: 16 additions & 0 deletions trigger/twister.py
Original file line number Diff line number Diff line change
Expand Up @@ -837,6 +837,15 @@ def verifyHostKey(self, pubKey, fingerprint):
"""Verify host key, but don't actually verify. Awesome."""
return defer.succeed(True)

def connectionMade(self):
"""
Once the connection is up, set the ciphers but don't do anything else!
"""
self.currentEncryptions = transport.SSHCiphers(
'none', 'none', 'none', 'none'
)
self.currentEncryptions.setKeys('', '', '', '', '', '')

# FIXME(jathan): Make sure that this isn't causing a regression to:
# https://github.com/trigger/trigger/pull/198
def dataReceived(self, data):
Expand All @@ -851,13 +860,20 @@ def dataReceived(self, data):
self.my_buf = ''
self.my_buf = self.my_buf + data

preVersion = self.gotVersion

# One extra loop should be enough to get the banner to come through.
if not self.gotVersion and b'SSH-' not in self.my_buf:
return

# This call should populate the SSH version and carry on as usual.
transport.SSHClientTransport.dataReceived(self, data)

# We have now seen the SSH version in the banner.
# signal that the connection has been made successfully.
if self.gotVersion and not preVersion:
transport.SSHClientTransport.connectionMade(self)

def connectionSecure(self):
"""Once we're secure, authenticate."""
# The default SSHUserAuth requires options to be set.
Expand Down
40 changes: 39 additions & 1 deletion trigger/twister2.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

setup()

from twisted.conch.ssh import session, common
from twisted.conch.ssh import session, common, transport
from twisted.conch.ssh.channel import SSHChannel
from twisted.conch.endpoints import (SSHCommandClientEndpoint,
_NewConnectionHelper,
Expand All @@ -29,6 +29,7 @@
_UserAuth,
_ConnectionReady)
from twisted.internet import defer, protocol, reactor, threads
from twisted.internet.defer import CancelledError
from twisted.internet.task import LoopingCall
from twisted.protocols.policies import TimeoutMixin
from twisted.python import log
Expand Down Expand Up @@ -267,6 +268,43 @@ def _cbUserauthFailure(self, result, iterator):
return d

class _TriggerCommandTransport(_CommandTransport):
def connectionMade(self):
"""
Once the connection is up, set the ciphers but don't do anything else!
"""
self.currentEncryptions = transport.SSHCiphers(
'none', 'none', 'none', 'none'
)
self.currentEncryptions.setKeys('', '', '', '', '', '')

# FIXME(jathan): Make sure that this isn't causing a regression to:
# https://github.com/trigger/trigger/pull/198
def dataReceived(self, data):
"""
Explicity override version detection for edge cases where "SSH-"
isn't on the first line of incoming data.
"""
# Store incoming data in a local buffer until we've detected the
# presence of 'SSH-', then handover to default .dataReceived() for
# version banner processing.
if not hasattr(self, 'my_buf'):
self.my_buf = ''
self.my_buf = self.my_buf + data

preVersion = self.gotVersion

# One extra loop should be enough to get the banner to come through.
if not self.gotVersion and b'SSH-' not in self.my_buf:
return

# This call should populate the SSH version and carry on as usual.
_CommandTransport.dataReceived(self, data)

# We have now seen the SSH version in the banner.
# signal that the connection has been made successfully.
if self.gotVersion and not preVersion:
_CommandTransport.connectionMade(self)

def connectionSecure(self):
"""
When the connection is secure, start the authentication process.
Expand Down

0 comments on commit 4e6b7c7

Please sign in to comment.