<html><body>
<p>Hi,<br>
I'm having problems implementing LDAP user authentication in RT and perhaps someone has done this on RT 3.6.3.  Basically,  its not allowing me to authenticate either using an existing RT user or an LDAP user.    I copied the CurrentUser_Local.pm over to my /opt/rt3/lib/RT directory and from what I can observe, RT is not calling the IsPassword function.  I know this because I added a bunch of debug statements and don't see it being generated in any of the logs that I know.  Is there anything I need to do different?  or anyone know of any gotchas I should be aware of?   I've included in this note the output from the /var/log/error_log, and CustomUser_Local.pm.   Any help is very much appreciated.  Thanks.<br>
<br>
BTW, I modified the autohandler to print out my user and password.<br>
[Fri Mar 02 14:33:25 2007] [notice] suEXEC mechanism enabled (wrapper: /usr/sbin/suexec)<br>
[Fri Mar 02 14:33:25 2007] [notice] Digest: generating secret for digest authentication ...<br>
[Fri Mar 02 14:33:25 2007] [notice] Digest: done<br>
[Fri Mar 02 14:33:25 2007] [notice] LDAP: Built with OpenLDAP LDAP SDK<br>
[Fri Mar 02 14:33:25 2007] [notice] LDAP: SSL support unavailable<br>
[Fri Mar 02 14:33:26 2007] [notice] FastCGI: process manager initialized (pid 26008)<br>
[Fri Mar 02 14:33:26 2007] [warn] FastCGI: server "/opt/rt3/bin/mason_handler.fcgi" started (pid 26010)<br>
[Fri Mar 02 14:33:26 2007] [notice] Apache/2.0.52 (Red Hat) configured -- resuming normal operations<br>
[Fri Mar 02 14:33:27 2007] [warn] FastCGI: server "/opt/rt3/bin/mason_handler.fcgi" started (pid 26018)<br>
[Fri Mar 02 14:33:28 2007] [warn] FastCGI: server "/opt/rt3/bin/mason_handler.fcgi" started (pid 26019)<br>
[Fri Mar 02 14:33:29 2007] [warn] FastCGI: server "/opt/rt3/bin/mason_handler.fcgi" started (pid 26020)<br>
[Fri Mar 02 14:34:49 2007] [error] [client 9.41.30.100] FastCGI: server "/opt/rt3/bin/mason_handler.fcgi" stderr: [Fri Mar  2 20:34:49 2007] [error]: DEBUG: egaona@us.ibm.com password: boo (/opt/rt3/share/html/autohandler:248), referer: <a href="http://austrack01.austin.ibm.com/index.html">http://austrack01.austin.ibm.com/index.html</a><br>
[Fri Mar 02 14:34:49 2007] [error] [client 9.41.30.100] FastCGI: server "/opt/rt3/bin/mason_handler.fcgi" stderr: [Fri Mar  2 20:34:49 2007] [error]: FAILED LOGIN for egaona@us.ibm.com from 9.41.30.100 (/opt/rt3/share/html/autohandler:250), referer: <a href="http://austrack01.austin.ibm.com/index.html">http://austrack01.austin.ibm.com/index.html</a><br>
<br>
<br>
Here are the contents of CurrentUser_Local.pm and the LDAP settings.   We have another instance of RT, but its using the 3.4.x release and its working beautifully.  <br>
<br>
RT_SiteConfig.pm:<br>
Set($LdapServer, "bluepages.ibm.com:389");<br>
Set($LdapUser, "");<br>
Set($LdapPass, "");<br>
Set($LdapBase, "ou=bluepages,o=ibm.com");<br>
Set($LdapUidAttr, "mail");<br>
Set($LdapFilter, "(objectclass=*)");<br>
Set($LdapTLS, 0);<br>
Set($LdapNameAttr, "cn");<br>
Set($LdapMailAttr, "mail");<br>
Set($AutoCreateFromExternalUserInfo, 1);<br>
Set($MaxInlineBody, 13456);<br>
<br>
CurrentUser_Local.pm:<br>
<tt>#<br>
# AutoCreateFromExternalUserInfo overlay<br>
#<br>
# author: Robin Battey <zanfur at zanfur dot com><br>
# <br>
# based in part by the LookupExternalUserInfo function<br>
# written by Jeff Hoover <jeff.hoover at infotechfl dot com><br>
#<br>
# This Overlay is useful if you want the following behavior:<br>
#  * Whenever RT tries -- and fails -- to load a user from the <br>
#    RT user database, it queries an Ldap server for the account<br>
#    information and creates it on the fly (for both email lookups<br>
#    and web logins)<br>
#  * RT behaves as though the account has always been there -- i.e.<br>
#    there is no reason to give "Everyone" the "Create Ticket" right,<br>
#    because the account has been there all along ...<br>
#  * NO synchronization with the Ldap server once the account has<br>
#    been created, so any changes in RT stay in RT and any changes<br>
#    in Ldap stay in Ldap (unless you run some other script, of course)<br>
#<br>
# The situation I had at my place of employment, which caused me<br>
# to write this, is we have an Active Directory server with a fairly<br>
# large number of users on it, with a fair bit of adding/deleting of<br>
# users going on.  I wanted a way for users to send a request to the<br>
# help queue, and then immediately be able to see the ticket, the<br>
# ticket's status, etc using their Active Directory (i.e. windows <br>
# domain) username and password.  I wrote this overlay for the account<br>
# generation, and used the LdapOverlay available in the "Contributions"<br>
# section of the RT3 Wiki (</tt><tt><a href="http://wiki.bestpractical.com">http://wiki.bestpractical.com</a></tt><tt>) for the <br>
# authentication.  This overlay was therefore designed to work well <br>
# with the LdapOverlay, and actually uses (some of) the same Ldap <br>
# variables.<br>
#<br>
# I spent a bit of effort making sure this was modular, particularly <br>
# in the case of a different external user info source.  It currently <br>
# works with LDAP (and, of course, Active Directory), but there's no<br>
# good reason why you can't just replace the LookupExternalUserInfo <br>
# function to get your data from somewhere else.<br>
<br>
no warnings qw(redefine);<br>
use Net::LDAP qw(LDAP_SUCCESS LDAP_PARTIAL_RESULTS);<br>
use Net::LDAP::Util qw (ldap_error_name);<br>
use Net::LDAP::Filter;<br>
use constant DEBUG => 1; # Change to 1 to log debugging info.<br>
<br>
<br>
# {{{ sub IsPassword<br>
<br>
# Modification Originally by Marcelo Bartsch <bartschm_cl@hotmail.com><br>
# Update by Stewart James <stewart.james@vu.edu.au for rt3.<br>
# Update by David Wheeler <david@kineticode.com> for TLS and Group membership support.<br>
# Drop this file in /opt/rt3/lib/RT/User_Local.pm<br>
# Drop something like below in yout RT_SiteConfig.pm<br>
# $LDAPExternalAuth = 1;<br>
# $LdapServer="127.0.0.1";<br>
# $LdapUser="";<br>
# $LdapPass="";<br>
# $LdapBase="ou=Users,dc=example,dc=com";<br>
# $LdapUidAttr="uid";<br>
# $LdapFilter="(objectclass=*)";<br>
# $LdapTLS = 1;<br>
# $LdapGroup ="cn=RT,ou=Group,dc=example,dc=com";<br>
# $LdapGroupAttribute = 'uniqueMember';<br>
# $LdapSSLVersion = 3;<br>
<br>
$Net::SSLeay::ssl_version = $RT::LdapSSLVersion<br>
  if $RT::LdapTLS && defined $RT::LdapSSLVersion;<br>
