module DRbService::LDAPAuthentication

An authentication strategy for DRbService – set a password via a class method.

Attributes

authuser[R]

the username of the authenticated user

authuser_branch[R]

the Treequel::Branch of the authenticated user

Public Class Methods

included( klass ) click to toggle source

Overridden mixin callback – add the ClassMethods to the including class

Calls superclass method
# File lib/drbservice/ldapauth.rb, line 82
def self::included( klass )
        super
        klass.extend( ClassMethods )
end
new( *args ) click to toggle source

Set up some instance variables used by the mixin.

Calls superclass method
# File lib/drbservice/ldapauth.rb, line 89
def initialize( *args )
        super
        @authenticated         = false
        @authuser              = nil
        @authuser_branch = nil
end

Public Instance Methods

authenticate( user, password ) { || ... } click to toggle source

Authenticate using the specified password, calling the provided block if authentication succeeds. Raises a SecurityError if authentication fails. If no password is set, the block is called regardless of what the password is.

Calls superclass method
# File lib/drbservice/ldapauth.rb, line 107
def authenticate( user, password )
        uri = self.class.ldap_uri
        self.log.debug "Connecting to %p for authentication" % [ uri ]
        directory = Treequel.directory( uri )
        self.log.debug "  finding LDAP record for: %p" % [ user ]
        user_branch = self.find_auth_user( directory, user ) or
                return super

        self.log.debug "  binding as %p (%p)" % [ user, user_branch ]
        directory.bind_as( user_branch, password )
        self.log.debug "  bound successfully..."

        @authenticated = true

        if cb = self.class.ldap_authz_callback
                self.log.debug "  calling authorization callback..."

                unless self.call_authz_callback( cb, user_branch, directory )
                        msg = "  authorization failed for: %s" % [ user_branch ]
                        self.log.debug( msg )
                        raise SecurityError, msg
                end

                self.log.debug "  authorization succeeded."
        end

        @authuser = user
        @authuser_branch = user
        yield

rescue LDAP::ResultError => err
        self.log.error "  authentication failed for %p" % [ user_branch || user ]
        raise SecurityError, "authentication failure"

ensure
        @authuser = nil
        @authuser_branch = nil
        @authenticated = false
end

Protected Instance Methods

call_authz_callback( callback, user, directory ) click to toggle source

Call the authorization callback with the given user and directory and return true if it indicates authorization was successful.

# File lib/drbservice/ldapauth.rb, line 187
def call_authz_callback( callback, user, directory )

        if callback.respond_to?( :call )
                return true if callback.call( user, directory )

        else callback = self.method( callback )
                return true if callback.call( user, directory )
        end

end
find_auth_user( directory, username ) click to toggle source

Find the specified username entry in the given directory, which should be a Treequel::Directory. Returns the Treequel::Branch for the first found user, if one was found, or nil if no such user was found.

# File lib/drbservice/ldapauth.rb, line 155
def find_auth_user( directory, username )
        self.log.debug "Finding the user to bind as."

        if dnpattern = self.class.ldap_dn
                self.log.debug "  using DN pattern %p" % [ dnpattern ]
                dn = dnpattern % [ username ]
                user = Treequel::Branch.new( directory, dn )
                return user.exists? ? user : nil

        else
                dnsearch = self.class.ldap_dn_search
                usersearch = dnsearch[:base] ?
                        Treequel::Branch.new( directory, dnsearch[:base] ) :
                        directory.base
                usersearch = usersearch.scope( dnsearch[:scope] ) if dnsearch[:scope]
                usersearch = usersearch.filter( dnsearch[:filter] % [username] )

                self.log.debug "  using filter: %s" % [ usersearch ]
                if user = usersearch.first
                        self.log.debug "    search found: %s" % [ user ]
                        return user
                else
                        self.log.error "    search returned no entries" % [ usersearch ]
                        return nil
                end
        end

end