summaryrefslogtreecommitdiff
path: root/doc/rfc/rfc1823.txt
blob: 835f1ef477fc96b9592f4f2df285131fa6db984e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
Network Working Group                                           T. Howes
Request for Comments: 1823                                      M. Smith
Category: Informational                          University of  Michigan
                                                             August 1995


                 The LDAP Application Program Interface

Status of this Memo

   This memo provides information for the Internet community.  This memo
   does not specify an Internet standard of any kind.  Distribution of
   this memo is unlimited.

1.  Introduction

   This document defines a C language application program interface to
   the lightweight directory access protocol (LDAP). The LDAP API is
   designed to be powerful, yet simple to use. It defines compatible
   synchronous and asynchronous interfaces to LDAP to suit a wide
   variety of applications.  This document gives a brief overview of the
   LDAP model, then an overview of how the API is used by an application
   program to obtain LDAP information.  The API calls are described in
   detail, followed by an appendix that provides some example code
   demonstrating the use of the API.

2.  Overview of the LDAP Model

   LDAP is the lightweight directory access protocol, described in [2]
   and [7]. It can provide a lightweight frontend to the X.500 directory
   [1], or a stand-alone service. In either mode, LDAP is based on a
   client-server model in which a client makes a TCP connection to an
   LDAP server, over which it sends requests and receives responses.

   The LDAP information model is based on the entry, which contains
   information about some object (e.g., a person).  Entries are composed
   of attributes, which have a type and one or more values. Each
   attribute has a syntax that determines what kinds of values are
   allowed in the attribute (e.g., ASCII characters, a jpeg photograph,
   etc.) and how those values behave during directory operations (e.g.,
   is case significant during comparisons).

   Entries are organized in a tree structure, usually based on
   political, geographical, and organizational boundaries. Each entry is
   uniquely named relative to its sibling entries by its relative
   distinguished name (RDN) consisting of one or more distinguished
   attribute values from the entry.  At most one value from each
   attribute may be used in the RDN.  For example, the entry for the



Howes & Smith                Informational                      [Page 1]
^L
RFC 1823                        LDAP API                     August 1995


   person Babs Jensen might be named with the "Barbara Jensen" value
   from the commonName attribute. A globally unique name for an entry,
   called a distinguished name or DN, is constructed by concatenating
   the sequence of RDNs from the root of the tree down to the entry. For
   example, if Babs worked for the University of Michigan, the DN of her
   U-M entry might be "cn=Barbara Jensen, o=University of Michigan,
   c=US". The DN format used by LDAP is defined in [4].

   Operations are provided to authenticate, search for and retrieve
   information, modify information, and add and delete entries from the
   tree.  The next sections give an overview of how the API is used and
   detailed descriptions of the LDAP API calls that implement all of
   these functions.

3.  Overview of LDAP API Use

   An application generally uses the LDAP API in four simple steps.

   o    Open a connection to an LDAP server. The ldap_open() call
        returns a handle to the connection, allowing multiple
        connections to be open at once.

   o    Authenticate to the LDAP server and/or the X.500 DSA. The
        ldap_bind() call and friends support a variety of
        authentication methods.

   o    Perform some LDAP operations and obtain some results.
        ldap_search() and friends return results which can be parsed
        by ldap_result2error(), ldap_first_entry(), ldap_next_entry(),
        etc.

   o    Close the connection. The ldap_unbind() call closes the
        connection.

   Operations can be performed either synchronously or asynchronously.
   Synchronous calls end in _s. For example, a synchronous search can be
   completed by calling ldap_search_s(). An asynchronous search can be
   initiated by calling ldap_search(). All synchronous routines return
   an indication of the outcome of the operation (e.g, the constant
   LDAP_SUCCESS or some other error code).  The asynchronous routines
   return the message id of the operation initiated. This id can be used
   in subsequent calls to ldap_result() to obtain the result(s) of the
   operation.  An asynchronous operation can be abandoned by calling
   ldap_abandon().







Howes & Smith                Informational                      [Page 2]
^L
RFC 1823                        LDAP API                     August 1995


   Results and errors are returned in an opaque structure called
   LDAPMessage.  Routines are provided to parse this structure, step
   through entries and attributes returned, etc. Routines are also
   provided to interpret errors. The next sections describe these
   routines in more detail.

4.  Calls for performing LDAP operations

   This section describes each LDAP operation API call in detail. All
   calls take a "connection handle", a pointer to an LDAP structure
   containing per-connection information.  Many routines return results
   in an LDAPMessage structure. These structures and others are
   described as needed below.

