1Net::LDAP::FAQ(3)     User Contributed Perl Documentation    Net::LDAP::FAQ(3)
2
3
4

NAME

6       Net::LDAP::FAQ - Frequently Asked Questions about Net::LDAP
7

SYNOPSIS

9        perldoc Net::LDAP::FAQ
10

DESCRIPTION

12       This document serves to answer the most frequently asked questions on
13       both the perl-ldap Mailing List and those sent to Graham Barr.
14
15       The latest version of this FAQ can be found at
16
17        http://ldap.perl.org/FAQ.html
18

GENERAL

20   What is perl-ldap ?
21       perl-ldap is the distribution name. The perl-ldap distribution contains
22       the Net::LDAP modules.
23
24   Why another perl LDAP implementation ?
25       perl-ldap's goal is to be as portable as possible. It does this by
26       being implemented completely in perl. So basically anywhere that perl
27       runs perl-ldap will run. This is not true for other implementations
28       which require a C compiler.
29
30   Where can I get it ?
31       Perl-ldap is available from CPAN. You will find it in the
32       authors/id/GBARR directory. Alternatively you can download the latest
33       version from
34
35        http://www.cpan.org/search?dist=perl-ldap
36
37       WARNING:  The perl-ldap module is stored on CPAN as a *.gz file.
38       Netscape on Windows systems sometimes has a problem storing the module
39       with the correct name, it will replace the *.tar.gz with *_tar.tar.  To
40       correct the problem, with the pointer on the link, do a right click and
41       then select save link as to save the file with the correct file name.
42
43   Is there a web page for perl-ldap ?
44       Yes there is at http://ldap.perl.org/
45
46   Is there a mailing list ?
47       Yes there is at perl-ldap@perl.org
48
49       You can subscribe to this list by mailing perl-ldap-subscribe@perl.org
50
51   Is the mailing list archived ?
52       Yes, at http://nntp.perl.org/group/perl.ldap
53
54       Archives with messages before we switched to using perl.org can be
55       found at
56
57        http://marc.theaimsgroup.com/?l=perl-ldap-dev
58
59       There is also an archive of the perl-ldap mailing list at
60
61        http://www.xray.mpe.mpg.de/mailing-lists/perl-ldap/
62
63       which also has messages from before the move.
64
65   Is there any online documentation ?
66       Yes. perl-ldap has online documentation at
67
68        http://ldap.perl.org/
69
70       which will have the latest documentation available.
71
72   Is there a public CVS repository ?
73       No, but there is a public SVN repository at
74
75        http://svn.mutatus.co.uk
76
77   Can I get perl-ldap from the public SVN repository?
78       Yes, any one can pull perl-ldap from the public SVN repository on
79       perl.ldap.org.
80
81       There are several ways this can be done.
82
83       Web You can download it from CPAN by following the release link:
84
85           The 2 lines in the following example should be put together as one
86           continuous line.  Example;
87
88            http://search.cpan.org/CPAN/authors/id/G/GB/GBARR/perl-ldap-0.33.tar.gz
89
90           WARNING:  The perl-ldap module is stored on CPAN as a *.gz file.
91           Netscape on Windows systems sometimes has a problem storing the
92           module with the correct name, it will replace the *.tar.gz with
93           *_tar.tar.  To correct the problem, with the pointer on the link,
94           do a right click and then select save link as to save the file with
95           the correct file name.
96
97       SVN You can download latest development version of perl-ldap from
98           svn.mutatus.co.uk by executing a anonymous SVN "checkout" command.
99
100           The 2 lines in the following example should be put together as one
101           continuous line.  Example;
102
103            svn co http://svn.mutatus.co.uk/repos/perl-ldap/trunk
104
105       Web page
106           Most of the time there is a URL link on the perl-ldap home page on
107           ldap.perl.org that points to the latest released version of perl-
108           ldap.  Due to the fact that humans must update the web page to
109           point to a new release it sometimes does not get updated as quickly
110           as it should.
111
112           WARNING:  The perl-ldap module is stored on CPAN as a *.gz file.
113           Netscape on Windows systems sometimes has a problem storing the
114           module with the correct name, it will replace the *.tar.gz with
115           *_tar.tar.  To correct the problem, with the pointer on the link,
116           do a right click and then select save link as to save the file with
117           the correct file name.
118
119   What is SVN.
120       "SVN" is an abbreviation for "Subversion" (see
121       http://subversion.tigris.org).  Subversion is a "Source Control" or
122       "Revision Control" tool designed to keep track of source changes made
123       by groups of developers working on the same files, allowing them to
124       stay in sync with each other as each individual chooses.
125

LDAP AND DIRECTORY TERMINOLOGY.

127       In order to help the user understand the perl-ldap module better some
128       key LDAP terminology is defined here.
129
130   What is a directory.
131       A directory is a special purpose hierarchical database that usually
132       contains typed information such as text strings, binary data, or X.509
133       certificates.
134
135   What is LDAP.
136       LDAP stands for Lightweight Directory Access Protocol.  The word
137       Protocol is the key word in the definition given in the preceding
138       sentence, LDAP is NOT hardware or software.  It is a protocol that
139       defines how a client and server will communicate with one another.
140
141       The Lightweight Directory Access Protocol is defined in a series of
142       Requests For Comments, better known as RFCs. The RFCs can be found on
143       the Internet at http://www.ietf.org/ (the master repository) and many
144       other places. There's a link to all the LDAP-related RFCs at Perl-
145       LDAP's web site, http://ldap.perl.org/rfc.html. Some of the more
146       important RFC numbers are RFC 451i0 - 4519 for LDAP (previously called
147       LDAPv3) and the historic RFC 1777 for LDAPv2.
148
149   What is a LDAP Directory.
150       In the strictest terms of the definition there is no such thing as a
151       LDAP directory.  To be practical about this situation every day
152       directory professionals refer to their directory as " a LDAP directory"
153       because it is easy to say and it does convey the type of protocol used
154       to communicate with their directory.  Using this definition a LDAP
155       directory is a directory whose server software conforms to the
156       Lightweight Directory Access Protocol when communicating with a client.
157
158   What is an Entry.
159       The traditional directory definition of a directory object is called an
160       Entry. Entries are composed of attributes that contain the information
161       to be recorded about the object.
162
163       (An entry in LDAP is somewhat analogous to a record in a table in an
164       SQL database, but don't get too hung up about this analogy!)
165
166       Entries are held in an upside-down tree structure. Entries can
167       therefore contain subordinate entries, and entries must have one direct
168       superior entry.
169
170       Entries with subordinate entries are called 'non-leaf' entries.
171
172       Entries without subordinate entries are called 'leaf' entries.
173
174       An entry's direct superior entry is called the entry's 'parent'.
175
176       'Non-leaf' entries are also said to have 'child' entries.
177
178   What is an attribute.
179       The entry(s) in a directory are composed of attributes that contain
180       information about the object.  Each attribute has a type and can
181       contain one or more values.
182
183       For example:
184
185         cn=Road Runner
186
187       is an attribute with a type named "cn", and one value.
188
189       Each attribute is described by a 'syntax' which defines what kind of
190       information can be stored in the attributes values.  Trying to store a
191       value that doesn't conform to the attribute's syntax will result in an
192       error.
193
194       For example:
195
196         jpegPhoto=unknown
197
198       is not permitted by the directory, because jpegPhotos may only contain
199       JPEG-formatted images.
200
201       Most syntaxes used in LDAP however describe text strings rather than
202       binary objects (like JPEGs or certificates.)
203
204       In LDAPv3 most of these syntaxes support Unicode encoded using UTF-8.
205       Because the Net::LDAP modules do not change the strings that you pass
206       in as attribute values (they get sent to the LDAP server as-is) to use
207       accented characters you simply need to encode your strings in UTF-8.
208       There are modules on CPAN that will help you here.
209
210       Note that LDAPv2 servers used something called T.61 instead of Unicode
211       and UTF-8. Most servers do not implement T.61 correctly, and it is
212       recommended that you use LDAPv3 instead.
213
214       Attributes may also be searched.  The algorithms used to perform
215       different kinds of searches are described by the attribute's 'matching
216       rules'.  Some matching rules are case-sensitive and some are case-
217       insensitive, for example.  Sometimes matching rules aren't defined for
218       a particular attribute: there's no way to search for jpegPhotos that
219       contain a substring!
220
221       You can examine all of a server's attribute definitions by reading the
222       schema from the server.
223
224   What is an object class.
225       An object class is the name associated with a group of attributes that
226       must be present in an entry, and the group of attributes that may also
227       be present in an entry.
228
229       Object classes may be derived (subclassed) from other object classes.
230       For example the widely used 'inetOrgPerson' object class is derived
231       from 'organizationalPerson', which is itself derived from 'person'
232       which is itself derived from 'top'.
233
234       Every entry has an attribute called 'objectClass' that lists all the
235       names of object classes (and their superclasses) being used with the
236       entry.
237
238       You can examine all of a server's objectclass definitions by reading
239       the schema from the server.
240
241   What is a Distinguished Name (DN).
242       Every entry in a directory has a Distinguished Name, or DN.  It is a
243       unique Entry identifier throughout the complete directory.  No two
244       Entries can have the same DN within the same directory.
245
246       Examples of DNs:
247
248        cn=Road Runner, ou=bird, dc=cartoon, dc=com
249        ou=bird, dc=cartoon, dc=com
250        dc=cartoon, dc=com
251        dc=com
252
253   What is a Relative Distinguished Name.
254       Every DN is made up of a sequence of Relative Distinguished Names, or
255       RDNs.  The sequences of RDNs are separated by commas (,). In LDAPv2
256       semi-colons (;) were also allowed.  There can be more than one
257       identical RDN in a directory, but they must have different parent
258       entries.
259
260       Technically, an RDN contains attribute-value assertions, or AVAs. When
261       an AVA is written down, the attribute name is separated from the
262       attribute value with an equals (=) sign.
263
264       Example of a DN:
265
266        cn=Road Runner,ou=bird,dc=cartoon,dc=com
267
268        RDNs of the proceeding DN:
269        RDN => cn=Road Runner
270        RDN => ou=bird
271        RDN => dc=cartoon
272        RDN => dc=com
273
274       RDNs can contain multiple attributes, though this is somewhat unusual.
275       They are called multi-AVA RDNs, and each AVA is separated in the RDN
276       from the others with a plus sign (+).
277
278       Example of a DN with a multi-AVA RDN:
279
280        cn=Road Runner+l=Arizona,ou=bird,dc=cartoon,dc=com
281
282   Where is an entry's name held?
283       Entries do not contain their DN. When you retrieve an entry from a
284       search, the server will tell you the DN of each entry.
285
286       On the other hand, entries do contain their RDN. Recall that the RDN is
287       formed from one or more attribute-value assertions (AVAs); each entry
288       must contain all the attributes and values in the RDN.
289
290       For example the entry:
291
292        cn=Road Runner+l=Arizona,ou=bird,dc=cartoon,dc=com
293
294       must contain a 'cn' attribute containing at least the value "Road
295       Runner", and an 'l' attribute containing at least the value "Arizona".
296
297       The attributes used in the RDN may contain additional values, but the
298       entry still only has one DN.
299
300   What is a search base.
301       A search base is a Distinguished Name that is the starting point of
302       search queries.
303
304       Example of a DN:
305
306        cn=Road Runner,ou=bird,dc=cartoon,dc=com
307
308       Possible search base(s) for the proceeding DN:
309
310        Base => cn=Road Runner,ou=bird,dc=cartoon,dc=com
311        Base => ou=bird,dc=cartoon,dc=com
312        Base => dc=cartoon,dc=com
313        Base => dc=com
314
315       Setting the search base to the lowest possible branch of the directory
316       will speed up searches considerably.
317
318   What is the difference between a LDAP server and a relational database.
319       The most basic difference is that a directory server is  a specialized
320       database designed to provide fast searches. While a relational database
321       is optimized for transactions (where a series of operations is counted
322       as 1, thus if one of the steps fails, the RDBMS can roll-back to the
323       state it was in before you started).
324
325       Directories also typically are hierarchical in nature (RDBMS is
326       typically flat, but you can implement a hierarchy using tables and
327       queries), networkable, distributed and replicated.
328
329       LDAP provides an open-standard to a directory service.
330
331       Typically we use LDAP for email directories (all popular email clients
332       provide an LDAP client now) and authorization services (authentication
333       and access control).
334
335       You could use a RDBMS for these types of queries but there's no set
336       standard, in particular over TCP/IP to connect to databases over the
337       network. There's language specific protocols (like Perl's DBI and
338       Java's JDBC) that hide this problem behind an API abstraction, but
339       that's not a replacement for a standard access protocol.
340
341       LDAP is starting to be used on roles traditionally played by RDBMS in
342       terms of general data management because it's easier to setup a LDAP
343       server (once you understand the basic nomenclature) and you don't need
344       a DBA to write your queries and more importantly all LDAP servers speak
345       the same essential protocol, thus you don't have to fuss with a
346       database driver trying to connect it to the Internet. Once you have an
347       LDAP server up and running, it's automatically available over the 'net.
348       It's possible to connect to a LDAP server from a variety of mechanisms,
349       including just about every possible programming language.
350
351       More information on this topic can be found on the following URLs;
352
353        http://www.openldap.org/faq/data/cache/378.html
354
355        http://www.isode.com/whitepapers/ic-6055.html
356
357   What is the difference between a ldap reference and a ldap referral?
358       A referral is returned when the entire operation must be resent to
359       another server.
360
361       A continuation reference is returned when part of the operation must be
362       resent to another server.
363
364       See RFC 2251 section 4.5.3 for more details.
365

PERL-LDAP INSTALLATION

367   How do I install perl-ldap ?
368       To install the modules that are in the perl-ldap distribution follow
369       the same steps that you would for most other distributions found on
370       CPAN, that is
371
372          # replace 0.33 with the version you have
373
374          gunzip perl-ldap-0.33.tar.gz
375          tar xvf perl-ldap-0.33.tar
376          cd perl-ldap-0.33
377
378          perl Makefile.PL
379          make
380          make test
381          make install
382
383   But I do not have make, how can I install perl-ldap ?
384       Well as luck would have it the modules in perl-ldap do not do anything
385       complex, so a simple copy is enough to install. First run
386
387         perl -V
388
389       This will output information about the version of perl you have
390       installed. Near the bottom you will find something like
391
392         @INC:
393           /usr/local/perl/perl5.005/lib/5.00502/sun4-solaris
394           /usr/local/perl/perl5.005/lib/5.00502
395           /usr/local/perl/perl5.005/lib/site_perl/5.005/sun4-solaris
396           /usr/local/perl/perl5.005/lib/site_perl/5.005
397           .
398
399       This is a list of directories that perl searches when it is looking for
400       a module. The directory you need is the site_perl directory, but
401       without the system architecture name, in this case it is
402       "/usr/local/perl/perl5.005/lib/site_perl/5.005". The files required can
403       then be installed with
404
405          # replace 0.33 with the version you have
406
407          gunzip perl-ldap-0.33.tar.gz
408          tar xvf perl-ldap-0.33.tar
409          cd perl-ldap-0.33/lib
410
411          cp * /usr/local/perl/perl5.005/lib/site_perl/5.005
412
413   How can I load Perl-LDAP into an ActiveState Perl installation.
414       There are several ways that Perl-LDAP can be installed into an
415       ActiveState Perl tree.
416
417       1.  The ActiveState ppm command can be used to install Perl-LDAP.  When
418           a new version of Perl-LDAP is released, it takes ActiveState a
419           period of time to get the new release into the ActiveState ppm
420           system.
421
422       2.  If the user has nmake installed, the user can do a normal perl
423           module install using nmake instead of make.
424
425       3.  If the user does not have nmake or make, the user can install Perl-
426           LDAP using the install-nomake script by issuing the following
427           command.
428
429            perl install-nomake
430
431           The install-nomake script can be used on any system that does not
432           have make installed.
433
434   What other modules will I need ?
435       perl-ldap does use other modules. Some are required, but some are
436       optional (i.e. required to use certain features)
437
438       Convert::ASN1
439           This module is required for perl-ldap to work.
440
441           You can obtain the latest release from
442             http://search.cpan.org/search?module=Convert::ASN1
443
444       Authen::SASL
445           This module is optional.  You only need to install Authen::SASL if
446           you want to use the SASL authentication method.
447
448           You can obtain the latest release from
449             http://search.cpan.org/search?module=Authen::SASL
450
451       Digest::MD5
452           This module is optional. It also requires a C compiler when
453           installing.  You only need to install Digest::MD5 if you want to
454           use the SASL DIGEST-MD5 authentication method.
455
456           You can obtain the latest release from
457             http://search.cpan.org/search?module=Digest::MD5
458
459       URI::ldap
460           This module is optional. You only need to install URI::ldap if you
461           are going to need to parse ldap referrals. Net::LDAP does not do
462           this automatically yet, so this module is not used by perl-ldap.
463
464           You can obtain the latest release from
465             http://search.cpan.org/search?module=URI::ldap
466
467       OpenSSL and IO::Socket::SSL for Net::LDAPS
468           If you want to use Net::LDAP::LDAPS you will need this module and
469           the OpenSSL software package.
470
471           You can obtain the latest release of IO::Socket::SSL from
472             http://search.cpan.org/search?module=IO::Socket::SSL
473
474           You can obtain the latest release of OpenSSL from
475             http://www.openssl.org/
476
477           If you are using a Linux system, many of the distributions have RPM
478           packages that you can install.  Use your favorite web search engine
479           to find the package that you need.
480
481       XML::SAX and XML::SAX::Writer
482           If you want to use Net::LDAP::DSML you will need these modules.
483
484           You can obtain the latest releases from
485             http://search.cpan.org/search?module=XML::SAX
486             http://search.cpan.org/search?module=XML::SAX::Writer
487
488       ResourcePool::Factory::Net::LDAP
489           If you want to use failover the ResourcePool::Factory::Net::LDAP
490           perl module provides methods to do this.
491
492           You can obtain the latest release from
493             http://search.cpan.org/search?module=ResourcePool::Factory::Net::LDAP
494

USING NET::LDAP

496   How do I connect to my server ?
497       The connection to the server is created when you create a new Net::LDAP
498       object, e.g.
499
500         $ldap = Net::LDAP->new($server);
501
502   Net::LDAP->new sometimes returns undef, why ?
503       The constructor will return undef if there was a problem connecting to
504       the specified server. Any error message will be available in $@
505
506   What is the proper format of the bind DN.
507       The DN used to bind to a directory is a FULLY QUALIFIED DN.  The exact
508       structure of the DN will depend on what data has been stored in the
509       server.
510
511       The following are valid examples.
512
513         uid=clif,ou=People,dc=umich,dc=edu
514
515         cn=directory manager,ou=admins,dc=umich,dc=edu
516
517       In some servers the following would be a valid fully qualified DN of
518       the directory manager.
519
520         cn=directory manager
521
522   How can I tell when the server returns an error, bind() always returns true
523       ?
524       Most methods in Net::LDAP return a Net::LDAP::Message object, or a sub-
525       class of that. This object will hold the results from the server,
526       including the result code.
527
528       So, for example, to determine the result of the bind operation.
529
530         $mesg = $ldap->bind( $dn, password => $passwd );
531
532         if ( $mesg->code ) {
533           # Handle error codes here
534         }
535
536   How can I set the LDAP version of a connection to my ldap server?
537       This is done by adding the version option when connecting or binding to
538       the LDAP server.
539
540       For example;
541
542         $ldap = Net::LDAP->new( $server, version => 3 );
543
544       or
545
546         $mesg = $ldap->bind( $dn, password => $passwd, version => 3 );
547
548       Valid version numbers are 2 and 3.  As of perl-ldap 0.27 the default
549       LDAP version is 3.
550
551   I did a search on my directory using the 'search' method. Where did the
552       results go ?
553       Your search results are stored in a 'search object'.  Consider the
554       following:
555
556        use Net::LDAP;
557
558        $ldap = Net::LDAP->new('ldap.acme.com') or die "$@";
559        $mesg = $ldap->search(
560                              base   => "o=acme.com",
561                              filter => "uid=jsmith",
562                             );
563
564       $mesg is a search object. It is a reference blessed into the
565       Net::LDAP::Search package. By calling methods on this object you can
566       obtain information about the result and also the individual entries.
567
568       The first thing to check is if the search was successful. This is done
569       with with the method $mesg->code. This method will return the status
570       code that the server returned. A success will yield a zero value, but
571       there are other values, some of which could also be considered a
572       success.  See Net::LDAP::Constant
573
574         use Net::LDAP::Util qw(ldap_error_text);
575
576         die ldap_error_text($mesg->code)
577           if $mesg->code;
578
579       There are two ways in which you can access the entries. You can access
580       then with an index or you can treat the container like a stack and
581       shift each entry in turn. For example
582
583         # as an array
584
585         # How many entries were returned from the search
586         my $max = $mesg->count;
587
588         for( my $index = 0 ; $index < $max ; $index++) {
589           my $entry = $mesg->entry($index);
590           # ...
591         }
592
593         # or as a stack
594
595         while( my $entry = $mesg->shift_entry) {
596           # ...
597         }
598
599       In each case $entry is an entry object. It is a reference blessed into
600       the Net::LDAP::Entry package. By calling methods on this object you can
601       obtain information about the entry.
602
603       For example, to obtain the DN for the entry
604
605         $dn = $entry->dn;
606
607       To obtain the attributes that a given entry has
608
609         @attrs = $entry->attributes;
610
611       And to get the list of values for a given attribute
612
613         @values = $entry->get( 'sn' );
614
615       And to get the first of the values for a given attribute
616
617         $values = $entry->get( 'cn' );
618
619       One thing to remember is that attribute names are case insensitive, so
620       'sn', 'Sn', 'sN' and 'SN' are all the same.
621
622       So, if you want to print all the values for the attribute 'ou' then
623       this is as simple as
624
625         foreach ($entry->get_value( 'ou' )) {
626             print $_,"\n";
627           }
628
629       Now if you just want to print all the values for all the attributes you
630       can do
631
632         foreach my $attr ($entry->attributes) {
633           foreach my $value ($entry->get_value($attr)) {
634             print $attr, ": ", $value, "\n";
635           }
636         }
637
638   How do I limit the scope of a directory search.
639       You limit the scope of a directory search by setting the scope
640       parameter of search request.  Consider the following:
641
642        use Net::LDAP;
643
644        $ldap = Net::LDAP->new('ldap.acme.com') or die "$@";
645        $mesg = $ldap->search(
646                              base   => "o=acme.com",
647                              scope  => 'sub',
648                              filter => "uid=jsmith",
649                             );
650
651       Values for the scope parameter are as follows.
652
653       base
654           Search only the base object.
655
656       one Search the entries immediately below the base object.
657
658       sub Search the whole tree below the base object.  This is the default.
659

GETTING SEARCH RESULTS

661       There are two ways of retrieving the results of a requested LDAP
662       search; inline and by using a callback subroutine.
663
664   USING THE INLINE APPROACH
665       Using the inline approach involves requesting the data and then waiting
666       for all of the data to be returned before the user starts processing
667       the data.
668
669       Example:
670
671        use Net::LDAP;
672
673        $ldap = Net::LDAP->new('ldap.acme.com') or die "$@";
674        $mesg = $ldap->search(
675                              base   => "o=acme.com",
676                              scope  => 'sub',
677                              filter => "sn=smith",
678                             );
679         #
680         # At this point the user can get the returned data as an array
681         # or as a stack.
682         # In this example we will use an array
683
684         # How many entries were returned from the search
685         my $max = $mesg->count;
686
687         for( my $index = 0 ; $index < $max ; $index++)
688         {
689           my $entry = $mesg->entry($index);
690           my $dn = $entry->dn; # Obtain DN of this entry
691
692           @attrs = $entry->attributes; # Obtain attributes for this entry.
693           foreach my $var (@attrs)
694           {
695            #get a list of values for a given attribute
696            $attr = $entry->get_value( $var, asref => 1 );
697            if ( defined($attr) )
698            {
699                foreach my $value ( @$attr )
700                {
701                 print "$var: $value\n";  # Print each value for the attribute.
702                }
703            }
704           }
705         }
706
707       As you can see the example is straight forward, but there is one
708       drawback to this approach.  You must wait until all entries for the
709       request search to be returned before you can process the data.  If
710       there several thousand entries that match the search filter this could
711       take quite a long time period.
712
713   USING THE CALLBACK SUBROUTINE APPROACH
714       Using the callback approach involves requesting the data be sent to a
715       callback subroutine as each entry arrives at the client.
716
717       A callback is just a subroutine that is passed two parameters when it
718       is called, the mesg and entry objects.
719
720       Example:
721
722        use Net::LDAP;
723
724        $ldap = Net::LDAP->new('ldap.acme.com') or die "$@";
725        $mesg = $ldap->search(
726                              base   => "o=acme.com",
727                              scope  => 'sub',
728                              filter => "sn=smith",
729                              callback => \&callback,
730                             );
731        #
732        # At this point the user needs to check the status of the
733        # ldap search.
734        #
735
736        if ( $mesg->code )
737        {
738           $errstr = $mesg->code;
739           print "Error code:  $errstr\n";
740           $errstr = ldap_error_text($errstr);
741           print "$errstr\n";
742        }
743
744
745        sub callback
746        {
747        my ( $mesg, $entry) = @_;
748
749          #
750          # First you must check to see if something was returned.
751          # Last execution of callback subroutine will have no
752          # defined entry and mesg object
753          #
754          if ( !defined($entry) )
755          {
756            print "No records found matching filter $match.\n"
757            if ($mesg->count == 0) ; # if mesg is not defined nothing will print.
758            return;
759          }
760
761          my $dn = $entry->dn; # Obtain DN of this entry
762
763          @attrs = $entry->attributes; # Obtain attributes for this entry.
764          foreach my $var (@attrs)
765          {
766           #get a list of values for a given attribute
767           $attr = $entry->get_value( $var, asref => 1 );
768           if ( defined($attr) )
769           {
770             foreach my $value ( @$attr )
771             {
772               print "$var: $value\n";  # Print each value for the attribute.
773             }
774           }
775          }
776          #
777          # For large search requests the following 2 lines of code
778          # may be very important, they will reduce the amount of memory
779          # used by the search results.
780          #
781          # If the user is not worried about memory usage then the 2 lines
782          # of code can be omitted.
783          #
784          $mesg->pop_entry;
785
786        }  # End of callback subroutine
787
788       As you can see the example is straight forward and it does not waste
789       time waiting for all of the entries to be returned.  However if the
790       pop_entry method is not used the callback approach can allocate a lot
791       of memory to the search request.
792

USING NET::LDAPS

794   Using an SSL network connection, how do I connect to my server?
795       This class is a subclass of Net::LDAP so all the normal Net::LDAP
796       methods can be used with a Net::LDAPS object; see the documentation for
797       Net::LDAP to find out how to query a directory server using the LDAP
798       protocol.
799
800       The connection to the server is created when you create a new
801       Net::LDAPS object, e.g.
802
803         $ldaps = Net::LDAPS->new($server,
804                                  port => '10000',
805                                  verify => 'require',
806                                  capath => '/usr/local/cacerts/',
807                                  );
808
809       Starting with version 0.28 perl-ldap also supports URIs in the new
810       method.  So, the above can also be expressed as:
811
812         $ldaps = Net::LDAP->new("ldaps://$server",
813                                  port => '10000',
814                                  verify => 'require',
815                                  capath => '/usr/local/cacerts/',
816                                  );
817
818       There are additional options to the new method with LDAPS URIs and the
819       LDAPS new method and several additional methods are included in the
820       LDAPS object class.
821
822       For further information and code examples read the LDAPS module
823       documentation;  perldoc Net::LDAPS
824

USING LDAP GROUPS.

826   What are LDAP groups.
827       LDAP groups are object classes that contain an attribute that can store
828       multiple DN values.  Two standard object classes are 'groupOfNames'
829       (which has a 'member' attribute) and 'groupOfUniqueNames' (which has a
830       'uniqueMember' attribute.)
831
832       According to the RFCs a group can be a member of another group, but
833       some LDAP server vendors restrict this flexibility by not allowing
834       nested groups in their servers.
835
836       Two scripts for working with groups are available in the contrib
837       directory.  They are isMember.pl and printMembers.pl.
838
839   How do you format a filter to search for entries whose 'member' attribute
840       has a particular value?
841       Asking for (member=*) is OK - the directory uses the equality matching
842       rule which is defined for the member attribute.
843
844       Asking for (member=c*) is not OK - there is no defined substring
845       matching rule for the member attribute. That's because the member
846       values are *not* strings, but distinguished names. There is no
847       substring matching rule for DNs, see RFC 2256 section 5.50.
848
849       What you have to do is get the results of (member=*) and then select
850       the required results from the returned values. You need to do this
851       using knowledge of the string representation of DNs defined in RFC
852       2253, which is important because the same DN can have different string
853       representations. So you need to perform some canonicalization if you
854       want to be correct.
855

USING DSML.

857   How can I access DSML features from PERL-LDAP.
858       Directory Service Markup Language (DSML) is the XML standard for
859       representing directory service information in XML.
860
861       Support for DSML is included in PERL-LDAP starting with version .20.
862
863       At the moment this module only reads and writes DSML entry entities. It
864       cannot process any schema entities because schema entities are
865       processed differently than elements.
866
867       Eventually this module will be a full level 2 consumer and producer
868       enabling you to give you full DSML conformance.
869
870       The specification for DSML is at http://www.oasis-open.org/specs/
871
872       For further information and code examples read the DSML module
873       documentation;  perldoc Net::LDAP::DSML
874

USING CONTROLS AND VIRTUAL LISTS.

876   How do I access the Control features.
877       Support for LDAP version 3 Control objects is included in perl-ldap
878       starting with version .20.
879
880       For further information and code examples read the Control module
881       documentation;  perldoc Net::LDAP::Control
882
883   How do I access the Virtual List features.
884       Support for Virtual Lists is included in perl-ldap starting with
885       version .20.
886
887       For further information and code examples read the Control module
888       documentation;  perldoc Net::LDAP::Control
889

GENERAL QUESTIONS.

891   Are there any other code examples.
892       Yes, there is an Examples pod file.  To view the pod do the following
893       command;  perldoc Net::LDAP::Examples
894
895       There is user contributed software in the contrib directory that is
896       supplied with the PERL-LDAP distribution.  This is an excellent source
897       of information on how to use the PERL-LDAP module.
898
899   Are there any performance issues with perl-ldap ?
900       In the vast majority of use cases (one user has suggested 9 out of 10)
901       there are no performance issues with perl-ldap.
902
903       Where you may wish to use perl-ldap to perform, for example, a very
904       large number of queries (e.g. 10,000) in succession you may find a
905       noticeable performance difference between perl-ldap and non pure-perl
906       modules. This is not because of perl-ldap itself but because of the
907       pure-perl Convert::ASN1 module that it depends on.
908
909       You should make up your own mind, based upon your own situation
910       (performance requirements, hardware etc.) as to whether you should use
911       perl-ldap or not. The figures quoted in this answer are only
912       indicative, and will differ for different people.
913
914   Can I contribute perl scripts that use perl-ldap to the contrib section?
915       Any one can submit a perl script that uses perl-ldap for inclusion in
916       the contrib section.  Graham Barr will determine if the script will be
917       included and will do the initial check in of the script to the SVN
918       system on http://svn.mutatus.co.uk.  Graham will make you the
919       owner/developer of the script.
920
921       There are a couple of requirements for consideration.
922
923       You must supply a one line description of your script to be included in
924       the contrib readme file.
925
926       Inside the script will be the pod documentation for the script.  No
927       auxiliary documentation will be allowed.  For examples of how to do
928       this see the tklkup script currently in the contrib section.
929
930   Is it possible to get a complete entry, DN and attributes without
931       specifying the attributes name?
932       Yes, just specify you want a list of no attributes back. The RFC says
933       that this tells the server to return all readable attributes back
934       (there may be access controls to prevent some from being returned.)
935
936       So in the search method, just set (for LDAPv2):
937
938                       attrs => [ ]
939
940       If you are using LDAPv3, you can specify an attribute called "*"
941       instead, which lets you ask for additional (i.g. operational)
942       attributes in the same search.
943
944                       attrs => [ "*" ]
945
946       To get all operational attributes in a search, some servers allow the
947       use of the "+" pseudo attribute. So that with these servers
948
949                       attrs => [ "*", "+" ]
950
951       will return the most information from the server.
952
953   How do I put a JPEG photo into a entry in the directory.
954       Follow the following code example, replacing the (...) with whatever is
955       relevant to your setup.
956
957         use Net::LDAP;
958         use Net::LDAP::Util qw(ldap_error_text);
959         use CGI;
960
961         local $/ = undef;
962         my $jpeg = <$filename>;
963
964         my $ldap = Net::LDAP->new(...);
965         my $res = $ldap->bind(...);
966            $res = $ldap->modify(...,
967                          add => [ 'jpegPhoto' => [ $jpeg ] ]);
968            $res = $ldap->unbind();
969
970   How do I add a jpeg photo into a entry in the directory via html-forms.
971       Follow the following code example, replacing the (...) with whatever is
972       relevant to your setup.
973
974         use Net::LDAP;
975         use Net::LDAP::Util qw(ldap_error_text);
976         use CGI;
977
978         my $q = new CGI;
979
980         print $q->header;
981         print $q->start_html(-title => 'Change JPEG photo');
982
983         if ($q->param('Update')) {
984                 my $filename = $q->param('jpeg');
985                 local $/ = undef;
986                 my $jpeg = <$filename>;
987
988                 my $ldap = Net::LDAP->new(...);
989                 my $res = $ldap->bind(...);
990                 $res = $ldap->modify(...,
991                                 add => [ 'jpegPhoto' => [ $jpeg ] ]);
992                 $res = $ldap->unbind();
993         } else {
994                 print $q->start_multipart_form();
995                 print $q->filefield(-name => 'jpeg', -size => 50);
996                 print $q->submit('Update');
997                 print $q->end_form();
998         }
999
1000         print $q->end_html();
1001
1002   What happens when you delete an attribute that does not exist.
1003       It is an error to delete an attribute that doesn't exist.  When you get
1004       the error back the server ignores the entire modify operation you sent
1005       it, so you need to make sure the error doesn't happen.
1006
1007       Another approach, if you are using LDAPv3 (note beginning with version
1008       .27 Net::LDAP uses LDAPv3 by default) is to use a 'replace' with your
1009       attribute name and no values.  In LDAPv3, this is defined to always
1010       work even if that attribute doesn't exist in the entry.
1011
1012       i.e.:
1013
1014         my $mesg = $ldap->modify( $entry, replace => { %qv_del_arry } );
1015
1016       But make sure you are using LDAPv3, because that is defined to not work
1017       in LDAPv2. (A nice incompatibility between LDAPv2 and LDAPv3.)
1018
1019   How can I delete a referral from an LDAP tree.
1020       Since this is a proprietary feature, you will have to check your
1021       server's documentation. You might find that you need to use a control.
1022       If there is a control called something like managedsait, that's the one
1023       you should probably use.  For proper operation you will need the oid
1024       number for managedsait; 2.16.840.1.113730.3.4.2 and do not specify a
1025       value for type.
1026
1027       The code required will look similar to the following code snippet.
1028
1029         $mesg =  $ldap->delete("ref=\"ldap://acme/c=us,o=bricks\",o=clay",
1030                         control => {type => "2.16.840.1.113730.3.4.2"} );
1031
1032   How do I add an ACI/ACL entry to a directory server with Perl-LDAP.
1033       ACIs and ACLs are proprietary features in LDAP. The following code
1034       snippet works with a Netscape directory server. You will need the
1035       specify the correct DN (-DN-) and correct attribute(s) (-nom attr-).
1036
1037         my $aci = '(target="ldap:///-DN-")(targetattr="-nom attr-")(version 3.0;
1038                     acl "-nom acl-"; deny(all) userdn = "ldap:///self";)' ;
1039
1040         $ldap->modify($dn_modif, add => {'aci' => $aci });
1041
1042   How do I avoid file type and data type mis-matching when loading data from
1043       a Win32 system.
1044       When loading a binary attribute with data read from a file on a Win32
1045       system, it has been noted that you should set "binmode" on the file
1046       before reading the file contents into the data array.
1047
1048       Another possible solution to this problem is to convert the binary data
1049       into a base64 encoded string and then store the encoded string in the
1050       file.  Then when reading the file, decode the base64 encoded string
1051       back to binary and then use perl ldap to store the data in the
1052       directory.
1053
1054   How do I create a Microsoft Exchange 5.x user.
1055       This is a solution provide by a perl-ldap user.
1056
1057       This code works with ActiveState Perl running on WinNT 4. Please note
1058       that this requires the Win32::Perms module, and needs valid NT account
1059       info to replace the placeholders.
1060
1061         use Net::LDAP;
1062         use Net::LDAP::Util;
1063         use Win32::Perms;
1064
1065         #Constants taken from ADSI Type Library
1066         $ADS_RIGHT_EXCH_ADD_CHILD = 1;
1067         $ADS_RIGHT_EXCH_DELETE = 0x10000;
1068         $ADS_RIGHT_EXCH_DS_REPLICATION = 64;
1069         $ADS_RIGHT_EXCH_DS_SEARCH = 256;
1070         $ADS_RIGHT_EXCH_MAIL_ADMIN_AS = 32;
1071         $ADS_RIGHT_EXCH_MAIL_RECEIVE_AS = 16;
1072         $ADS_RIGHT_EXCH_MAIL_SEND_AS = 8;
1073         $ADS_RIGHT_EXCH_MODIFY_ADMIN_ATT = 4;
1074         $ADS_RIGHT_EXCH_MODIFY_SEC_ATT = 128;
1075         $ADS_RIGHT_EXCH_MODIFY_USER_ATT = 2;
1076
1077         $EXCH_USER_RIGHTS = $ADS_RIGHT_EXCH_MAIL_RECEIVE_AS |
1078         $ADS_RIGHT_EXCH_MAIL_SEND_AS |
1079         $ADS_RIGHT_EXCH_MODIFY_USER_ATT;
1080
1081         $exch = Net::LDAP->new('server', debug =>0) || die $@;
1082
1083         $exch->bind( 'cn=admin_user,cn=nt_domain,cn=admin', version =>3,
1084         password=>'password');
1085
1086         $myObj = Win32::Perms->new();
1087         $Result = $myObj->Owner('nt_domain\user_name');
1088         $myObj->Group('nt_domain\Everyone');
1089         $myObj->Allow('nt_domain\user_name',
1090         $EXCH_USER_RIGHTS,OBJECT_INHERIT_ACE);
1091         $BinarySD = $myObj->GetSD(SD_RELATIVE);
1092         $TextSD = uc(unpack( "H*", $BinarySD ));
1093         Win32::Perms::ResolveSid('nt_domain\user_name', $sid);
1094         $mysid = uc(unpack("H*",$sid));
1095
1096         $result = $exch->add ( dn   =>
1097                       'cn=user_name,cn=container,ou=site,o=organization',
1098                       attr => [ 'objectClass' => ['organizationalPerson'],
1099                                 'cn'   => 'directory_name',
1100                                 'uid' => 'mail_nickname',
1101                                 'mail' => 'smtp_address',
1102                               'assoc-nt-account' => [ $mysid ],
1103                               'nt-security-descriptor' => [ $TextSD ],
1104                               'mailPreferenceOption'  => 0
1105                               ]
1106                     );
1107
1108
1109         print ldap_error_name($result->code);
1110
1111   Ho do I reset a user's password ...
1112       ... in most LDAP servers ?
1113
1114       Most LDAP servers use the standard userPassword attribute as the
1115       attribute to set when you want to change a user's password.
1116
1117       They usually allow to set the password either using the regular modify
1118       operation on the userPassword attribute or using the extended LDAP
1119       Password Modify operation defined in RFC3062.
1120
1121       The recommended method is the extended Password Modify operation, which
1122       offers a standardized way to set user passwords but unfortunately is
1123       not available on all LDAP servers.
1124
1125       Whether the extended Password Modify operation is available can be
1126       found out by searching the attribute supportedExtension for the value
1127       1.3.6.1.4.1.4203.1.11.1 in the RootDSE object.
1128
1129       If the extended Password Modify operation is not available the
1130       alternative is the regular modification of the userPassword attribute.
1131
1132       But this method has some drawbacks:
1133
1134       ·   Depending on the type of the server the arguments to the modify
1135           operations may vary. Some want the modify done with replace, some
1136           want it done by explicitly deleting the old password and add of the
1137           new one.  This may even depend on whether you change the password
1138           for the bound user or as an administrator for another user.
1139
1140       ·   With the modify operation some servers expect the client to do the
1141           hashing of the password on the client side. I.e. all clients that
1142           set passwords need to agree on the algorithm and the format of the
1143           hashed password.
1144
1145       ·   Some LDAP servers do not allow setting the password if the
1146           connection is not sufficiently secured. I.e. require SSL or TLS
1147           support to set the password (which is heavily recommended anyway
1148           ;-)
1149
1150       Here is an example of how to change your own password (for brevity's
1151       sake error checking is left out):
1152
1153         use Net::LDAP;
1154
1155         my $ldap = Net::LDAP->new('ldaps://server.domain')  or  die "$@";
1156         my $mesg = $ldap->bind('cn=Joe User,dc=perl,dc=ldap,dc=org',
1157                                password => 'oldPW');
1158
1159         my $rootdse = $ldap->root_dse();
1160
1161         if ($rootdse->supported_extension('1.3.6.1.4.1.4203.1.11.1') {
1162
1163             require Net::LDAP::Extension::SetPassword;
1164
1165             $mesg = $ldap->set_password(user => 'cn=Joe User,dc=perl,dc=ldap,dc=org',
1166                                         oldpasswd => 'oldPW',
1167                                         newpasswd => 'newPW');
1168         }
1169         else {
1170             $mesg = $ldap->modify('cn=Joe User,dc=perl,dc=ldap,dc=org',
1171                                   changes => [
1172                                       delete => [ userPassword => $oldPW ]
1173                                       add    => [ userPassword => $newPW ] ]);
1174         }
1175
1176         $ldap->unbind();
1177
1178       ... in MS Active Directory ?
1179
1180       With Active Directory a user's password is stored in the unicodePwd
1181       attribute and changed using the regular modify operation.
1182
1183       ADS expects this password to be encoded in Unicode - UTF-16 to be
1184       exact.  Before the unicode conversion is done the password needs to be
1185       surrounded by double quotes which do not belong to the user's password.
1186
1187       For the password modify operation to succeed SSL is required.
1188
1189       When changing the password for the user bound to the directory ADS
1190       expects it to be done by deleting the old password and adding the new
1191       one.  When doing it as a user with administrative privileges replacing
1192       the unicodePwd's value with a new one is allowed too.
1193
1194       Here's an example that demonstrates setting your own password (again
1195       almost no error checking):
1196
1197         use Net::LDAP;
1198         use Unicode::Map8;
1199         use Unicode::String qw(utf16);
1200
1201         # build the conversion map from your local character set to Unicode
1202         my $charmap = Unicode::Map8->new('latin1')  or  die;
1203
1204         # surround the PW with double quotes and convert it to UTF-16
1205         # byteswap() was necessary in experiments on i386 Linux, YMMV
1206         my $oldUniPW = $charmap->tou('"'.$oldPW.'"')->byteswap()->utf16();
1207         my $newUniPW = $charmap->tou('"'.$newPW.'"')->byteswap()->utf16();
1208
1209         my $ldap = Net::LDAP->new('ldaps://ads.domain.controller')  or  die "$@";
1210
1211         my $mesg = $ldap->bind('cn=Joe User,dc=your,dc=ads,dc=domain',
1212                                password => 'oldPW');
1213
1214         $mesg = $ldap->modify('cn=Joe User,dc=your,dc=ads,dc=domain',
1215                               changes => [
1216                                   delete => [ unicodePwd => $oldUniPW ]
1217                                   add    => [ unicodePwd => $newUniPW ] ]);
1218
1219         $ldap->unbind();
1220
1221   How can I simulate server failover.
1222       Perl-LDAP does not do server failover, however there are several
1223       programming options for getting around this situation.
1224
1225       Here is one possible solution.
1226
1227         unless ( $ldaps =
1228                   Net::LDAPS->new($ldapserverone,
1229                                   port=>636,timeout=>5) )
1230                 {
1231                     $ldaps = Net::LDAPS->new($ldapservertwo,
1232                                              port=>636,timeout=>20) ||
1233                     return
1234                     "Can't connect to $ldapserverone or $ldapservertwo via LDAPS: $@";
1235                 }
1236
1237       As of version 0.27 of perl-ldap the above can be expressed much
1238       simpler:
1239
1240         $ldaps = Net::LDAPS->new([ $ldapserverone, $ldapservertwo ],
1241                                  port=>636, timeout=>5)  or  die "$@";
1242

Using X.509 certificates.

1244   How do I store X.509 certificates in the directory?
1245       The first problem here is that there are many different formats to hold
1246       certificates in, for example PEM, DER, PKCS#7 and PKCS#12. The
1247       directory only uses the DER format (more correctly, it only uses the
1248       BER format) which is a binary format.
1249
1250       Your first job is to ensure that your certificates are therefore in
1251       DER/BER format. You could use OpenSSL to convert from PEM like this:
1252
1253         openssl x509 -inform PEM -in cert.pem -outform DER -out cert.der
1254
1255       Consult the OpenSSL documentation to find out how to perform other
1256       conversions.
1257
1258       To add a certificate to the directory, just slurp in the DER/BER
1259       certificate into a scalar variable, and add it to the entry's
1260       userCertificate attribute. How you do that will depend on which version
1261       of LDAP you are using.
1262
1263       To slurp in the certificate try something like this:
1264
1265         my $cert;
1266         {
1267             local $/ = undef; # Slurp mode
1268             open CERT, "cert.der" or die;
1269             binmode CERT;
1270             $cert = <CERT>;
1271             close CERT;
1272         }
1273         # The certificate is now in $cert
1274
1275       For LDAPv2, because most directory vendors ignore the string
1276       representation of certificates defined in RFC 1778, you should add this
1277       value to the directory like this:
1278
1279         $res = $ldap->modify("cn=My User, o=My Company,c=XY",
1280                              add => [
1281                                      'userCertificate' => [ $cert ]
1282                                     ]);
1283         die "Modify failed (" . ldap_error_name($res->code) . ")\n"
1284             if $res->code;
1285
1286       For LDAPv3, you must do this instead:
1287
1288         $res = $ldap->modify("cn=My User, o=My Company, c=XY",
1289                              add => [
1290                                      'userCertificate;binary' => [ $cert ]
1291                                     ]);
1292         die "Modify failed (" . ldap_error_name($res->code) . ")\n"
1293             if $res->code;
1294
1295       Of course, the entry you are trying to add the certificate to must use
1296       object classes that permit the userCertificate attribute, otherwise the
1297       modify will fail with an object class violation error. The
1298       inetOrgPerson structural object class permits userCertificates, as does
1299       the strongAuthenticationUser auxiliary object class. Others might also.
1300

ADDITIONAL DIRECTORY AND LDAP RESOURCES.

1302   URLs.
1303       Directory Services Mark Language (DSML)
1304       http://www.oasis-open.org/specs/
1305
1306       eMailman LDAP information http://www.emailman.com/ldap/
1307
1308       Rafael Corvalan's LDAP shell http://sf.net/projects/ldapsh
1309
1310       LDAPS, also known as LDAPGURU.  This web site has a nasty habit of
1311       resizing the browser to cover the WHOLE screen.  http://www.ldaps.com
1312
1313       Jeff Hodges's Kings Mountain LDAP
1314       http://www.kingsmountain.com/ldapRoadmap.shtml
1315
1316       Mark Wahl's LDAP World at Innosoft.  http://www.innosoft.com/ldapworld/
1317       (outdated: last update was in 1998)
1318
1319       Open Source LDAP Directory Server.  http://www.openldap.org/
1320
1321       CriticalPath http://www.cp.net/
1322
1323       IBM Directory Server
1324       http://www-306.ibm.com/software/network/directory/server/
1325
1326       Innosoft http://www.innosoft.com (acquired by Sun)
1327
1328       Isode (was MessagingDirect) http://www.isode.com/
1329
1330       Netscape Directory Developers Area
1331       http://developer.netscape.com/directory/
1332
1333       Nexor's X.500 and Internet Directories
1334       http://www.nexor.com/info/directory.htm/
1335
1336       Novell's eDirectory http://www.novell.com/
1337
1338       Novell's LDAPzone http://ldapzone.com/
1339
1340       Octet String http://www.octetstring.com/
1341
1342       SUN JAVA JNDI (Java Naming and Directory Interface)
1343       http://www.java.sun.com/jndi/
1344
1345       Sun One, formerly Iplanet.  http://wwws.sun.com/software/
1346
1347       Eine deutsche LDAP Website A German LDAP Website
1348       http://verzeichnisdienst.de/ldap/Perl/index.html
1349
1350       The 2 following URLs deal mainly with Microsoft's Active Directory.
1351
1352       Directory Works http://directoryworks.com/
1353
1354       ActiveX LDAP Client http://www.polonia-online.com/ldap/
1355
1356   BOOKS
1357       Developing LDAP and ADSI Clients for Microsoft(R) Exchange.  By Sven B.
1358       Schreiber.  ISBN:  0201657775
1359
1360       Implementing LDAP.  By Mark Wilcox.  ISBN:  1861002211
1361
1362       LDAP: Programming Directory-Enabled Applications With Lightweight
1363       Directory Access Protocol.  By Tim Howes, Mark Smith.  ISBN:
1364       1578700000
1365
1366       LDAP Programming; Directory Management and Integration.  By Clayton
1367       Donley.  ISBN:  1884777910
1368
1369       LDAP Programming with Java.  By Rob Weltman, Tony Dahbura.  ISBN:
1370       0201657589
1371
1372       LDAP System Administration.  By Gerald Carter.  ISBN:  1565924916
1373
1374       Managing Enterprise Active Directory Services.  By Robbie Allen,
1375       Richard Puckett.  ISBN:  0672321254
1376
1377       Solaris and LDAP Naming Services.  By Tom Bialaski, Michael Haines.
1378       ISBN:  0-13-030678-9
1379
1380       Understanding and Deploying LDAP Directory Services (2ed).  By Tim
1381       Howes, Mark Smith, Gordon Good.  ISBN:  0672323168
1382
1383       LDAP Directories Explained.  By Brian Arkills. ISBN 0-201-78792-X
1384

AUTHORS

1386       Any good FAQ is made up of many authors, everyone that contributes
1387       information to the perl-ldap mail list is a potential author.
1388
1389       An attempt to maintain this FAQ is being done by Chris Ridd
1390       <chris.ridd@isode.com> and Peter Marschall <peter@adpm.de>.  It was
1391       previously updated by Clif Harden <charden@pobox.com>.
1392
1393       The original author of this FAQ was Graham Barr <gbarr@pobox.com>
1394
1395       Please report any bugs, or post any suggestions, to the perl-ldap
1396       mailing list <perl-ldap@perl.org>.
1397
1399       Copyright (c) 1999-2004 Graham Barr. All rights reserved. This document
1400       is distributed, and may be redistributed, under the same terms as Perl
1401       itself.
1402
1403
1404
1405perl v5.10.1                      2017-03-21                 Net::LDAP::FAQ(3)
Impressum