summaryrefslogtreecommitdiffstats
path: root/py-bin/ejabber_auth.py
blob: 8acb10dc49279b3f3cb3528fc3e5059c7704214d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
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()