4.1.  Opening a connection

   ldap_open() opens a connection to the LDAP server.

              typedef struct ldap {
                      /* ... opaque parameters ... */
                      int     ld_deref;
                      int     ld_timelimit;
                      int     ld_sizelimit;
                      int     ld_errno;
                      char    *ld_matched;
                      char    *ld_error;
                      /* ... opaque parameters ... */
              } LDAP;

              LDAP *ldap_open( char *hostname, int portno );

      Parameters are:

      hostname Contains a space-separated list of hostnames or dotted
               strings representing the IP address of hosts running an
               LDAP server to connect to. The hosts are tried in the
               order listed, stopping with the first one to which a
               successful connection is made;

      portno   contains the TCP port number to which to connect. The
               default LDAP port can be obtained by supplying the
               constant LDAP_PORT.

   ldap_open() returns a "connection handle", a pointer to an LDAP
   structure that should be passed to subsequent calls pertaining to the
   connection. It returns NULL if the connection cannot be opened. One
   of the ldap_bind calls described below must be completed before other
   operations can be performed on the connection.



Howes & Smith                Informational                      [Page 3]
^L
RFC 1823                        LDAP API                     August 1995


   The calling program should assume nothing about the order of the
   fields in the LDAP structure. There may be other fields in the
   structure for internal library use. The fields shown above are
   described as needed in the description of other calls below.

4.2.  Authenticating to the directory

   ldap_bind() and friends are used to authenticate to the directory.

           int ldap_bind( LDAP *ld, char *dn, char *cred, int method );

           int ldap_bind_s( LDAP *ld, char *dn, char *cred, int method );

           int ldap_simple_bind( LDAP *ld, char *dn, char *passwd );

           int ldap_simple_bind_s( LDAP *ld, char *dn, char *passwd );

           int ldap_kerberos_bind( LDAP *ld, char *dn );

           int ldap_kerberos_bind_s( LDAP *ld, char *dn );

   Parameters are:

   ld     The connection handle;

   dn     The name of the entry to bind as;

   cred   The credentials with which to authenticate;

   method One of LDAP_AUTH_SIMPLE, LDAP_AUTH_KRBV41, or
          LDAP_AUTH_KRBV42, indicating the authentication method to use;

   passwd For ldap_simple_bind(), the password to compare to the entry's
          userPassword attribute;

   There are three types of bind calls, providing simple authentication,
   kerberos authentication, and general routines to do either one. In
   the case of Kerberos version 4 authentication using the general
   ldap_bind() routines, the credentials are ignored, as the routines
   assume a valid ticket granting ticket already exists which can be
   used to retrieve the appropriate service tickets.

   Synchronous versions of the routines have names that end in _s.
   These routines return the result of the bind operation, either the
   constant LDAP_SUCCESS if the operation was successful, or another
   LDAP error code if it was not. See the section below on error
   handling for more information about possible errors and how to
   interpret them.



Howes & Smith                Informational                      [Page 4]
^L
RFC 1823                        LDAP API                     August 1995


   Asynchronous versions of these routines return the message id of the
   bind operation initiated. A subsequent call to ldap_result(),
   described below, can be used to obtain the result of the bind. In
   case of error, these routines will return -1, setting the ld_errno
   field in the LDAP structure appropriately.

   Note that no other operations over the connection should be attempted
   before a bind call has successfully completed. Subsequent bind calls
   can be used to re-authenticate over the same connection.

4.3.  Closing the connection

   ldap_unbind() is used to unbind from the directory and close the
   connection.

           int ldap_unbind( LDAP *ld );

   Parameters are:

      ld   The connection handle.

   ldap_unbind() works synchronously, unbinding from the directory,
   closing the connection, and freeing up the ld structure before
   returning. ldap_unbind() returns LDAP_SUCCESS (or another LDAP error
   code if the request cannot be sent to the LDAP server).  After a call
   to ldap_unbind(), the ld connection handle is invalid.

4.4.  Searching

   ldap_search() and friends are used to search the LDAP directory,
   returning a requested set of attributes for each entry matched.
   There are three variations.

           struct timeval {
                   long    tv_sec;
                   long    tv_usec;
           };
           int ldap_search(
                   LDAP    *ld,
                   char    *base,
                   int     scope,
                   char    *filter,
                   char    *attrs[],
                   int     attrsonly
           );
           int ldap_search_s(
                   LDAP            *ld,
                   char            *base,



Howes & Smith                Informational                      [Page 5]
^L
RFC 1823                        LDAP API                     August 1995


                   int             scope,
                   char            *filter,
                   char            *attrs[],
                   int             attrsonly,
                   LDAPMessage     **res
           );
           int ldap_search_st(
                   LDAP            *ld,
                   char            *base,
                   int             scope,
                   char            *filter,
                   char            *attrs[],
                   int             attrsonly,
                   struct timeval  *timeout,
                   LDAPMessage     **res
           );

   Parameters are:

   ld        The connection handle;

   base      The dn of the entry at which to start the search;

   scope     One of LDAP_SCOPE_BASE, LDAP_SCOPE_ONELEVEL, or
             LDAP_SCOPE_SUBTREE, indicating the scope of the search;

   filter    A character string as described in RFC 1558 [3],
             representing the search filter;

   attrs     A NULL-terminated array of strings indicating which
             attributes to return for each matching entry. Passing
             NULL for this parameter causes all available attributes
             to be retrieved;

   attrsonly A boolean value that should be zero if both attribute
             types and values are to be returned, non-zero if only
             types are wanted;

   timeout   For the ldap_search_st() call, this specifies the local
             search timeout value;

   res       For the synchronous calls, this is a result parameter
             which will contain the results of the search upon
             completion of the call.

   There are three fields in the ld connection handle which control how
   the search is performed. They are:




Howes & Smith                Informational                      [Page 6]
^L
RFC 1823                        LDAP API                     August 1995


   ld_sizelimit A limit on the number of entries to return from the
                search. A value of zero means no limit;

   ld_timelimit A limit on the number of seconds to spend on the search.
                A value of zero means no limit;

   ld_deref     One of LDAP_DEREF_NEVER, LDAP_DEREF_SEARCHING,
                LDAP_DEREF_FINDING, or LDAP_DEREF_ALWAYS, specifying
                how aliases should be handled during the search. The
                LDAP_DEREF_SEARCHING value means aliases should be
                dereferenced during the search but not when locating
                the base object of the search. The LDAP_DEREF_FINDING
                value means aliases should be dereferenced when
                locating the base object but not during the search.

   An asynchronous search is initiated by calling ldap_search(). It
   returns the message id of the initiated search. The results of the
   search can be obtained by a subsequent call to ldap_result().  The
   results can be parsed by the result parsing routines described in
   detail later.  In case of error, -1 is returned and the ld_errno
   field in the LDAP structure is set appropriately.

   A synchronous search is performed by calling ldap_search_s() or
   ldap_search_st(). The routines are identical, except that
   ldap_search_st() takes an additional parameter specifying a timeout
   for the search.  Both routines return an indication of the result of
   the search, either LDAP_SUCCESS or some error indication (see Error
   Handling below).  The entries returned from the search (if any) are
   contained in the res parameter. This parameter is opaque to the
   caller.  Entries, attributes, values, etc., should be extracted by
   calling the parsing routines described below. The results contained
   in res should be freed when no longer in use by calling
   ldap_msgfree(), described later.

4.5.  Reading an entry

   LDAP does not support a read operation directly. Instead, this
   operation is emulated by a search with base set to the DN of the
   entry to read, scope set to LDAP_SCOPE_BASE, and filter set to
   "(objectclass=*)". attrs contains the list of attributes to return.

4.6.  Listing the children of an entry

   LDAP does not support a list operation directly. Instead, this
   operation is emulated by a search with base set to the DN of the
   entry to list, scope set to LDAP_SCOPE_ONELEVEL, and filter set to
   "(objectclass=*)". attrs contains the list of attributes to return
   for each child entry.



Howes & Smith                Informational                      [Page 7]
^L
RFC 1823                        LDAP API                     August 1995


