mirror of https://github.com/cowrie/cowrie.git
173 lines
5.7 KiB
Python
173 lines
5.7 KiB
Python
from twisted.words.xish import domish
|
|
from wokkel.xmppim import AvailablePresence
|
|
from wokkel import muc
|
|
import uuid
|
|
|
|
class XMPPLoggerProtocol(muc.MUCClient):
|
|
|
|
def __init__(self, server, rooms, nick):
|
|
muc.MUCClient.__init__(self)
|
|
self.server = server
|
|
self.jrooms = rooms
|
|
self.nick = nick
|
|
self.last = {}
|
|
self.activity = None
|
|
|
|
def initialized(self):
|
|
"""The bot has connected to the xmpp server, now try to join the room.
|
|
"""
|
|
for i in self.jrooms:
|
|
print(i)
|
|
self.join(self.server, i, self.nick).addCallback(self.initRoom)
|
|
|
|
def initRoom(self, room):
|
|
print 'Joined room %s' % room.name
|
|
|
|
def connectionMade(self):
|
|
print 'Connected!'
|
|
|
|
# send initial presence
|
|
self.send(AvailablePresence())
|
|
|
|
def connectionLost(self, reason):
|
|
print 'Disconnected!'
|
|
|
|
def onMessage(self, msg):
|
|
pass
|
|
|
|
def receivedGroupChat(self, room, user, body):
|
|
pass
|
|
|
|
def receivedHistory(self, room, user, body, dely, frm=None):
|
|
pass
|
|
|
|
from twisted.application import service
|
|
from twisted.words.protocols.jabber import jid
|
|
from wokkel.client import XMPPClient
|
|
from kippo.core import dblog
|
|
from twisted.words.xish import domish
|
|
|
|
class DBLogger(dblog.DBLogger):
|
|
def start(self, cfg):
|
|
from random import choice
|
|
import string
|
|
|
|
server = cfg.get('database_xmpp', 'server')
|
|
user = cfg.get('database_xmpp', 'user')
|
|
password = cfg.get('database_xmpp', 'password')
|
|
muc = cfg.get('database_xmpp', 'muc')
|
|
channels = {}
|
|
for i in ('createsession', 'connectionlost', 'loginfailed',
|
|
'loginsucceeded', 'command', 'clientversion'):
|
|
x = cfg.get('database_xmpp', 'signal_' + i)
|
|
if not x in channels:
|
|
channels[x] = []
|
|
channels[x].append(i)
|
|
|
|
resource = ''.join([choice(string.ascii_letters)
|
|
for i in range(8)])
|
|
jid = user + '/' + resource
|
|
application = service.Application('honeypot')
|
|
self.run(application, jid, password, muc, channels)
|
|
|
|
def run(self, application, jidstr, password, muc, channels, anon=True):
|
|
self.xmppclient = XMPPClient(jid.internJID(jidstr), password)
|
|
if self.cfg.has_option('database_xmpp', 'debug') and \
|
|
self.cfg.get('database_xmpp', 'debug') in ('1', 'true', 'yes'):
|
|
self.xmppclient.logTraffic = True # DEBUG HERE
|
|
(user, host, resource) = jid.parse(jidstr)
|
|
self.muc = XMPPLoggerProtocol(
|
|
muc, channels.keys(), user + '-' + resource)
|
|
self.muc.setHandlerParent(self.xmppclient)
|
|
self.xmppclient.setServiceParent(application)
|
|
self.signals = {}
|
|
for channel in channels:
|
|
for signal in channels[channel]:
|
|
self.signals[signal] = channel
|
|
self.anonymous = True
|
|
self.xmppclient.startService()
|
|
|
|
def broadcast(self, msgtype, msg):
|
|
if msgtype in self.signals:
|
|
self.report(msgtype, '%s@%s' %
|
|
(self.signals[msgtype], self.muc.server) , msg)
|
|
|
|
def report(self, msgtype, to, xmsg):
|
|
body = domish.Element((None, 'body'))
|
|
body.addContent('\n')
|
|
msg = domish.Element(('http://code.google.com/p/kippo/', 'kippo'))
|
|
msg['type'] = msgtype
|
|
msg.addChild(xmsg)
|
|
body.addChild(msg)
|
|
self.muc.groupChat(to, None, children=[body])
|
|
|
|
# We have to return an unique ID
|
|
def createSession(self, peerIP, peerPort, hostIP, hostPort):
|
|
session = uuid.uuid4().hex
|
|
ses = domish.Element((None, 'session'))
|
|
ses['session'] = session
|
|
ses['remote_host'] = peerIP
|
|
ses['remote_port'] = str(peerPort)
|
|
if self.anonymous == True:
|
|
ses['local_host'] = '127.0.0.1'
|
|
else:
|
|
ses['local_host'] = hostIP
|
|
ses['local_port'] = str(hostPort)
|
|
|
|
self.broadcast('createsession', ses)
|
|
return session
|
|
|
|
def handleTTYLogOpened(self, session, args):
|
|
pass
|
|
|
|
def handleConnectionLost(self, session, args):
|
|
ses = domish.Element((None, 'session'))
|
|
ses['session'] = session
|
|
self.broadcast('connectionlost', ses)
|
|
|
|
def handleLoginFailed(self, session, args):
|
|
ses = domish.Element((None, 'credentials'))
|
|
ses['session'] = session
|
|
ses['username'] = args['username']
|
|
ses['password'] = args['password']
|
|
self.broadcast('loginfailed', ses)
|
|
|
|
def handleLoginSucceeded(self, session, args):
|
|
ses = domish.Element((None, 'credentials'))
|
|
ses['session'] = session
|
|
ses['username'] = args['username']
|
|
ses['password'] = args['password']
|
|
self.broadcast('loginsucceeded', ses)
|
|
|
|
def handleCommand(self, session, args):
|
|
ses = domish.Element((None, 'command'))
|
|
ses['session'] = session
|
|
ses['command'] = 'known'
|
|
ses.addContent(args['input'])
|
|
self.broadcast('command', ses)
|
|
|
|
def handleUnknownCommand(self, session, args):
|
|
ses = domish.Element((None, 'command'))
|
|
ses['session'] = session
|
|
ses['command'] = 'unknown'
|
|
ses.addContent(args['input'])
|
|
self.broadcast('command', ses)
|
|
|
|
def handleInput(self, session, args):
|
|
ses = domish.Element((None, 'input'))
|
|
ses['session'] = session
|
|
ses['realm'] = args['realm']
|
|
ses.addContent(args['input'])
|
|
self.broadcast('input', ses)
|
|
|
|
def handleTerminalSize(self, session, args):
|
|
pass
|
|
|
|
def handleClientVersion(self, session, args):
|
|
ses = domish.Element((None, 'version'))
|
|
ses['session'] = session
|
|
ses['version'] = args['version']
|
|
self.broadcast('clientversion', ses)
|
|
|
|
# vim: set sw=4 et:
|