| 1 | #!/usr/bin/env python |
| 2 | # -*- coding: UTF-8 -*- |
| 3 | # Depends: python-mysqldb |
| 4 | import sys |
| 5 | import traceback |
| 6 | import struct |
| 7 | import time |
| 8 | import MySQLdb |
| 9 | import crypt |
| 10 | |
| 11 | # TODO: transformer toute la partie gestion de BdD en une classe |
| 12 | # TODO: connexion persistente et gérer les coupures de service MySQL |
| 13 | |
| 14 | _host = 'nss' |
| 15 | _user = 'jabber' |
| 16 | _passwd = 'password' |
| 17 | _db = 'auth' |
| 18 | |
| 19 | def find_user(user): |
| 20 | global _host, _user, _passwd, _db |
| 21 | db = MySQLdb.connect(host=_host, user=_user, passwd=_passwd, |
| 22 | db=_db, connect_timeout=1) |
| 23 | cur = db.cursor(MySQLdb.cursors.DictCursor) |
| 24 | nrows = cur.execute( |
| 25 | """SELECT uid FROM users WHERE source=0 AND username=%s""", (user, )) |
| 26 | del cur, db |
| 27 | return (nrows > 0) |
| 28 | |
| 29 | def authenticate_user(user, password): |
| 30 | global _host, _user, _passwd, _db |
| 31 | db = MySQLdb.connect(host=_host, user=_user, passwd=_passwd, |
| 32 | db=_db, connect_timeout=1) |
| 33 | cur = db.cursor(MySQLdb.cursors.DictCursor) |
| 34 | nrows = cur.execute( |
| 35 | """SELECT password FROM users WHERE source=0 AND username=%s""" |
| 36 | """ AND LENGTH(password)>1""", (user, )) |
| 37 | users = cur.fetchall() |
| 38 | del cur, db |
| 39 | if nrows < 1: |
| 40 | return False |
| 41 | for user in users: |
| 42 | if crypt.crypt(password, user['password']) == user['password']: |
| 43 | return True |
| 44 | return False |
| 45 | |
| 46 | def main(): |
| 47 | log_file = open('/var/log/ejabberd/auth-mysql.log', 'a') |
| 48 | while True: |
| 49 | try: |
| 50 | nread = sys.stdin.read(2) |
| 51 | if len(nread) == 0: |
| 52 | time.sleep(0.25) |
| 53 | continue |
| 54 | now = time.strftime('%Y/%m/%d %H:%M:%S', time.localtime()) |
| 55 | if len(nread) < 2: |
| 56 | log_file.write('%s bytes_read=%d\n' % (now, len(nread))) |
| 57 | log_file.flush() |
| 58 | continue |
| 59 | size = struct.unpack('>h', nread)[0] |
| 60 | data = sys.stdin.read(size) |
| 61 | (operation, data) = data.split(':', 1) |
| 62 | if operation == 'auth': |
| 63 | (user, host, password) = data.split(':', 2) |
| 64 | log_file.write('%s operation=%s user=%s host=%s\n' |
| 65 | % (now, operation, user, host)) |
| 66 | log_file.flush() |
| 67 | result = authenticate_user(user, password) |
| 68 | elif operation == 'isuser': |
| 69 | (user, host) = data.split(':', 1) |
| 70 | log_file.write('%s operation=%s user=%s host=%s\n' |
| 71 | % (now, operation, user, host)) |
| 72 | log_file.flush() |
| 73 | result = find_user(user) |
| 74 | elif operation == 'setpass': |
| 75 | (user, host, password) = data.split(':', 2) |
| 76 | log_file.write('%s operation=%s user=%s host=%s\n' |
| 77 | % (now, operation, user, host)) |
| 78 | log_file.flush() |
| 79 | #result = set_user_password(user, password) |
| 80 | result = False |
| 81 | else: |
| 82 | result = False |
| 83 | log_file.write('%s => result=%s\n' % (now, result)) |
| 84 | log_file.flush() |
| 85 | sys.stdout.write(struct.pack('>hh', 2, result and 1 or 0)) |
| 86 | sys.stdout.flush() |
| 87 | except: |
| 88 | traceback.print_exc(file=log_file) |
| 89 | #sys.exit() |
| 90 | |
| 91 | if __name__ == '__main__': |
| 92 | main() |