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 |
From: Jim H. <ha...@us...> - 2001-12-11 17:59:04
|
2 things: I'm not sure if this works from your code my $struct = $result->as_struct; if( my $newbase = ( %$struct )[0] ) If it does, that's fine, but if( my $newbase = $result->dn ) is clearer. That said, the following is definitely an issue: my @bindparmz = ( base => $newbase, password => $password, ); $bindresult = $ldh2->bind( @bindparmz); you should replace 'base' with 'dn' --Jim Harle On Tue, 11 Dec 2001, Steven Lembark wrote: > > 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 > |
From: <le...@wr...> - 2001-12-11 18:12:57
|
> if( my $newbase = $result->dn ) > > is clearer. That said, the following is definitely an issue: > my @bindparmz = > ( > base => $newbase, > password => $password, > ); > $bindresult = $ldh2->bind( @bindparmz); > you should replace 'base' with 'dn' Looks like $result->dn returns nothing, though the first key returned in the struct hash seems to be a valid dn for the following query... Using the corrrect paramter for the bind certianly helps :-) thanx sl 58: print "\nSearching on:", Dumper \@searchparmz; 59 60: if( my $result = $ldh->search(@searchparmz) ) 61 { 62: croak "Roadkill: search: " . $result->code if $result->code; 63 64: my $struct = $result->as_struct; 65 66: print "\nYields:", Dumper $result->as_struct; Searching on: [ 'base', 'ou=people, o=FOO', 'scope', 'one', 'filter', '(uid=jowbloe)', 'attrs', [ 'uid' ] ] main::(test-ldap:66): print "\nYields:", Dumper $result->as_struct; DB<2> n Yields: { 'employeenumber=12345, ou=people, o=FOO' => { 'uid' => [ 'jowbloe' ] } } main::(test-ldap:68): if( my $newbase = $result->dn ) main::(test-ldap:69): { DB<2> x $result->dn 0 '' -- Steven Lembark 2930 W. Palmer Workhorse Computing Chicago, IL 60647 +1 800 762 1582 |
From: Graham B. <gb...@po...> - 2001-12-11 18:59:18
|
On Tue, Dec 11, 2001 at 12:11:15PM -0600, le...@wr... wrote: > > > > if( my $newbase = $result->dn ) > > > > is clearer. That said, the following is definitely an issue: > > my @bindparmz = > > ( > > base => $newbase, > > password => $password, > > ); > > $bindresult = $ldh2->bind( @bindparmz); > > you should replace 'base' with 'dn' > > Looks like $result->dn returns nothing, though the > first key returned in the struct hash seems to be > a valid dn for the following query... I think you want $result->entry(0)->dn So that you get the DN of the first entry returned. Graham. |
From: <le...@wr...> - 2001-12-11 19:35:51
|
-- Graham Barr <gb...@po...> on 12/11/01 18:59:20 +0000 > $result->entry(0)->dn For a large number of entries with no attribues, is this going to be any faster than keys %{ $msg->as_struct }? The current task is to dump an entire database so that the users can locate their usernames... -- Steven Lembark 2930 W. Palmer Workhorse Computing Chicago, IL 60647 +1 800 762 1582 |
From: Graham B. <gb...@po...> - 2001-12-11 19:48:43
|
On Tue, Dec 11, 2001 at 01:34:09PM -0600, le...@wr... wrote: > > > -- Graham Barr <gb...@po...> on 12/11/01 18:59:20 +0000 > > > $result->entry(0)->dn > > For a large number of entries with no attribues, is > this going to be any faster than keys %{ $msg->as_struct }? Yes, because $msg->as_struct loops over the list and calls ->dn on each. as_struct is there only to aid people coming from using Mozilla::LDAP, it is not very efficient Graham. > > The current task is to dump an entire database so that the > users can locate their usernames... > > -- > Steven Lembark 2930 W. Palmer > Workhorse Computing Chicago, IL 60647 > +1 800 762 1582 > |