#!/usr/bin/python """ proxy_auth_ldap.py 0.1.8 - external authenticator for Squid (C) 1999 by Michael Stroeder This script is meant as external authenticator for Squid (see parameter authenticate_program in squid.conf). You need the ldapmodule for Python from: http://python-ldap.sourceforge.net/ License: Distributed under the terms of the GPL (GNU GENERAL PUBLIC LICENSE) Version 2 (see http://www.gnu.org/copyleft/gpl.html) $Id: proxy_auth_ldap.py,v 1.11 2003/03/25 11:17:11 michael Exp $ """ # Some configuration parameters # LDAP host to contact ldap_host = 'ldap.example.com' # bind DN for doing the searches # (might be sufficient to leave this empty) ldap_binddn = 'cn=UID-Searcher,ou=Processes,dc=example,dc=com' # ldap_passwd for LDAP bind dn given above ldap_passwd = 'Geheim123' # base DN for search ldap_basedn = 'ou=Users,dc=example,dc=com' # Specify a search filter template ldap_searchtemplate = '(uid=%(username)s)' ldap_cachetimeout = 7200 ldap_cachemaxmem = 50000 ######################################################################## # There's nothing to configure below ######################################################################## AUTH_FAILED = 'ERR\n' AUTH_OK = 'OK\n' import sys, os, string, socket, ldap, syslog def DoConnectAndBind(): try: # LDAP connection for doing the searches l_s = ldap.open(ldap_host) # LDAP connection for authentication tests l_a = ldap.open(ldap_host) except: exc_obj,exc_value,exc_traceback = sys.exc_info() syslog.syslog(syslog.LOG_CRIT,'Failed to connect to %s:\n%s' % (ldap_host,exc_value)) l_a,l_s = None, None else: syslog.syslog(syslog.LOG_INFO,'Connected to %s.' % (ldap_host)) try: l_s.bind_s(ldap_binddn,ldap_passwd,ldap.AUTH_SIMPLE) except: exc_obj,exc_value,exc_traceback = sys.exc_info() syslog.syslog(syslog.LOG_CRIT,'Unable to bind as "%s" to %s: %s %s' % (ldap_binddn,ldap_host,exc_obj,exc_value)) l_a.unbind() ; l_s.unbind() l_a,l_s = None, None else: syslog.syslog(syslog.LOG_INFO,'Bound as "%s" to %s.' % (ldap_binddn,ldap_host)) try: l_s.enable_cache(ldap_cachetimeout,ldap_cachemaxmem) except: pass else: syslog.syslog(syslog.LOG_INFO,'Enabled LDAP cache for %s (ldap_cachetimeout=%d,ldap_cachemaxmem=%d).' % (ldap_host,ldap_cachetimeout,ldap_cachemaxmem)) return (l_a,l_s) def iso2utf(s): new = '' for ch in s: c=ord(ch) if (c & 0x80) == 0: new = new+ch else: new = new+chr(0xC0 | (0x03 & (c >> 6)))+chr(0x80 | (0x3F & c)) return new ######################################################################## script_name=os.path.basename(sys.argv[0]) syslog.openlog(script_name,syslog.LOG_PID|syslog.LOG_NDELAY,syslog.LOG_AUTH) l_a,l_s = DoConnectAndBind() s = string.strip(sys.stdin.readline()) while s: try: username,ldap_passwd = string.split(s,' ',1) ldap_passwd = iso2utf(ldap_passwd) searchfilter = ldap_searchtemplate % {'username':username} if not ldap_passwd: auth_result = AUTH_FAILED syslog.syslog(syslog.LOG_DEBUG,'Empty ldap_passwd for user name "%s".' % (username)) else: auth_result = None while auth_result is None: if l_a==None or l_s==None: syslog.syslog(syslog.LOG_DEBUG,'Try connect to %s.' % (ldap_host)) l_a,l_s = DoConnectAndBind() if l_a==None or l_s==None: auth_result = AUTH_FAILED syslog.syslog(syslog.LOG_ERR,'Unable to connect to %s.' % (ldap_host)) else: try: result = l_s.search_s(ldap_basedn,ldap.SCOPE_SUBTREE,searchfilter,['objectclass'],1) if result and len(result)==1: ldap_dn = result[0][0] try: l_a.bind_s(ldap_dn,ldap_passwd,ldap.AUTH_SIMPLE) auth_result = AUTH_OK syslog.syslog(syslog.LOG_DEBUG,'Username "%s" authenticated against entry "%s".' % (username,ldap_dn)) except ldap.INVALID_CREDENTIALS: auth_result = AUTH_FAILED syslog.syslog(syslog.LOG_DEBUG,'ldap_passwd for "%s" not valid.' % (ldap_dn)) else: auth_result = AUTH_FAILED syslog.syslog(syslog.LOG_DEBUG,'Found %d entries with %s. No unique DN available.' % (len(result),searchfilter)) except ldap.NO_SUCH_OBJECT: auth_result = AUTH_FAILED syslog.syslog(syslog.LOG_DEBUG,'No such object. Probably because wrong value for ldap_basedn (currently "%s").' % (ldap_basedn)) except ldap.SERVER_DOWN: l_a.unbind() ; l_s.unbind() l_a,l_s = DoConnectAndBind() except ldap.LDAPError,e: exc_obj,exc_value,exc_traceback = sys.exc_info() auth_result = AUTH_FAILED syslog.syslog(syslog.LOG_ERR,'LDAP exception: %s, "%s"' % (exc_obj,exc_value)) except: exc_obj,exc_value,exc_traceback = sys.exc_info() auth_result = AUTH_FAILED syslog.syslog(syslog.LOG_ERR,'Unhandled exception: %s, "%s"' % (exc_obj,exc_value)) sys.stdout.write(auth_result) sys.stdout.flush() s = string.strip(sys.stdin.readline()) if l_s: l_s.unbind() if l_a: l_a.unbind() syslog.syslog(syslog.LOG_INFO,'Unbound as from %s. Terminating.' % (ldap_host))