Ticket #11501: ldapauth.py

File ldapauth.py, 3.1 KB (added by rmartinjak, 10 years ago)
Line 
1class LdapAuth(AuthMethod):
2    """
3    Authentication via LDAP
4   
5    User authentication works like this:
6    1a. bind to LDAP with a generic (configured) DN and password
7    1b. find the ldap object matching to username. return None when more than 1 object is found
8    2. if 1 succeeds, bind with the user DN and the supplied password
9
10    User lookup:
11    wildcard-match all configured "user lookup attributes" for
12    the given search string
13    """
14    def __init__(self, conf):
15        AuthMethod.__init__(self, conf)
16
17    def _ldap_search(self, query, attrlist=None):
18        """
19        runs any ldap query passed as arg
20        """
21        import ldap
22        conn = ldap.initialize(self._conf['ldap_uri'])
23        try: 
24            conn.simple_bind_s(self._conf['ldap_binddn'], self._conf['ldap_bindpw'])
25        except: 
26            raise ValueError, "invalid LDAP credentials"
27
28        result = conn.search_ext_s(self._conf['ldap_basedn'],
29                                     ldap.SCOPE_SUBTREE,
30                                     filterstr=query,
31                                     attrlist=attrlist)
32        conn.unbind_s()
33        return result
34       
35    def _get_ldapuser(self, username, attrlist=None):
36        from ldap.filter import filter_format
37        # escape
38        try:
39            result = self._ldap_search(filter_format("(%s=%s)", [self._conf['ldap_username_attrib'], username]), attrlist)
40        except:
41            return None
42        # return None if more than 1 object found
43        return result[0] if len(result) == 1 else None
44
45    def user_lookup(self, search):
46        from ldap.filter import filter_format
47        # build a ldap OR query
48        q = "(|"
49        for a in self._conf['ldap_lookup_attribs']:
50            q += filter_format("(%s=*%s*)", [a, search])
51        q += ")"
52
53        try:
54            r = self._ldap_search(q, attrlist=[self._conf['ldap_username_attrib']])
55        except:
56            return None
57        # return a list of usernames
58        return [x[1][self._conf['ldap_username_attrib']][0] for x in r if x[1].has_key(self._conf['ldap_username_attrib'])]
59       
60    def check_user(self, username):
61        return self._get_ldapuser(username) is not None
62   
63    def check_password(self, username, password):
64        import ldap
65        # retrieve username's DN
66        try:
67            u = self._get_ldapuser(username)
68            #u[0] is DN, u[1] is a dict with all other attributes
69            userdn = u[0]
70        except ValueError:
71            return False
72
73        # try to bind with that DN
74        try: 
75            conn = ldap.initialize(uri=self._conf['ldap_uri'])
76            conn.simple_bind_s(userdn, password)
77            conn.unbind_s()
78            return True
79        except ldap.INVALID_CREDENTIALS: 
80            return False
81
82    def get_attrib(self, username, attrib):
83        # translate some common attribute names to their ldap equivalents, i.e. "email" is "mail
84        attrib = 'mail' if attrib == 'email' else attrib
85
86        u = self._get_ldapuser(username)
87        if u is not None:
88            a = u[1][attrib][0] #if u[1].has_key(attrib) else '' 
89            return a