cowrie/kippo/dblog/xmpp.py

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: