Skip Menu |

This queue is for tickets about the Catalyst-Plugin-Authentication-LDAP CPAN distribution.

Report information
The Basics
Id: 20888
Status: new
Priority: 0/
Queue: Catalyst-Plugin-Authentication-LDAP

People
Owner: Nobody in particular
Requestors: izut [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: Unimportant
Broken in: (no value)
Fixed in: (no value)



Subject: Support for LDAP servers, other than Active Directory
Added support for servers other than Active Directory. First checks for user's DN on LDAP server, performing an anonymous bind, then use that to authenticated bind. Patch attached.
Subject: catalyst-plugin-authentication-ldap.diff
--- /usr/lib/perl5/site_perl/5.8.8/Catalyst/Plugin/Authentication/LDAP.pm 2005-04-27 18:15:12.000000000 -0300 +++ /home/igor/lib/Catalyst/Plugin/Authentication/LDAP.pm 2006-08-07 15:29:31.000000000 -0300 @@ -1,6 +1,7 @@ package Catalyst::Plugin::Authentication::LDAP; use strict; +use List::Util qw(first); use NEXT; use Net::LDAP; @@ -20,6 +21,7 @@ user_append => '@mycompany.com', user_filter => '(&(objectclass=user)(objectcategory=user)(samaccountname=__USER__*))', group_attribute => 'memberOf', + active_directory => 1, ); $c->login( $user, $password ); $c->logout; @@ -73,6 +75,12 @@ Optional. Specify which attribute contains the list of groups/roles the user is a member of. + active_directory => 1 + +Optional. You can omit it if you're connecting to servers other than Microsoft Active Directory. +If omitted, it will not use any of 'user_append' and 'user_context' attributes, searching for +user's DN before authenticated connection. + =head2 METHODS =over 4 @@ -92,26 +100,52 @@ return 1 if $c->request->{user}; my $ldap_server = $c->config->{authentication}->{ldap_server}; + my $active_directory = $c->config->{authentication}->{active_directory}; my $dnc = $c->config->{authentication}->{default_naming_context}; my $user_append = $c->config->{authentication}->{user_append} || ''; my $user_context = $c->config->{authentication}->{user_context} || 'cn=users'; my $user_filter = $c->config->{authentication}->{user_filter} || '(&(objectclass=user)(objectcategory=user)(samaccountname=__USER__*))'; my $group_attribute = $c->config->{authentication}->{group_attribute} || 'memberOf'; + my $user_dn = undef; eval { my $ldap = Net::LDAP->new( $ldap_server ) or die "Unable to connect to LDAP server $ldap_server: $@"; + $user_filter =~ s/__USER__/$user/; + # usually the username on LDAP servers are the entire user dn. it seems + # to not be true on Active Directory servers, so we check if the server + # we want to ask is an Active Directory. if not, we must perform an + # anonymous bind to search the user's DN for authenticated bind. + if ($active_directory) { + $user_dn = $user . $user_append; + } + else { + # perform an anonymous bind on ldap server. + my $rc = $ldap->bind(); + die "Server does not allow anonymous bind: " . $rc->error if $rc->code; + + # ldap search to get all possibles DN. + my $search = $ldap->search( + base => $dnc, + scope => "sub", + filter => $user_filter, + ); + die "Unable to retrieve DNs for filter: " . $search->error if $search->code; + + ($user_dn) = map { $_->dn } first { $_->dn =~ /$user/ } $search->entries; + } - my $rc = $ldap->bind( $user . $user_append, password => $password ); + # now we can perform an authenticated bind. + my $rc = $ldap->bind( $user_dn, password => $password ); die "User authentication failed for $user: " . $rc->error if $rc->code; # since most LDAP servers require a password on every connection, we have to query # the user's groups/roles here and store them in the session, since we won't have the # password available later - $user_filter =~ s/__USER__/$user/; my $search = $ldap->search( - base => $user_context . "," . $dnc, - scope => "sub", + # again, we must check if we are talking to an Active Directory server. + base => (defined $active_directory) ? $user_context . "," . $dnc : $dnc, + scope => "sub", filter => $user_filter, ); die "Unable to retrieve user details for $user: " . $search->error if $search->code;