4.7.  Modifying an entry

   The ldap_modify() and ldap_modify_s() routines are used to modify an
   existing LDAP entry.

           typedef struct ldapmod {
                   int             mod_op;
                   char            *mod_type;
                   union {
                           char            **modv_strvals;
                           struct berval   **modv_bvals;
                   } mod_vals;
           } LDAPMod;
           #define mod_values      mod_vals.modv_strvals
           #define mod_bvalues     mod_vals.modv_bvals

           int ldap_modify( LDAP *ld, char *dn, LDAPMod *mods[] );

           int ldap_modify_s( LDAP *ld, char *dn, LDAPMod *mods[] );

   Parameters are:

   ld       The connection handle;

   dn       The name of the entry to modify;

   mods     A NULL-terminated array of modifications to make to the
            entry.

   The fields in the LDAPMod structure have the following meanings:

   mod_op   The modification operation to perform. It should be one of
            LDAP_MOD_ADD, LDAP_MOD_DELETE, or LDAP_MOD_REPLACE. This
            field also indicates the type of values included in the
            mod_vals union. It is ORed with LDAP_MOD_BVALUES to select
            the mod_bvalues form. Otherwise, the mod_values form is
            used;

   mod_type The type of the attribute to modify;

   mod_vals The values (if any) to add, delete, or replace. Only one of
            the mod_values or mod_bvalues variants should be used,
            selected by ORing the mod_op field with the constant
            LDAP_MOD_BVALUES. mod_values is a NULL-terminated array of
            zero-terminated strings and mod_bvalues is a NULL-terminated
            array of berval structures that can be used to pass binary
            values such as images.




Howes & Smith                Informational                      [Page 8]
^L
RFC 1823                        LDAP API                     August 1995


   For LDAP_MOD_ADD modifications, the given values are added to the
   entry, creating the attribute if necessary.  For LDAP_MOD_DELETE
   modifications, the given values are deleted from the entry, removing
   the attribute if no values remain.  If the entire attribute is to be
   deleted, the mod_vals field should be set to NULL.  For
   LDAP_MOD_REPLACE modifications, the attribute will have the listed
   values after the modification, having been created if necessary.  All
   modifications are performed in the order in which they are listed.

   ldap_modify_s() returns the LDAP error code  resulting  from the
   modify  operation.   This  code  can  be interpreted by ldap_perror()
   and friends.

   ldap_modify() returns the message id of the request it initiates, or
   -1 on error.  The result of the operation can be obtained by calling
   ldap_result().

4.8.  Modifying the RDN of an entry

   The ldap_modrdn() and ldap_modrdn_s() routines are used to change the
   name of an LDAP entry.

           int ldap_modrdn(
                   LDAP    *ld,
                   char    *dn,
                   char    *newrdn,
                   int     deleteoldrdn
           );
           int ldap_modrdn_s(
                   LDAP    *ld,
                   char    *dn,
                   char    *newrdn,
                   int     deleteoldrdn
           );

   Parameters are:

   ld            The connection handle;

   dn            The name of the entry whose RDN is to be changed;

   newrdn        The new RDN to give the entry;

   deleteoldrdn  A boolean value, if non-zero indicating that the old
                 RDN value(s) should be removed, if zero indicating that
                 the old RDN value(s) should be retained as non-
                 distinguished values of the entry.




Howes & Smith                Informational                      [Page 9]
^L
RFC 1823                        LDAP API                     August 1995


   The ldap_modrdn_s() routine is synchronous, returning the LDAP error
   code indicating the outcome of the operation.

   The ldap_modrdn() routine is asynchronous, returning the message id
   of the operation it initiates, or -1 in case of trouble. The result
   of the operation can be obtained by calling ldap_result().

4.9.  Adding an entry

   ldap_add() and ldap_add_s() are used to add entries to the LDAP
   directory.

           int ldap_add( LDAP *ld, char *dn, LDAPMod *attrs[] );

           int ldap_add_s( LDAP *ld, char *dn, LDAPMod *attrs[] );

   Parameters are:

   ld    The connection handle;

   dn    The name of the entry to add;

   attrs The entry's attributes, specified using the LDAPMod structure
         defined for ldap_modify(). The mod_type and mod_vals fields
         should be filled in.  The mod_op field is ignored unless ORed
         with the constant LDAP_MOD_BVALUES, used to select the
         mod_bvalues case of the mod_vals union.

   Note that the parent of the entry must already exist.

   ldap_add_s() is synchronous, returning the LDAP error code indicating
   the outcome of the operation.

   ldap_add() is asynchronous, returning the message id of the operation
   it initiates, or -1 in case of trouble. The result of the operation
   can be obtained by calling ldap_result().

4.10.  Deleting an entry

   ldap_delete() and ldap_delete_s() are used to delete entries from the
   LDAP directory.

           int ldap_delete( LDAP *ld, char *dn );

           int ldap_delete_s( LDAP *ld, char *dn );






Howes & Smith                Informational                     [Page 10]
^L
RFC 1823                        LDAP API                     August 1995


   Parameters are:

   ld       The connection handle;

   dn       The name of the entry to delete.

   Note that the entry to delete must be a leaf entry (i.e., it must
   have no children). Deletion of entire subtrees is not supported by
   LDAP.

   ldap_delete_s() is synchronous, returning the LDAP error code
   indicating the outcome of the operation.

   ldap_delete() is asynchronous, returning the message id of the
   operation it initiates, or -1 in case of trouble. The result of the
   operation can be obtained by calling ldap_result().

5.  Calls for abandoning an operation

   ldap_abandon() is used to abandon an operation in progress.

           int ldap_abandon( LDAP *ld, int msgid );

   ldap_abandon() abandons the operation with message id msgid. It
   returns zero if the abandon was successful, -1 otherwise. After a
   successful call to ldap_abandon(), results with the given message id
   are never returned from a call to ldap_result().

6.  Calls for obtaining results

   ldap_result() is used to obtain the result of a previous
   asynchronously initiated operation. ldap_msgfree() frees the results
   obtained from a previous call to ldap_result(), or a synchronous
   search routine.

           int ldap_result(
                   LDAP            *ld,
                   int             msgid,
                   int             all,
                   struct timeval  *timeout,
                   LDAPMessage     **res
           );

           int ldap_msgfree( LDAPMessage *res );







Howes & Smith                Informational                     [Page 11]
^L
RFC 1823                        LDAP API                     August 1995


   Parameters are:

   ld       The connection handle;

   msgid    The message id of the operation whose results are to be
            returned, or the constant LDAP_RES_ANY if any result is
            desired;

   all      A boolean parameter that only has meaning for search
            results. If non-zero it indicates that all results of a
            search should be retrieved before any are returned. If zero,
            search results (entries) will be returned one at a time as
            they arrive;

   timeout  A timeout specifying how long to wait for results to be
            returned.  A NULL value causes ldap_result() to block until
            results are available.  A timeout value of zero second
            specifies a polling behavior;

   res      For ldap_result(), a result parameter that will contain the
            result(s) of the operation. For ldap_msgfree(), the result
            chain to be freed, obtained from a previous call to
            ldap_result() or ldap_search_s() or ldap_search_st().

   Upon successful completion, ldap_result() returns the type of the
   result returned in the res parameter. This will be one of the
   following constants.

             LDAP_RES_BIND
             LDAP_RES_SEARCH_ENTRY
             LDAP_RES_SEARCH_RESULT
             LDAP_RES_MODIFY
             LDAP_RES_ADD
             LDAP_RES_DELETE
             LDAP_RES_MODRDN
             LDAP_RES_COMPARE

   ldap_result() returns 0 if the timeout expired and -1 if an error
   occurs, in which case the ld_errno field of the ld structure will be
   set accordingly.

   ldap_msgfree() frees the result structure pointed to be res and
   returns the type of the message it freed.








Howes & Smith                Informational                     [Page 12]
^L
RFC 1823                        LDAP API                     August 1995


7.  Calls for error handling

   The following calls are used to interpret errors returned by other
   LDAP API routines.

           int ldap_result2error(
                   LDAP            *ld,
                   LDAPMessage     *res,
                   int             freeit
           );

           char *ldap_err2string( int err );

           void ldap_perror( LDAP *ld, char *msg );

   Parameters are:

   ld       The connection handle;

   res      The result of an LDAP operation as returned by ldap_result()
            or one of the synchronous API operation calls;

   freeit   A boolean parameter indicating whether the res parameter
            should be freed (non-zero) or not (zero);

   err      An LDAP error code, as returned by ldap_result2error() or
            one of the synchronous API operation calls;

   msg      A message to be displayed before the LDAP error message.

   ldap_result2error() is used to convert the LDAP result message
   obtained from ldap_result(), or the res parameter returned by one of
   the synchronous API operation calls, into a numeric LDAP error code.
   It also parses the ld_matched and ld_error portions of the result
   message and puts them into the connection handle information. All the
   synchronous operation routines call ldap_result2error() before
   returning, ensuring that these fields are set correctly. The relevant
   fields in the connection structue are:

   ld_matched In the event of an LDAP_NO_SUCH_OBJECT error return, this
              parameter contains the extent of the DN matched;

   ld_error   This parameter contains the error message sent in the
              result by the LDAP server.

   ld_errno   The LDAP error code indicating the outcome of the
              operation. It is one of the following constants:




