pvl/login/auth.py
author Tero Marttila <terom@paivola.fi>
Sun, 07 Sep 2014 14:21:56 +0300
changeset 424 e77e967d59b0
parent 370 184917c7d4d4
permissions -rw-r--r--
hgignore: use glob; ignore snmp mibs
import ldap

import pvl.ldap.domain
import pvl.users.group

import logging; log = logging.getLogger('pvl.login.auth')

class AuthError (Exception) :
    def __init__ (self, error) :
        self.error = error

    def __unicode__ (self) :
        return u"Authenticating against the backend failed: {self.error}".format(self=self)

class LDAPAuth (object) :
    def __init__ (self, ldap) :
        self.ldap = ldap

    def auth (self, username, password) :
        """
            Attempt to bind against LDAP with given user object and password.

            Returns None if the user does not seem to exist, False on invalid auth, True on valid auth.

            Raises AuthError.
        """
        
        # search
        try :
            user = self.ldap.users.get(username)
        except KeyError :
            log.info("%s: not found", username)
            return None
        else :
            log.info("%s: %s", username, user)
        
        # bind
        bind = self.bind(user, password)
        
        if bind :
            return user
        else :
            return False

    def bind (self, user, password) :
        """
            Attempt to bind against LDAP with given user object and password.
        
            Returns the bound connection, or
                None        - if the user does not seem toe xist
                False       - invalid auth

            Raises AuthError.
        """

        conn = self.ldap.open()
        
        try :
            conn.bind(user.dn, password)

        except ldap.INVALID_CREDENTIALS as ex :
            log.info("%s: INVALID_CREDENTIALS", user)
            return False

        except ldap.NO_SUCH_OBJECT as ex :
            log.info("%s: ldap.NO_SUCH_OBJECT", user)
            return None
    
        except ldap.LDAPError as ex :
            log.exception("%s", user)
            raise AuthError(ex)

        else :
            log.info("%s", user)
            return conn

    def access (self, user) :
        """
            Yield a list of access control tokens for the given auth username.
        """
        
        yield pvl.users.group.Group.fromldap(self.ldap.users.group(user))

        for group in self.ldap.users.groups(user) :
            yield pvl.users.group.Group.fromldap(group)
    
    def userdata (self, user) :
        """
            Yield arbitrary userdata for given auth state.
        """

        return user.get('cn')

    def renew (self, username) :
        """
            Re-lookup auth state for given username.
        """

        try :
            return self.ldap.users.get(username)
        except KeyError :
            return None