LDAP stands for Lightweight Directory Access Protocol. It is usually used to fetch (and sometimes update) data in a directory of people. For example the employees and students of a University.
For example, Active Directory, which is used in Microsoft Windows based networks to hold the accounts of all he users, provides a way to access it via LDAP.
Using Net::LDAP can provide a way to interact with this database. For example you might build an in-house web application and instead of managing your own user database, you could let the users authenticate using their username/password in the Windows network.
There are several publicly accessible LDAP servers you can use to check your code. We are going to use the one published by The University of Michigan.
Fetching Data from an LDAP server
#!/usr/bin/env perl
use strict;
use warnings;
use Net::LDAP;
my $server = "ldap.itd.umich.edu";
my $ldap = Net::LDAP->new( $server ) or die $@;
$ldap->bind;
my $result = $ldap->search(
base => "",
filter => "(&(cn=Jame*) (sn=Woodw*))",
);
die $result->error if $result->code;
printf "COUNT: %s\n", $result->count;
foreach my $entry ($result->entries) {
$entry->dump;
}
print "===============================================\n";
foreach my $entry ($result->entries) {
printf "%s <%s>\n",
$entry->get_value("displayName"),
($entry->get_value("mail") || '');
}
$ldap->unbind;
Running the above code will print:
COUNT: 2
------------------------------------------------------------------------
dn:uid=jrwood,ou=People,dc=umich,dc=edu
objectClass: umichPerson
top
person
inetOrgPerson
posixAccount
uid: jrwood
sn: Woodworth
cn: James R Woodworth
James Woodworth
uidNumber: 75786
gidNumber: 10
homeDirectory: /users/jrwood
RealtimeBlockList: TRUE
ou: Alumni
displayName: James R Woodworth
krbName: jrwood@umich.edu
------------------------------------------------------------------------
dn:uid=jwoodnh,ou=People,dc=umich,dc=edu
krbName: jwoodnh@umich.edu
uidNumber: 99417910
loginShell: /bin/csh
sn: Woodward
ou: Alumni
mail: jwoodnh@umich.edu
homeDirectory: /users/jwoodnh
RealtimeBlockList: TRUE
displayName: James Alan Woodward
uid: jwoodnh
gidNumber: 10
cn: James Alan Woodward
James A Woodward
James Woodward
objectClass: umichPerson
inetOrgPerson
organizationalPerson
person
top
posixAccount
===============================================
James R Woodworth <>
James Alan Woodward <jwoodnh@umich.edu>
First thing is to create a Net::LDAP object providing the name of the LDAP server. Then we call bind
. That is where we connect to the LDAP server.
In this example we used an anonymous connection. This usually only allows read access.
The search
method returns a Net::LDAP::Search object. (This is what gets assigned to the $result
variable.
The code
method of the Net::LDAP::Search object returns
Net::LDAP::Constant which is 0 on success.
(Like the exit code of a Unix shell command.) So the Perl code to check for failure is
if ($result->code) {
die $result->error;
}
Or if you prefer:
die $result->error if $result->code;
The example in the documentation uses the shell-style:
$result->code && die $result->error;
that I personally don't find very readable.
If the search was successful the count
method will return the number of hits.
The entries
method returns all the hits. Each one is a
Net::LDAP::Entry object.
In the first foreach
loop we just dump
the results for each entry. This is mostly
useful for debugging purposes, or when we try to explore what kind of fields does the server provide.
In the second foreach
loop we used the get_value
method to fetch specific fields
from the entry.
At the end of our interaction we unbind
(disconnect) from the LDAP server.
Admin limit exceeded
If we widen our search, for example by searching for sn=W*
instead of sn=Woodw*
:
my $result = $ldap->search(
base => "",
filter => "(&(cn=Jame*) (sn=W*))",
);
die $result->error if $result->code;
We will get an Admin limit exceeded
error code.
Bad filter
If we don't provide a filter
, or if it is formatted incorrectly, we get a
Bad filter
error code.