Howes & Smith                Informational                     [Page 13]
^L
RFC 1823                        LDAP API                     August 1995


           LDAP_SUCCESS
           LDAP_OPERATIONS_ERROR
           LDAP_PROTOCOL_ERROR
           LDAP_TIMELIMIT_EXCEEDED
           LDAP_SIZELIMIT_EXCEEDED
           LDAP_COMPARE_FALSE
           LDAP_COMPARE_TRUE
           LDAP_STRONG_AUTH_NOT_SUPPORTED
           LDAP_STRONG_AUTH_REQUIRED
           LDAP_NO_SUCH_ATTRIBUTE
           LDAP_UNDEFINED_TYPE
           LDAP_INAPPROPRIATE_MATCHING
           LDAP_CONSTRAINT_VIOLATION
           LDAP_TYPE_OR_VALUE_EXISTS
           LDAP_INVALID_SYNTAX
           LDAP_NO_SUCH_OBJECT
           LDAP_ALIAS_PROBLEM
           LDAP_INVALID_DN_SYNTAX
           LDAP_IS_LEAF
           LDAP_ALIAS_DEREF_PROBLEM
           LDAP_INAPPROPRIATE_AUTH
           LDAP_INVALID_CREDENTIALS
           LDAP_INSUFFICIENT_ACCESS
           LDAP_BUSY
           LDAP_UNAVAILABLE
           LDAP_UNWILLING_TO_PERFORM
           LDAP_LOOP_DETECT
           LDAP_NAMING_VIOLATION
           LDAP_OBJECT_CLASS_VIOLATION
           LDAP_NOT_ALLOWED_ON_NONLEAF
           LDAP_NOT_ALLOWED_ON_RDN
           LDAP_ALREADY_EXISTS
           LDAP_NO_OBJECT_CLASS_MODS
           LDAP_RESULTS_TOO_LARGE
           LDAP_OTHER
           LDAP_SERVER_DOWN
           LDAP_LOCAL_ERROR
           LDAP_ENCODING_ERROR
           LDAP_DECODING_ERROR
           LDAP_TIMEOUT
           LDAP_AUTH_UNKNOWN
           LDAP_FILTER_ERROR
           LDAP_USER_CANCELLED
           LDAP_PARAM_ERROR
           LDAP_NO_MEMORY






Howes & Smith                Informational                     [Page 14]
^L
RFC 1823                        LDAP API                     August 1995


   ldap_err2string() is used to convert a numeric LDAP error code, as
   returned by ldap_result2error() or one of the synchronous API
   operation calls, into an informative NULL-terminated character string
   message describing the error.  It returns a pointer to static data.

   ldap_perror() is used to print the message supplied in msg, followed
   by an indication of the error contained in the ld_errno field of the
   ld connection handle, to standard error.

8.  Calls for parsing search entries

   The following calls are used to parse the entries returned by
   ldap_search() and friends. These entries are returned in an opaque
   structure that should only be accessed by calling the routines
   described below. Routines are provided to step through the entries
   returned, step through the attributes of an entry, retrieve the name
   of an entry, and retrieve the values associated with a given
   attribute in an entry.

8.1.  Stepping through a set of entries

   The ldap_first_entry() and ldap_next_entry() routines are used to
   step through a set of entries in a search result.
   ldap_count_entries() is used to count the number of entries returned.

           LDAPMesage *ldap_first_entry( LDAP *ld, LDAPMessage *res );

           LDAPMesage *ldap_next_entry( LDAP *ld, LDAPMessage *entry );

           int ldap_count_entries( LDAP *ld, LDAPMessage *res );

   Parameters are:

   ld     The connection handle;

   res    The search result, as obtained by a call to one of the syn-
          chronous search routines or ldap_result();

   entry  The entry returned by a previous call to ldap_first_entry() or
          ldap_next_entry().

   ldap_first_entry() and ldap_next_entry() will return NULL when no
   more entries exist to be returned. NULL is also returned if an error
   occurs while stepping through the entries, in which case the ld_errno
   field of the ld connection handle will be set to indicate the error.

   ldap_count_entries() returns the number of entries contained in a
   chain of entries. It can also be used to count the number of entries



Howes & Smith                Informational                     [Page 15]
^L
RFC 1823                        LDAP API                     August 1995


   that remain in a chain if called with an entry returned by
   ldap_first_entry() or ldap_next_entry().

