merge sshserver.py with ssh.py

This commit is contained in:
Michel Oosterhof
2015-07-31 16:57:14 +04:00
parent fd801d1f4f
commit eeb6c70dac
2 changed files with 62 additions and 101 deletions

View File

@@ -21,12 +21,10 @@ from twisted.conch.ssh.common import NS, getNS
import ConfigParser
import fs
import sshserver
import auth
import connection
import honeypot
import protocol
import sshserver
import exceptions
class HoneyPotSSHUserAuthServer(userauth.SSHUserAuthServer):
@@ -211,11 +209,15 @@ class HoneyPotRealm:
else:
raise Exception("No supported interfaces found.")
class HoneyPotTransport(sshserver.CowrieSSHServerTransport):
class HoneyPotTransport(transport.SSHServerTransport):
"""
"""
def connectionMade(self):
"""
Called when the connection is made from the other side.
We send our version, but wait with sending KEXINIT
"""
self.transportId = uuid.uuid4().hex[:8]
self.interactors = []
@@ -225,16 +227,49 @@ class HoneyPotTransport(sshserver.CowrieSSHServerTransport):
dst_ip=self.transport.getHost().host, dst_port=self.transport.getHost().port,
sessionno=self.transport.sessionno)
sshserver.CowrieSSHServerTransport.connectionMade(self)
self.transport.write('%s\r\n' % (self.ourVersionString,))
self.currentEncryptions = transport.SSHCiphers('none', 'none', 'none', 'none')
self.currentEncryptions.setKeys('', '', '', '', '', '')
def sendKexInit(self):
# Don't send key exchange prematurely
if not self.gotVersion:
return
sshserver.CowrieSSHServerTransport.sendKexInit(self)
transport.SSHServerTransport.sendKexInit(self)
def dataReceived(self, data):
sshserver.CowrieSSHServerTransport.dataReceived(self, data)
"""
First, check for the version string (SSH-2.0-*). After that has been
received, this method adds data to the buffer, and pulls out any
packets.
@type data: C{str}
"""
self.buf = self.buf + data
if not self.gotVersion:
if not '\n' in self.buf:
return
self.otherVersionString = self.buf.strip()
if self.buf.startswith('SSH-'):
self.gotVersion = True
remoteVersion = self.buf.split('-')[1]
if remoteVersion not in self.supportedVersions:
self._unsupportedVersionReceived(remoteVersion)
return
i = self.buf.index('\n')
self.buf = self.buf[i+1:]
self.sendKexInit()
else:
self.transport.write('Protocol mismatch.\n')
log.msg('Bad protocol version identification: %s' % (self.otherVersionString))
self.transport.loseConnection()
return
packet = self.getPacket()
while packet:
messageNum = ord(packet[0])
self.dispatchMessage(messageNum, packet[1:])
packet = self.getPacket()
# later versions seem to call sendKexInit again on their own
if twisted.version.major < 11 and \
not self._hadVersion and self.gotVersion:
@@ -256,7 +291,7 @@ class HoneyPotTransport(sshserver.CowrieSSHServerTransport):
kexAlgs=kexAlgs, keyAlgs=keyAlgs, encCS=encCS, macCS=macCS,
compCS=compCS, format='Remote SSH version: %(version)s')
return sshserver.CowrieSSHServerTransport.ssh_KEXINIT(self, packet)
return transport.SSHServerTransport.ssh_KEXINIT(self, packet)
# this seems to be the only reliable place of catching lost connection
def connectionLost(self, reason):
@@ -264,9 +299,28 @@ class HoneyPotTransport(sshserver.CowrieSSHServerTransport):
i.sessionClosed()
if self.transport.sessionno in self.factory.sessions:
del self.factory.sessions[self.transport.sessionno]
sshserver.CowrieSSHServerTransport.connectionLost(self, reason)
transport.SSHServerTransport.connectionLost(self, reason)
log.msg(eventid='KIPP0011', format='Connection lost')
def sendDisconnect(self, reason, desc):
"""
http://kbyte.snowpenguin.org/portal/2013/04/30/kippo-protocol-mismatch-workaround/
Workaround for the "bad packet length" error message.
@param reason: the reason for the disconnect. Should be one of the
DISCONNECT_* values.
@type reason: C{int}
@param desc: a descrption of the reason for the disconnection.
@type desc: C{str}
"""
if not 'bad packet length' in desc:
transport.SSHServerTransport.sendDisconnect(self, reason, desc)
else:
self.transport.write('Packet corrupt\n')
log.msg('[SERVER] - Disconnecting with error, code %s\nreason: %s' % (reason, desc))
self.transport.loseConnection()
class HoneyPotSSHSession(session.SSHSession):
def __init__(self, *args, **kw):

View File

@@ -1,93 +0,0 @@
# Copyright (c) 2013 Thomas Nicholson <tnnich@googlemail.com>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. The names of the author(s) may not be used to endorse or promote
# products derived from this software without specific prior written
# permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
from twisted.conch.ssh import transport
from twisted.python import log
class CowrieSSHServerTransport(transport.SSHServerTransport):
def connectionMade(self):
"""
Called when the connection is made to the other side. We sent our
version and the MSG_KEXINIT packet.
"""
self.transport.write('%s\r\n' % (self.ourVersionString,))
self.currentEncryptions = transport.SSHCiphers('none', 'none', 'none', 'none')
self.currentEncryptions.setKeys('', '', '', '', '', '')
def dataReceived(self, data):
"""
First, check for the version string (SSH-2.0-*). After that has been
received, this method adds data to the buffer, and pulls out any
packets.
@type data: C{str}
"""
self.buf = self.buf + data
if not self.gotVersion:
if not '\n' in self.buf:
return
self.otherVersionString = self.buf.strip()
if self.buf.startswith('SSH-'):
self.gotVersion = True
remoteVersion = self.buf.split('-')[1]
if remoteVersion not in self.supportedVersions:
self._unsupportedVersionReceived(remoteVersion)
return
i = self.buf.index('\n')
self.buf = self.buf[i+1:]
self.sendKexInit()
else:
self.transport.write('Protocol mismatch.\n')
log.msg('Bad protocol version identification: %s' % (self.otherVersionString))
self.transport.loseConnection()
return
packet = self.getPacket()
while packet:
messageNum = ord(packet[0])
self.dispatchMessage(messageNum, packet[1:])
packet = self.getPacket()
def sendDisconnect(self, reason, desc):
"""
http://kbyte.snowpenguin.org/portal/2013/04/30/kippo-protocol-mismatch-workaround/
Workaround for the "bad packet length" error message.
@param reason: the reason for the disconnect. Should be one of the
DISCONNECT_* values.
@type reason: C{int}
@param desc: a descrption of the reason for the disconnection.
@type desc: C{str}
"""
if not 'bad packet length' in desc:
# With python >= 3 we can use super?
transport.SSHServerTransport.sendDisconnect(self, reason, desc)
else:
self.transport.write('Protocol mismatch.\n')
log.msg('[SERVER] - Disconnecting with error, code %s\nreason: %s' % (reason, desc))
self.transport.loseConnection()