#!/usr/bin/env python ###################################################################### ## ## Copyright (C) 2006, Goedson Teixeira Paixao ## ## This program is free software; you can redistribute it and/or ## modify it under the terms of the GNU General Public License ## as published by the Free Software Foundation; either version 2 ## of the License, or (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, write to the Free Software ## Foundation, Inc., 51 Franklin Street, Fifth Floor Boston, ## MA 02110-1301, USA ## ## Filename: check_pass_pam.py ## Author: Goedson Teixeira Paixao ## Description: Check ejabberd user password using PAM ## ## Created at: Wed Aug 2 09:50:56 2006 ## Modified at: Tue Aug 22 09:54:59 2006 ## Modified by: Goedson Teixeira Paixao ###################################################################### ''' An external script for ejabberd to check user passwords against PAM ''' __revision__ = '0.1' import sys import traceback import struct import PAM import time def pam_auth_conversation(username, password): ''' Defines a PAM conversation function to pass username and password ''' def pam_conversation(auth, query_list, userdata): ''' Does the conversation to feed PAM with username and password. ''' resp = [] for i in range(len(query_list)): _, query_type = query_list[i] if query_type == PAM.PAM_PROMPT_ECHO_ON: val = username resp.append((val, 0)) elif query_type == PAM.PAM_PROMPT_ECHO_OFF: val = password resp.append((val, 0)) else: return None return resp return pam_conversation def authenticate_user(username, password): ''' Check, using PAM, if the username and password provided match. ''' auth = PAM.pam() auth.start('passwd') auth.set_item(PAM.PAM_CONV, pam_auth_conversation(username, password)) try: auth.authenticate() except PAM.error: return False except: return False else: return True def main(): ''' The main loop ''' log_file = open('/var/log/ejabberd/pam_auth.log', 'w') while True: time.sleep(2) try: nread = sys.stdin.read(2) now = time.strftime('%d/%m/%Y %H:%M:%S',time.localtime()) if len(nread) < 2: log_file.write('time=%s bytes_read=%d\n' % (now, len(nread))) log_file.flush() continue size = struct.unpack('>h', nread)[0] data = sys.stdin.read(size) (operation, user, host, password) = data.split(':') log_file.write('time=%s operation=%s user=%s host=%s\n' % (now, operation, user, host)) log_file.flush() if operation == 'auth': result = authenticate_user(user, password) if result: sys.stdout.write(struct.pack('>hh', 2, 1)) else: sys.stdout.write(struct.pack('>hh', 2, 0)) sys.stdout.flush() elif operation == 'isuser': sys.stdout.write(struct.pack('>hh', 2, 1)) sys.stdout.flush() else: sys.stdout.write(struct.pack('>hh', 2, 0)) sys.stdout.flush() except: traceback.print_exc(file=log_file) if __name__ == '__main__': main()