8.2.  Stepping through the attributes of an entry

   The ldap_first_attribute() and ldap_next_attribute() calls are used
   to step through the list of attribute types returned with an entry.

           char *ldap_first_attribute(
                   LDAP            *ld,
                   LDAPMessage     *entry,
                   void            **ptr
           );
           char *ldap_next_attribute(
                   LDAP            *ld,
                   LDAPMessage     *entry,
                   void            *ptr
           );

   Parameters are:

   ld     The connection handle;

   entry  The entry whose attributes are to be stepped through, as
          returned by ldap_first_entry() or ldap_next_entry();

   ptr    In ldap_first_attribute(), the address of a pointer used
          internally to keep track of the current position in the entry.
          In ldap_next_attribute(), the pointer returned by a previous
          call to ldap_first_attribute().

   ldap_first_attribute() and ldap_next_attribute() will return NULL
   when the end of the attributes is reached, or if there is an error,
   in which case the ld_errno field in the ld connection handle will be
   set to indicate the error.

   Both routines return a pointer to a per-connection buffer containing
   the current attribute name. This should be treated like static data.
   ldap_first_attribute() will allocate and return in ptr a pointer to a
   BerElement used to keep track of the current position. This pointer
   should be passed in subsequent calls to ldap_next_attribute() to step
   through the entry's attributes.

   The attribute names returned are suitable for passing in a call to
   ldap_get_values() and friends to retrieve the associated values.






Howes & Smith                Informational                     [Page 16]
^L
RFC 1823                        LDAP API                     August 1995


8.3.  Retrieving the values of an attribute

   ldap_get_values() and ldap_get_values_len() are used to retrieve the
   values of a given attribute from an entry. ldap_count_values() and
   ldap_count_values_len() are used to count the returned values.
   ldap_value_free() and ldap_value_free_len() are used to free the
   values.

           typedef struct berval {
                   unsigned long   bv_len;
                   char            *bv_val;
           };

           char **ldap_get_values(
                   LDAP            *ld,
                   LDAPMessage     *entry,
                   char            *attr
           );

           struct berval **ldap_get_values_len(
                   LDAP            *ld,
                   LDAPMessage     *entry,
                   char            *attr
           );

           int ldap_count_values( char **vals );

           int ldap_count_values_len( struct berval **vals );

           int ldap_value_free( char **vals );

           int ldap_value_free_len( struct berval **vals );

   Parameters are:

   ld     The connection handle;

   entry  The entry from which to retrieve values, as returned by
          ldap_first_entry() or ldap_next_entry();

   attr   The attribute whose values are to be retrieved, as returned by
          ldap_first_attribute() or ldap_next_attribute(), or a caller-
          supplied string (e.g., "mail");

   vals   The values returned by a previous call to ldap_get_values() or
          ldap_get_values_len().





Howes & Smith                Informational                     [Page 17]
^L
RFC 1823                        LDAP API                     August 1995


   Two forms of the various calls are provided. The first form is only
   suitable for use with non-binary character string data only. The
   second _len form is used with any kind of data.

   Note that the values returned are malloc'ed and should be freed by
   calling either ldap_value_free() or ldap_value_free_len() when no
   longer in use.

8.4.  Retrieving the name of an entry

   ldap_get_dn() is used to retrieve the name of an entry.
   ldap_explode_dn() is used to break up the name into its component
   parts. ldap_dn2ufn() is used to convert the name into a more "user
   friendly" format.

           char *ldap_get_dn( LDAP *ld, LDAPMessage *entry );

           char **ldap_explode_dn( char *dn, int notypes );

           char *ldap_dn2ufn( char *dn );

   Parameters are:

   ld      The connection handle;

   entry   The entry whose name is to be retrieved, as returned by
           ldap_first_entry() or ldap_next_entry();

   dn      The dn to explode, as returned by ldap_get_dn();

   notypes A boolean parameter, if non-zero indicating that the dn com-
           ponents should have their type information stripped off
           (i.e., "cn=Babs" would become "Babs").

   ldap_get_dn() will return NULL if there is some error parsing the dn,
   setting ld_errno in the ld connection handle to indicate the error.
   It returns a pointer to malloc'ed space that the caller should free
   by calling free() when it is no longer in use.  Note the format of
   the DNs returned is given by [4].

   ldap_explode_dn() returns a char * array containing the RDN
   components of the DN supplied, with or without types as indicated by
   the notypes parameter. The array returned should be freed when it is
   no longer in use by calling ldap_value_free().

   ldap_dn2ufn() converts the DN into the user friendly format described
   in [5]. The UFN returned is malloc'ed space that should be freed by a
   call to free() when no longer in use.



