From: Steven L. <le...@wr...> - 2001-12-11 16:23:21
|
Trying to authenticate user/pass in mod_perl againsed an LDAP server. Existing code uses one bind/search to look up the uid, gets back the DN from the first query and attempts to perform a bind with domain of the returned DN and password = $password. Problem at this point is that the second bind always succeeds. Customer is running a Netscape LDAP server, don't know the version (unless there is a simple way to ask). The code fragment below is supposed to work for them, but I don't have access to Nescape's LDAP Developers' Toolkit in order to compile perldap-1.4; would prefer to use Net::LDAP if it will work. Question: Is there any reasonable way to accomplish the steps shown below using Net::LDAP rather than Mozilla::LDAP? Or am I just screwing up the second bind? thanx. sl ######################################################################## # Mozilla::LDAP version ######################################################################## # !/usr/bin/perl -w use Mozilla::LDAP::Conn; use Mozilla::LDAP::Utils; use Mozilla::LDAP::Entry; $user="$ARGV[0]"; $password="$ARGV[1]"; $GROUPDN = "ou=groups, o=FOO"; $BASEDN = "ou=people, o=FOO"; $conn = new Mozilla::LDAP::Conn(white, 389); # Anonymous bind die "Could't connect to LDAP server $host" unless $conn; $entry = $conn->search("o=FOO", samelevel, "(uid=$user)", 0, (uid)); if (! $entry) { print "No such userid: $user\n"; exit(1); } $dn = $entry->getDN(); $search = "(&(cn=proxy)(uniquemember=$dn))"; $entry = $conn->search($GROUPDN, "samelevel", "$search"); if ($entry) { $ret = $conn->simpleAuth($dn, $password); if ($ret) { { #print "$user was accepted\n"; $conn->close if $conn; exit(0); } } else { print "$user rejected for Invalid Password\n"; # Authentication Failed $conn->close if $conn; exit(1); } } ######################################################################## # Net::LDAP version ######################################################################## # !/usr/local/bin/perl -w ######################################################################## # housekeeping ######################################################################## use strict; $\ = "\n"; $, = "\n"; $| = 1; use Carp; use Net::LDAP qw( :all ); use Net::LDAP::LDIF; # use to pretty-print the results. use Data::Dumper; local $Data::Dumper::Terse = 1; local $Data::Dumper::Indent = 1; local $Data::Dumper::Deepcopy = 1; ######################################################################## # globals ######################################################################## my $host = 'ldap.foo.com'; my $port = getservbyname( 'ldap', 'tcp' ) || 389; my $base = q{ou=people, o=FOO}; ######################################################################## # real work begins here ######################################################################## my $ldh = Net::LDAP->new( $host, port => $port ) or croak "Failed LDAP->new"; print "LDH for anonymous bind: ", Dumper $ldh; my $bindresult = $ldh->bind; croak "Roadkill: bind: $bindresult->code()" if $bindresult->code(); for my $username ( qw( jowbloe jondow ) ) { my @searchparmz = ( base => $base, scope => 'one', filter => qq{(uid=\L$username)}, attrs => [ 'uid' ], ); print "\nSearching on:", Dumper \@searchparmz; if( my $result = $ldh->search(@searchparmz) ) { croak "Roadkill: search: " . $result->code if $result->code; my $struct = $result->as_struct; print "\nYields:", Dumper $struct; # snag the DN out of the returned query, it'll be the only # key for this query. if( my $newbase = ( %$struct )[0] ) { # might not need the second ldh, re-binding may # work but also might not. need to test this # after the rest of it works. if( my $ldh2 = Net::LDAP->new( $host, port => $port ) ) { print "LDH for password bind: ", Dumper $ldh2; # it is unlikely that anyone has picked either of # these as a password. # # it should be impossible to return a successful # bind with both. for my $password ( qw(foo bar) ) { # take the base returned from the first query, # try to bind it with the supplied password. # this should -- I think? -- only succeed if # the password is valid. my @bindparmz = ( base => $newbase, password => $password, ); print "\nBinding with:", Dumper \@bindparmz; $bindresult = $ldh2->bind( @bindparmz ); croak "Roadkill: bind: " . $bindresult->code() if $bindresult->code(); if( my $result = $ldh->search(@searchparmz) ) { print "Final result: ", Dumper $result->as_struct; } else { warn "Secondary query failed"; } } } else { warn "Failed to allocate second LDAP handle"; } } else { warn "No employee number found"; } } else { warn "No Search Result Returned"; } } # keep the shell happy 0 __END__ -- Steven Lembark 2930 W. Palmer Workhorse Computing Chicago, IL 60647 +1 800 762 1582 |