diff options
Diffstat (limited to 'py-bin/ejabber_auth.py')
-rw-r--r-- | py-bin/ejabber_auth.py | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/py-bin/ejabber_auth.py b/py-bin/ejabber_auth.py new file mode 100644 index 0000000..8acb10d --- /dev/null +++ b/py-bin/ejabber_auth.py @@ -0,0 +1,133 @@ +#!/usr/bin/python + +# this is an extauth script for use with ejabberd. +# it uses a binary protocol for communicating via stdin/stdout +# see ejabberd.jabber.ru/extauth for more examples +# this script uses the iwebjabber-database from for authentification + + +import sys, logging, os +import config +sys.stderr = open(config.authlog_path, 'a') +from struct import * +from jabberman import JabberDB + +class EjabberdInputError(Exception): + def __init__(self, value): + self.value = value + def __str__(self): + return repr(self.value) + +class EjabberAuth: + """ + ejabberd starts one instance for each domain it's serving + """ + def __init__(self): + self.jadb = JabberDB() + logging.basicConfig(level=logging.INFO, + format='%(asctime)s %(levelname)s %(message)s', + filename=config.authlog_path, + filemode='a') + logging.info('extauth script started, waiting for ejabberd requests') + + def ejabberd_in(self): + """ + Read from stdin, this is what ejabberd sends us + """ + logging.debug("trying to read 2 bytes from ejabberd:") + try: + input_length = sys.stdin.read(2) + except IOError: + logging.debug("ioerror") + if len(input_length) is not 2: + logging.debug("ejabberd sent us wrong things!") + raise EjabberdInputError('Wrong input from ejabberd!') + logging.debug('got 2 bytes via stdin') + + (size,) = unpack('>h', input_length) + return sys.stdin.read(size).split(':') + + def genanswer(self, bool): + answer = 0 + if bool: + answer = 1 + return pack('>hh', 2, answer) + + def ejabberd_out(self, bool): + logging.debug("Ejabberd gets: %s" % bool) + token = genanswer(bool) + logging.debug("sent bytes: %#x %#x %#x %#x" % (ord(token[0]), ord(token[1]), ord(token[2]), ord(token[3]))) + sys.stdout.write(token) + sys.stdout.flush() + + def log_success(self, method, jid, success): + if success: + logging.debug("%s successful for %s" % (method, jid)) + else: + logging.debug("%s unsuccessful for %s" % (method, jid)) + + def validate_jid(self, jid, password): + logging.debug("%s wants authentication ..." % (jid)) + return self.jadb.validate_jid(jid, password) + + def is_jid(self, jid): + logging.debug("do we know %s?" % (jid)) + return self.jadb.is_jid(jid) + + def update_jid(self, jid, new_password): + logging.debug("update_jid for %s" % (jid)) + + if self.jabdb.update_jid(jid, new_password): + logging.debug("password change for %s successful" % (jid)) + return True + else: + logging.debug("password change for %s not successful" % (jid)) + return False + + def run(self): + """ + Loop the auth script forever + """ + while True: + logging.debug("start of infinite loop") + + try: + data = self.ejabberd_in() + except EjabberdInputError, inst: + logging.info("Exception occured: %s", inst) + break + + logging.debug('Method: %s' % data[0]) + success = False + + jid = "%s@%s" % (data[1], data[2]) + + if data[0] == "auth": + success = self.validate_jid(jid, data[3]) + self.ejabberd_out(success) + self.log_success("auth", jid, success) + + elif data[0] == "isuser": + success = self.is_jid(jid) + self.ejabberd_out(success) + self.log_success("is_jid", jid, success) + + elif data[0] == "setpass": + success = self.update_jid(jid, data[3]) + self.ejabberd_out(success) + self.log_success("update_jid", jid, success) + + logging.debug("end of infinite loop") + + logging.info('extauth script terminating') + + +auth = EjabberAuth() +auth.run() + + + + + + + |