Howes & Smith                Informational                     [Page 18]
^L
RFC 1823                        LDAP API                     August 1995


9.  Security Considerations

   LDAP supports minimal security during connection authentication.

10.  Acknowledgements

   This material is based upon work supported by the National Science
   Foundation under Grant No. NCR-9416667.

11.  Bibliography

   [1] The Directory: Selected Attribute Syntaxes.  CCITT,
       Recommendation X.520.

   [2] Howes, T., Kille, S., Yeong, W., and C. Robbins, "The String
       Representation of Standard Attribute Syntaxes", University of
       Michigan, ISODE Consortium, Performance Systems International,
       NeXor Ltd., RFC 1778, March 1995.

   [3] Howes, T., "A String Representation of LDAP Search Filters", RFC
       1558, University of Michigan, December 1993.

   [4] Kille, S., "A String Representation of Distinguished Names", RFC
       1779, ISODE Consortium, March 1995.

   [5] Kille, S., "Using the OSI Directory to Achieve User Friendly
       Naming",  RFC 1781, ISODE Consortium, March 1995.

   [6] S.P. Miller, B.C. Neuman, J.I. Schiller, J.H. Saltzer, "Kerberos
       Authentication and Authorization System", MIT Project Athena
       Documentation Section  E.2.1, December 1987

   [7] Yeong, W., Howes, T., and S. Kille, "Lightweight Directory Access
       Protocol," RFC 1777, Performance Systems International,
       University of Michigan, ISODE Consortium, March 1995.
















Howes & Smith                Informational                     [Page 19]
^L
RFC 1823                        LDAP API                     August 1995


12.  Authors' Addresses

       Tim Howes
       University of Michigan
       ITD Research Systems
       535 W William St.
       Ann Arbor, MI 48103-4943
       USA

       Phone: +1 313 747-4454
       EMail: tim@umich.edu


       Mark Smith
       University of Michigan
       ITD Research Systems
       535 W William St.
       Ann Arbor, MI 48103-4943
       USA

       Phone: +1 313 764-2277
       EMail: mcs@umich.edu





























Howes & Smith                Informational                     [Page 20]
^L
RFC 1823                        LDAP API                     August 1995


13.  Appendix A - Sample LDAP API Code

   #include <ldap.h>

   main()
   {
           LDAP            *ld;
           LDAPMessage     *res, *e;
           int             i;
           char            *a, *dn;
           void            *ptr;
           char            **vals;

           /* open a connection */
           if ( (ld = ldap_open( "dotted.host.name", LDAP_PORT ))
                   == NULL )
                   exit( 1 );

           /* authenticate as nobody */
           if ( ldap_simple_bind_s( ld, NULL, NULL ) != LDAP_SUCCESS ) {
                   ldap_perror( ld, "ldap_simple_bind_s" );
                   exit( 1 );
           }

           /* search for entries with cn of "Babs Jensen",
                   return all attrs  */
           if ( ldap_search_s( ld, "o=University of Michigan, c=US",
               LDAP_SCOPE_SUBTREE, "(cn=Babs Jensen)", NULL, 0, &res )
               != LDAP_SUCCESS ) {
                   ldap_perror( ld, "ldap_search_s" );
                   exit( 1 );
           }

           /* step through each entry returned */
           for ( e = ldap_first_entry( ld, res ); e != NULL;
               e = ldap_next_entry( ld, e ) ) {
                   /* print its name */
                   dn = ldap_get_dn( ld, e );
                   printf( "dn: %s0, dn );
                   free( dn );

                   /* print each attribute */
                   for ( a = ldap_first_attribute( ld, e, &ptr );
                           a != NULL;
                       a = ldap_next_attribute( ld, e, ptr ) ) {
                           printf( "attribute: %s0, a );

                           /* print each value */



Howes & Smith                Informational                     [Page 21]
^L
RFC 1823                        LDAP API                     August 1995


                           vals = ldap_get_values( ld, e, a );
                           for ( i = 0; vals[i] != NULL; i++ ) {
                                   printf( "value: %s0, vals[i] );
                           }
                           ldap_value_free( vals );
                   }
           }
           /* free the search results */
           ldap_msgfree( res );

           /* close and free connection resources */
           ldap_unbind( ld );
   }






































Howes & Smith                Informational                     [Page 22]
^L