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
|
<pre>Network Working Group T. Howes
Request for Comments: 1823 M. Smith
Category: Informational University of Michigan
August 1995
<span class="h1">The LDAP Application Program Interface</span>
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.
<span class="h2"><a class="selflink" id="section-1" href="#section-1">1</a>. Introduction</span>
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.
<span class="h2"><a class="selflink" id="section-2" href="#section-2">2</a>. Overview of the LDAP Model</span>
LDAP is the lightweight directory access protocol, described in [<a href="#ref-2" title=""The String Representation of Standard Attribute Syntaxes"">2</a>]
and [<a href="#ref-7" title=""Lightweight Directory Access Protocol,"">7</a>]. It can provide a lightweight frontend to the X.500 directory
[<a href="#ref-1">1</a>], 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
<span class="grey">Howes & Smith Informational [Page 1]</span></pre>
<hr class='noprint'/><!--NewPage--><pre class='newpage'><span id="page-2" ></span>
<span class="grey"><a href="./rfc1823">RFC 1823</a> LDAP API August 1995</span>
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 [<a href="#ref-4" title=""A String Representation of Distinguished Names"">4</a>].
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.
<span class="h2"><a class="selflink" id="section-3" href="#section-3">3</a>. Overview of LDAP API Use</span>
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().
<span class="grey">Howes & Smith Informational [Page 2]</span></pre>
<hr class='noprint'/><!--NewPage--><pre class='newpage'><span id="page-3" ></span>
<span class="grey"><a href="./rfc1823">RFC 1823</a> LDAP API August 1995</span>
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.
<span class="h2"><a class="selflink" id="section-4" href="#section-4">4</a>. Calls for performing LDAP operations</span>
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.
<span class="h3"><a class="selflink" id="section-4.1" href="#section-4.1">4.1</a>. Opening a connection</span>
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.
<span class="grey">Howes & Smith Informational [Page 3]</span></pre>
<hr class='noprint'/><!--NewPage--><pre class='newpage'><span id="page-4" ></span>
<span class="grey"><a href="./rfc1823">RFC 1823</a> LDAP API August 1995</span>
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.
<span class="h3"><a class="selflink" id="section-4.2" href="#section-4.2">4.2</a>. Authenticating to the directory</span>
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.
<span class="grey">Howes & Smith Informational [Page 4]</span></pre>
<hr class='noprint'/><!--NewPage--><pre class='newpage'><span id="page-5" ></span>
<span class="grey"><a href="./rfc1823">RFC 1823</a> LDAP API August 1995</span>
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.
<span class="h3"><a class="selflink" id="section-4.3" href="#section-4.3">4.3</a>. Closing the connection</span>
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.
<span class="h3"><a class="selflink" id="section-4.4" href="#section-4.4">4.4</a>. Searching</span>
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,
<span class="grey">Howes & Smith Informational [Page 5]</span></pre>
<hr class='noprint'/><!--NewPage--><pre class='newpage'><span id="page-6" ></span>
<span class="grey"><a href="./rfc1823">RFC 1823</a> LDAP API August 1995</span>
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 <a href="./rfc1558">RFC 1558</a> [<a href="#ref-3" title=""A String Representation of LDAP Search Filters"">3</a>],
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:
<span class="grey">Howes & Smith Informational [Page 6]</span></pre>
<hr class='noprint'/><!--NewPage--><pre class='newpage'><span id="page-7" ></span>
<span class="grey"><a href="./rfc1823">RFC 1823</a> LDAP API August 1995</span>
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.
<span class="h3"><a class="selflink" id="section-4.5" href="#section-4.5">4.5</a>. Reading an entry</span>
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.
<span class="h3"><a class="selflink" id="section-4.6" href="#section-4.6">4.6</a>. Listing the children of an entry</span>
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.
<span class="grey">Howes & Smith Informational [Page 7]</span></pre>
<hr class='noprint'/><!--NewPage--><pre class='newpage'><span id="page-8" ></span>
<span class="grey"><a href="./rfc1823">RFC 1823</a> LDAP API August 1995</span>
<span class="h3"><a class="selflink" id="section-4.7" href="#section-4.7">4.7</a>. Modifying an entry</span>
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.
<span class="grey">Howes & Smith Informational [Page 8]</span></pre>
<hr class='noprint'/><!--NewPage--><pre class='newpage'><span id="page-9" ></span>
<span class="grey"><a href="./rfc1823">RFC 1823</a> LDAP API August 1995</span>
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().
<span class="h3"><a class="selflink" id="section-4.8" href="#section-4.8">4.8</a>. Modifying the RDN of an entry</span>
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.
<span class="grey">Howes & Smith Informational [Page 9]</span></pre>
<hr class='noprint'/><!--NewPage--><pre class='newpage'><span id="page-10" ></span>
<span class="grey"><a href="./rfc1823">RFC 1823</a> LDAP API August 1995</span>
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().
<span class="h3"><a class="selflink" id="section-4.9" href="#section-4.9">4.9</a>. Adding an entry</span>
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().
<span class="h3"><a class="selflink" id="section-4.10" href="#section-4.10">4.10</a>. Deleting an entry</span>
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 );
<span class="grey">Howes & Smith Informational [Page 10]</span></pre>
<hr class='noprint'/><!--NewPage--><pre class='newpage'><span id="page-11" ></span>
<span class="grey"><a href="./rfc1823">RFC 1823</a> LDAP API August 1995</span>
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().
<span class="h2"><a class="selflink" id="section-5" href="#section-5">5</a>. Calls for abandoning an operation</span>
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().
<span class="h2"><a class="selflink" id="section-6" href="#section-6">6</a>. Calls for obtaining results</span>
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 );
<span class="grey">Howes & Smith Informational [Page 11]</span></pre>
<hr class='noprint'/><!--NewPage--><pre class='newpage'><span id="page-12" ></span>
<span class="grey"><a href="./rfc1823">RFC 1823</a> LDAP API August 1995</span>
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.
<span class="grey">Howes & Smith Informational [Page 12]</span></pre>
<hr class='noprint'/><!--NewPage--><pre class='newpage'><span id="page-13" ></span>
<span class="grey"><a href="./rfc1823">RFC 1823</a> LDAP API August 1995</span>
<span class="h2"><a class="selflink" id="section-7" href="#section-7">7</a>. Calls for error handling</span>
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:
<span class="grey">Howes & Smith Informational [Page 13]</span></pre>
<hr class='noprint'/><!--NewPage--><pre class='newpage'><span id="page-14" ></span>
<span class="grey"><a href="./rfc1823">RFC 1823</a> LDAP API August 1995</span>
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
<span class="grey">Howes & Smith Informational [Page 14]</span></pre>
<hr class='noprint'/><!--NewPage--><pre class='newpage'><span id="page-15" ></span>
<span class="grey"><a href="./rfc1823">RFC 1823</a> LDAP API August 1995</span>
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.
<span class="h2"><a class="selflink" id="section-8" href="#section-8">8</a>. Calls for parsing search entries</span>
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.
<span class="h3"><a class="selflink" id="section-8.1" href="#section-8.1">8.1</a>. Stepping through a set of entries</span>
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
<span class="grey">Howes & Smith Informational [Page 15]</span></pre>
<hr class='noprint'/><!--NewPage--><pre class='newpage'><span id="page-16" ></span>
<span class="grey"><a href="./rfc1823">RFC 1823</a> LDAP API August 1995</span>
that remain in a chain if called with an entry returned by
ldap_first_entry() or ldap_next_entry().
<span class="h3"><a class="selflink" id="section-8.2" href="#section-8.2">8.2</a>. Stepping through the attributes of an entry</span>
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.
<span class="grey">Howes & Smith Informational [Page 16]</span></pre>
<hr class='noprint'/><!--NewPage--><pre class='newpage'><span id="page-17" ></span>
<span class="grey"><a href="./rfc1823">RFC 1823</a> LDAP API August 1995</span>
<span class="h3"><a class="selflink" id="section-8.3" href="#section-8.3">8.3</a>. Retrieving the values of an attribute</span>
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().
<span class="grey">Howes & Smith Informational [Page 17]</span></pre>
<hr class='noprint'/><!--NewPage--><pre class='newpage'><span id="page-18" ></span>
<span class="grey"><a href="./rfc1823">RFC 1823</a> LDAP API August 1995</span>
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.
<span class="h3"><a class="selflink" id="section-8.4" href="#section-8.4">8.4</a>. Retrieving the name of an entry</span>
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 [<a href="#ref-4" title=""A String Representation of Distinguished Names"">4</a>].
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 [<a href="#ref-5" title=""Using the OSI Directory to Achieve User Friendly Naming"">5</a>]. The UFN returned is malloc'ed space that should be freed by a
call to free() when no longer in use.
<span class="grey">Howes & Smith Informational [Page 18]</span></pre>
<hr class='noprint'/><!--NewPage--><pre class='newpage'><span id="page-19" ></span>
<span class="grey"><a href="./rfc1823">RFC 1823</a> LDAP API August 1995</span>
<span class="h2"><a class="selflink" id="section-9" href="#section-9">9</a>. Security Considerations</span>
LDAP supports minimal security during connection authentication.
<span class="h2"><a class="selflink" id="section-10" href="#section-10">10</a>. Acknowledgements</span>
This material is based upon work supported by the National Science
Foundation under Grant No. NCR-9416667.
<span class="h2"><a class="selflink" id="section-11" href="#section-11">11</a>. Bibliography</span>
[<a id="ref-1">1</a>] The Directory: Selected Attribute Syntaxes. CCITT,
Recommendation X.520.
[<a id="ref-2">2</a>] 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., <a href="./rfc1778">RFC 1778</a>, March 1995.
[<a id="ref-3">3</a>] Howes, T., "A String Representation of LDAP Search Filters", <a href="./rfc1558">RFC</a>
<a href="./rfc1558">1558</a>, University of Michigan, December 1993.
[<a id="ref-4">4</a>] Kille, S., "A String Representation of Distinguished Names", <a href="./rfc1779">RFC</a>
<a href="./rfc1779">1779</a>, ISODE Consortium, March 1995.
[<a id="ref-5">5</a>] Kille, S., "Using the OSI Directory to Achieve User Friendly
Naming", <a href="./rfc1781">RFC 1781</a>, ISODE Consortium, March 1995.
[<a id="ref-6">6</a>] 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
[<a id="ref-7">7</a>] Yeong, W., Howes, T., and S. Kille, "Lightweight Directory Access
Protocol," <a href="./rfc1777">RFC 1777</a>, Performance Systems International,
University of Michigan, ISODE Consortium, March 1995.
<span class="grey">Howes & Smith Informational [Page 19]</span></pre>
<hr class='noprint'/><!--NewPage--><pre class='newpage'><span id="page-20" ></span>
<span class="grey"><a href="./rfc1823">RFC 1823</a> LDAP API August 1995</span>
<span class="h2"><a class="selflink" id="section-12" href="#section-12">12</a>. Authors' Addresses</span>
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
<span class="grey">Howes & Smith Informational [Page 20]</span></pre>
<hr class='noprint'/><!--NewPage--><pre class='newpage'><span id="page-21" ></span>
<span class="grey"><a href="./rfc1823">RFC 1823</a> LDAP API August 1995</span>
<span class="h2"><a class="selflink" id="section-13" href="#section-13">13</a>. <a href="#appendix-A">Appendix A</a> - Sample LDAP API Code</span>
#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 */
<span class="grey">Howes & Smith Informational [Page 21]</span></pre>
<hr class='noprint'/><!--NewPage--><pre class='newpage'><span id="page-22" ></span>
<span class="grey"><a href="./rfc1823">RFC 1823</a> LDAP API August 1995</span>
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]
</pre>
|