<br>
sub IsPassword {<br>
    my $self  = shift;<br>
    my $user  = shift;<br>
    my $pass = shift;<br>
<br>
    #TODO there isn't any apparent way to legitimately ACL this<br>
<br>
    # RT does not allow null passwords<br>
    return unless defined $pass && $pass ne '';<br>
                 <br>
     $RT::Logger->debug("DEBUG self: ", $self, "\n");<br>
     $RT::Logger->debug("DEBUG user: ", $user, "\n");<br>
     $RT::Logger->debug("DEBUG pass: ", $pass, "\n");<br>
#    if ( $self->PrincipalObj->Disabled ) {<br>
#        $RT::Logger->info("Disabled user " . $self->Name . " tried to log in" );        return;<br>
#    }<br>
<br>
#    my $password = $self->__Value('Password');<br>
#    return unless defined $password && $password ne '';<br>
<br>
    #  if it's a historical password we say ok.<br>
#    return 1 if $RT::User->_GeneratePassword($pass) eq $password;<br>
<br>
    if ($RT::LDAPExternalAuth) {<br>
#        $user = RT::Interface::Web::WebCanonicalizeInfo();<br>
<br>
        my %user_info;<br>
        my $ldap = Net::LDAP->new($RT::LdapServer, version=>3)<br>
          or $RT::Logger->critical("GetExternalUserWithLDAP: Cannot connect to LDAP\n"),<br>
            return;<br>
<br>
        my $mesg = defined $RT::LdapUser && $RT::LdapUser ne ''<br>
          ? $ldap->bind($RT::LdapUser, password => $RT::LdapPass )<br>
          : $ldap->bind;<br>
<br>
        unless ($mesg->code == LDAP_SUCCESS) {<br>
            $RT::Logger->critical("GetExternalUserWithLDAP: Cannot bind to LDAP: ", $mesg->code, "\n");<br>
            return;<br>
        }<br>
        my $filter = Net::LDAP::Filter->new(<br>
          "mail=$user"<br>
        );<br>
        $RT::Logger->debug("GetExternalUserWithLDAP: First search filter '",<br>
                           $filter->as_string . "'\n") if DEBUG;<br>
        $mesg = $ldap->search(<br>
            base   => $RT::LdapBase,<br>
            filter => $filter,<br>
            attrs  => ['mail','telephonenumber','cn','uid']<br>
        );<br>
<br>
        unless ($mesg->code == LDAP_SUCCESS || $mesg->code == LDAP_PARTIAL_RESULTS) {<br>
            $RT::Logger->debug("GetExternalUserWithLDAP: Could not search for ",                               $filter->as_string, ": ", $mesg->code, "",<br>
                               ldap_error_name($mesg->code), "\n") if DEBUG;<br>
            return;<br>
        }<br>
<br>
        $RT::Logger->debug("GetExternalUserWithLDAP: First search produced ",<br>
                           $mesg->count, " results\n") if DEBUG;<br>
        unless ($mesg->count) {<br>
            $RT::Logger->info("AUTH FAILED: " . $self->Name . "\n");<br>
            return;<br>
        }<br>
<br>
        my $mesg2 = $ldap->bind($mesg->first_entry->dn, password => $pass );<br>
        if ($mesg2->code == LDAP_SUCCESS) {<br>
<br>
            # Create user on the fly if they don't already exist<br>
            if (!$self->Id()) {<br>
                my $entry = $mesg->entry(0);<br>
                $user_info{'RealName'} = $entry->get_value('cn');<br>
                $user_info{'EmailAddress'} = $entry->get_value('mail');<br>
                $user_info{'WorkPhone'} = $entry->get_value('telephonenumber');<br>
                $user_info{'Gecos'} = $entry->get_value('uid');<br>
<br>
                my $UserObj = RT::User->new(RT::CurrentUser->new('RT_System'));<br>
                my ($val, $msg) = $UserObj->Create(<br>
                                 Name=> $user_info{'EmailAddress'},<br>
                                 Gecos=> $user_info{'Gecos'}<br>
                                 );<br>
                unless ($val) {<br>
                    $RT::Logger->info ("CreateFromExternalUserInfo: failed to create user with args: ", %params, "\nval=".$val."\nmsg=".$msg);<br>
                     return undef;<br>
                }<br>
<br>
                # Set several attributes<br>
                $UserObj->SetRealName($user_info{'RealName'});<br>
                $UserObj->SetEmailAddress($user_info{'EmailAddress'});<br>
                $UserObj->SetWorkPhone($user_info{'WorkPhone'});<br>
                <br>
                $RT::Logger->info ("CreateFromExternalUserInfo: created user $val (\"$msg\")\n");<br>
                $self->LoadByCol("EmailAddress",$user_info{'EmailAddress'});<br>
<br>
            }<br>
            $RT::Logger->info("AUTH OK: " . $user_info{'EmailAddress'} . " (" .$user_info{'Gecos'} . ")\n");<br>
            return 1;<br>
        } else {<br>
            $RT::Logger->critical("GetExternalUserWithLDAP: Cannot bind to LDAP:",<br>
                                  $mesg2->code, "\n");<br>
            return;<br>
        }<br>
    } else {<br>
        return 1 if crypt($pass, $password) eq $password;<br>
    }<br>
<br>
    # no password check has succeeded. get out<br>
    return;<br>
}<br>
<br>
# }}}<br>
<br>
<br>
1;<br>
</tt><br>
<br>
Enrique<br>
<br>
</body></html>