LDAP functions LDAP Introduction to LDAP LDAP is the Lightweight Directory Access Protocol, and is a protocol used to access "Directory Servers". The Directory is a special kind of database that holds information in a tree structure. The concept is similar to your hard disk directory structure, except that in this context, the root directory is "The world" and the first level subdirectories are "countries". Lower levels of the directory structure contain entries for companies, organisations or places, while yet lower still we find directory entries for people, and perhaps equipment or documents. To refer to a file in a subdirectory on your hard disk, you might use something like /usr/local/myapp/docs The forwards slash marks each division in the reference, and the sequence is read from left to right. The equivalent to the fully qualified file reference in LDAP is the "distinguished name", referred to simply as "dn". An example dn might be. cn=John Smith,ou=Accounts,o=My Company,c=US The comma marks each division in the reference, and the sequence is read from right to left. You would read this dn as .. country = US organization = My Company organizationalUnit = Accounts commonName = John Smith In the same way as there are no hard rules about how you organise the directory structure of a hard disk, a directory server manager can set up any structure that is meaningful for the purpose. However, there are some conventions that are used. The message is that you can not write code to access a directory server unless you know something about its structure, any more than you can use a database without some knowledge of what is available. Complete code example Retrieve information for all entries where the surname starts with "S" from a directory server, displaying an extract with name and email address. LDAP search example <?php // basic sequence with LDAP is connect, bind, search, interpret search // result, close connection echo "<h3>LDAP query test</h3>"; echo "Connecting ..."; $ds=ldap_connect("localhost"); // must be a valid LDAP server! echo "connect result is ".$ds."<p>"; if ($ds) { echo "Binding ..."; $r=ldap_bind($ds); // this is an "anonymous" bind, typically // read-only access echo "Bind result is echo "Bind result is ".$r."<p>"; echo "Searching for (sn=S*) ..."; // Search surname entry $sr=ldap_search($ds,"o=My Company, c=US", "sn=S*"); echo "Search result is ".$sr."<p>"; echo "Number of entires returned is ".ldap_count_entries($ds,$sr)."<p>"; echo "Getting entries ...<p>"; $info = ldap_get_entries($ds, $sr); echo "Data for ".$info["count"]." items returned:<p>"; for ($i=0; $i<$info["count"]; $i++) { echo "dn is: ". $info[$i]["dn"] ."<br>"; echo "first cn entry is: ". $info[$i]["cn"][0] ."<br>"; echo "first email entry is: ". $info[$i]["mail"][0] ."<p>"; } echo "Closing connection"; ldap_close($ds); } else { echo "<h4>Unable to connect to LDAP server</h4>"; } ?> Using the PHP LDAP calls You will need to get and compile LDAP client libraries from either the University of Michigan ldap-3.3 package or the Netscape Directory SDK. You will also need to recompile PHP with LDAP support enabled before PHP's LDAP calls will work. Before you can use the LDAP calls you will need to know .. The name or address of the directory server you will use The "base dn" of the server (the part of the world directory that is held on this server, which could be "o=My Company,c=US") Whether you need a password to access the server (many servers will provide read access for an "anonymous bind" but require a password for anything else) The typical sequence of LDAP calls you will make in an application will follow this pattern: ldap_connect() // establish connection to server | ldap_bind() // anonymous or authenticated "login" | do something like search or update the directory and display the results | ldap_close() // "logout" More Information Lots of information about LDAP can be found at Netscape University of Michigan OpenLDAP Project LDAP World The Netscape SDK contains a helpful Programmer's Guide in .html format. ldap_add Add entries to LDAP directory Description int ldap_add int link_identifier string dn array entry returns true on success and false on error. The ldap_add function is used to add entries in the LDAP directory. The DN of the entry to be added is specified by dn. Array entry specifies the information about the entry. The values in the entries are indexed by individual attributes. In case of multiple values for an attribute, they are indexed using integers starting with 0. entry["attribute1"] = value entry["attribute2"][0] = value1 entry["attribute2"][1] = value2 Complete example with authenticated bind <?php $ds=ldap_connect("localhost"); // assuming the LDAP server is on this host if ($ds) { // bind with appropriate dn to give update access $r=ldap_bind($ds,"cn=root, o=My Company, c=US", "secret"); // prepare data $info["cn"]="John Jones"; $info["sn"]="Jones"; $info["mail"]="jonj@here.and.now"; $info["objectclass"]="person"; // add data to directory $r=ldap_add($ds, "cn=John Jones, o=My Company, c=US", $info); ldap_close($ds); } else { echo "Unable to connect to LDAP server"; } ?> ldap_mod_add Add attribute values to current attributes Description int ldap_mod_add int link_identifier string dn array entry returns true on success and false on error. This function adds attribute(s) to the specified dn. It performs the modification at the attribute level as opposed to the object level. Object-level additions are done by the ldap_add function. ldap_mod_del Delete attribute values from current attributes Description int ldap_mod_del int link_identifier string dn array entry returns true on success and false on error. This function removes attribute(s) from the specified dn. It performs the modification at the attribute level as opposed to the object level. Object-level deletions are done by the ldap_del function. ldap_mod_replace Replace attribute values with new ones Description int ldap_mod_replace int link_identifier string dn array entry returns true on success and false on error. This function replaces attribute(s) from the specified dn. It performs the modification at the attribute level as opposed to the object level. Object-level modifications are done by the ldap_modify function. ldap_bind Bind to LDAP directory Description int ldap_bind int link_identifier string bind_rdn string bind_password Binds to the LDAP directory with specified RDN and password. Returns true on success and false on error. ldap_bind does a bind operation on the directory. bind_rdn and bind_password are optional. If not specified, anonymous bind is attempted. ldap_close Close link to LDAP server Description int ldap_close int link_identifier Returns true on success, false on error. ldap_close closes the link to the LDAP server that's associated with the specified link_identifier. This call is internally identical to ldap_unbind. The LDAP API uses the call ldap_unbind, so perhaps you should use this in preference to ldap_close. ldap_connect Connect to an LDAP server Description int ldap_connect string hostname int port Returns a positive LDAP link identifier on success, or false on error. ldap_connect establishes a connection to a LDAP server on a specified hostname and port. Both the arguments are optional. If no arguments are specified then the link identifier of the already opened link will be returned. If only hostname is specified, then the port defaults to 389. ldap_count_entries Count the number of entries in a search Description int ldap_count_entries int link_identifier int result_identifier Returns number of entries in the result or false on error. ldap_count_entries returns the number of entries stored in the result of previous search operations. result_identifier identifies the internal ldap result. ldap_delete Delete an entry from a directory Description int ldap_delete int link_identifier string dn Returns true on success and false on error. ldap_delete function delete a particular entry in LDAP directory specified by dn. ldap_dn2ufn Convert DN to User Friendly Naming format Description string ldap_dn2ufn string dn ldap_dn2ufn function is used to turn a DN into a more user-friendly form, stripping off type names. ldap_explode_dn Splits DN into its component parts Description array ldap_explode_dn string dn int with_attrib ldap_explode_dn function is used to split the a DN returned by ldap_get_dn and breaks it up into its component parts. Each part is known as Relative Distinguished Name, or RDN. ldap_explode_dn returns an array of all those components. with_attrib is used to request if the RDNs are returned with only values or their attributes as well. To get RDNs with the attributes (i.e. in attribute=value format) set with_attrib to 0 and to get only values set it to 1. ldap_first_attribute Return first attribute Description string ldap_first_attribute int link_identifier int result_entry_identifier int ber_identifier Returns the first attribute in the entry on success and false on error. Similar to reading entries, attributes are also read one by one from a particular entry. ldap_first_attribute returns the first attribute in the entry pointed by the entry identifier. Remaining attributes are retrieved by calling ldap_next_attribute successively. ber_identifier is the identifier to internal memory location pointer. It is passed by reference. The same ber_identifier is passed to the ldap_next_attribute() function, which modifies that pointer. see also ldap_get_attributes ldap_first_entry Return first result id Description int ldap_first_entry int link_identifier int result_identifier Returns the result entry identifier for the first entry on success and false on error. Entries in the LDAP result are read sequentially using the ldap_first_entry and ldap_next_entry functions. ldap_first_entry returns the entry identifier for first entry in the result. This entry identifier is then supplied to lap_next_entry routine to get successive entries from the result. see also ldap_get_entries. ldap_free_result Free result memory Description int ldap_free_result int result_identifier Returns true on success and false on error. ldap_free_result frees up the memory allocated internally to store the result and pointed by the result_identifier. All result memory will be automatically freed when the script terminates. Typically all the memory allocated for the ldap result gets freed at the end of the script. In case the script is making successive searches which return large result sets, ldap_free_result could be called to keep the runtime memory usage by the script low. ldap_get_attributes Get attributes from a search result entry Description array ldap_get_attributes int link_identifier int result_entry_identifier Returns a complete entry information in a multi-dimensional array on success and false on error. ldap_get_attributes function is used to simplify reading the attributes and values from an entry in the search result. The return value is a multi-dimensional array of attributes and values. Having located a specific entry in the directory, you can find out what information is held for that entry by using this call. You would use this call for an application which "browses" directory entries and/or where you do not know the structure of the directory entries. In many applications you will be searching for a specific attribute such as an email address or a surname, and won't care what other data is held. return_value["count"] = number of attributes in the entry return_value[0] = first attribute return_value[n] = nth attribute return_value["attribute"]["count"] = number of values for attribute return_value["attribute"][0] = first value of the attribute return_value["attribute"][i] = ith value of the attribute Show the list of attributes held for a particular directory entry // $ds is the link identifier for the directory // $sr is a valid search result from a prior call to // one of the ldap directory search calls $entry = ldap_first_entry($ds, $sr); $attrs = ldap_get_attributes($ds, $entry); echo $attrs["count"]." attributes held for this entry:<p>"; for ($i=0; $i<$attrs["count"]; $i++) echo $attrs[$i]."<br>"; see also ldap_first_attribute and ldap_next_attribute ldap_get_dn Get the DN of a result entry Description string ldap_get_dn int link_identifier int result_entry_identifier Returns the DN of the result entry and false on error. ldap_get_dn function is used to find out the DN of an entry in the result. ldap_get_entries Get all result entries Description array ldap_get_entries int link_identifier int result_identifier Returns a complete result information in a multi-dimenasional array on success and false on error. ldap_get_entries function is used to simplify reading multiple entries from the result and then reading the attributes and multiple values. The entire information is returned by one function call in a multi-dimensional array. The structure of the array is as follows. The attribute index is converted to lowercase. (Attributes are case-insensitive for directory servers, but not when used as array indices) return_value["count"] = number of entries in the result return_value[0] : refers to the details of first entry return_value[i]["dn"] = DN of the ith entry in the result return_value[i]["count"] = number of attributes in ith entry return_value[i][j] = jth attribute in the ith entry in the result return_value[i]["attribute"]["count"] = number of values for attribute in ith entry return_value[i]["attribute"][j] = jth value of attribute in ith entry see also ldap_first_entry and ldap_next_entry ldap_get_values Get all values from a result entry Description array ldap_get_values int link_identifier int result_entry_identifier string attribute Returns an array of values for the attribute on success and false on error. ldap_get_values function is used to read all the values of the attribute in the entry in the result. entry is specified by the result_entry_identifier. The number of values can be found by indexing "count" in the resultant array. Individual values are accessed by integer index in the array. The first index is 0. This call needs a result_entry_identifier, so needs to be preceded by one of the ldap search calls and one of the calls to get an individual entry. You application will either be hard coded to look for certain attributes (such as "surname" or "mail") or you will have to use the ldap_get_attributes call to work out what attributes exist for a given entry. LDAP allows more than one entry for an attribute, so it can, for example, store a number of email addresses for one person's directory entry all labeled with the attribute "mail" return_value["count"] = number of values for attribute return_value[0] = first value of attribute return_value[i] = ith value of attribute List all values of the "mail" attribute for a directory entry // $ds is a valid link identifier for a directory server // $sr is a valid search result from a prior call to // one of the ldap directory search calls // $entry is a valid entry identifier from a prior call to // one of the calls that returns a directory entry $values = ldap_get_values($ds, $entry,"mail"); echo $values["count"]." email addresses for this entry.<p>"; for ($i=0; $i < $values["count"]; $i++) echo $values[$i]."<br>"; ldap_list Single-level search Description int ldap_list int link_identifier string base_dn string filter array attributes Returns a search result identifier or false on error. ldap_list performs the search for a specified filter on the directory with the scope LDAP_SCOPE_ONELEVEL. LDAP_SCOPE_ONELEVEL means that the search should only return information that is at the level immediately below the base dn given in the call. (Equivalent to typing "ls" and getting a list of files and folders in the current working directory.) This call takes an optional fourth parameter which is an array of the attributes required. See ldap_search notes. Produce a list of all organizational units of an organization // $ds is a valid link identifier for a directory server $basedn = "o=My Company, c=US"; $justthese = array("ou"); $sr=ldap_list($ds, $basedn, "ou=*", $justthese); $info = ldap_get_entries($ds, $sr); for ($i=0; $i<$info["count"]; $i++) echo $info[$i]["ou"][0] ; ldap_modify Modify an LDAP entry Description int ldap_modify int link_identifier string dn array entry Returns true on success and false on error. ldap_modify function is used to modify the existing entries in the LDAP directory. The structure of the entry is same as in ldap_add. ldap_next_attribute Get the next attribute in result Description string ldap_next_attribute int link_identifier int result_entry_identifier int ber_identifier Returns the next attribute in an entry on success and false on error. ldap_next_attribute is called to retrieve the attributes in an entry. The internal state of the pointer is maintained by the ber_identifier. It is passed by reference to the function. The first call to ldap_next_attribute is made with the result_entry_identifier returned from ldap_first_attribute. see also ldap_get_attributes ldap_next_entry Get next result entry Description int ldap_next_entry int link_identifier int result_entry_identifier Returns entry identifier for the next entry in the result whose entries are being read starting with ldap_first_entry. If there are no more entries in the result then it returns false. ldap_next_entry function is used to retrieve the entries stored in the result. Successive calls to the ldap_next_entry return entries one by one till there are no more entries. The first call to ldap_next_entry is made after the call to ldap_first_entry with the result_identifier as returned from the ldap_first_entry. see also ldap_get_entries ldap_read Read an entry Description int ldap_read int link_identifier string base_dn string filter array attributes Returns a search result identifier or false on error. ldap_read performs the search for a specified filter on the directory with the scope LDAP_SCOPE_BASE. So it is equivalent to reading an entry from the directory. An empty filter is not allowed. If you want to retrieve absolutely all information for this entry, use a filter of "objectClass=*". If you know which entry types are used on the directory server, you might use an appropriate filter such as "objectClass=inetOrgPerson". This call takes an optional fourth parameter which is an array of the attributes required. See ldap_search notes. ldap_search Search LDAP tree Description int ldap_search int link_identifier string base_dn string filter array attributes Returns a search result identifier or false on error. ldap_search performs the search for a specified filter on the directory with the scope of LDAP_SCOPE_SUBTREE. This is equivalent to searching the entire directory. base_dn specifies the base DN for the directory. There is a optional fourth parameter, that can be added to restrict the attributes and values returned by the server to just those required. This is much more efficient than the default action (which is to return all attributes and their associated values). The use of the fourth parameter should therefore be considered good practice. The fourth parameter is a standard PHP string array of the required attributes, eg array("mail","sn","cn") Note that the "dn" is always returned irrespective of which attributes types are requested. Note too that some directory server hosts will be configured to return no more than a preset number of entries. If this occurs, the server will indicate that it has only returned a partial results set. The search filter can be simple or advanced, using boolean operators in the format described in the LDAP doumentation (see the Netscape Directory SDK for full information on filters). The example below retrieves the organizational unit, surname, given name and email address for all people in "My Company" where the surname or given name contains the substring $person. This example uses a boolean filter to tell the server to look for information in more than one attribute. LDAP search // $ds is a valid link identifier for a directory server // $person is all or part of a person's name, eg "Jo" $dn = "o=My Company, c=US"; $filter="(|(sn=$person*)(givenname=$person*))"; $justthese = array( "ou", "sn", "givenname", "mail"); $sr=ldap_search($ds, $dn, $filter, $justthese); $info = ldap_get_entries($ds, $sr); print $info["count"]." entries returned<p>"; ldap_unbind Unbind from LDAP directory Description int ldap_unbind int link_identifier Returns true on success and false on error. ldap_unbind function unbinds from the LDAP directory.