2 Developing Applications with Standard LDAP APIs

This chapter takes a high-level look at the operations that the standard LDAP API enables. It explains how to integrate your applications with the API. Before presenting these topics, the chapter revisits the Lightweight Directory Access Protocol (LDAP).

This chapter contains these topics:

2.1 History of LDAP

LDAP began as a lightweight front end to the X.500 Directory Access Protocol. LDAP simplifies the X.500 Directory Access Protocol in the following ways:

  • It uses TCP/IP connections. These are lightweight compared to the OSI communication stack required by X.500 implementations

  • It eliminates little-used and redundant features of the X.500 Directory Access Protocol

  • It uses simple formats to represent data elements. These formats are easier to process than the complicated and highly structured representations in X.500.

  • It uses a simplified version of the X.500 encoding rules used to transport data over networks.

2.2 LDAP Models

LDAP uses four basic models to define its operations, described in the following sections:

2.2.1 Naming Model

The LDAP naming model enables directory information to be referenced and organized. Each entry in a directory is uniquely identified by a distinguished name (DN). The DN tells you exactly where an entry resides in the directory hierarchy. A directory information tree (DIT) is used to represent this hierarchy.

Figure 2-1 illustrates the relationship between a distinguished name and a directory information tree.

Figure 2-1 A Directory Information Tree

Described in text.

The DIT in Figure 2-1 shows entries for two employees of Example Corporation who are both named Anne Smith. It is structured along geographical and organizational lines. The Anne Smith represented by the left branch works in the Sales division in the United States. Her counterpart works in the Server Development division in the United Kingdom.

The Anne Smith represented by the right branch has the common name (cn) Anne Smith. She works in an organizational unit (ou) named Server Development, in the country (c) of United Kingdom of Great Britain and Northern Ireland (uk), in the organization (o) Example. The DN for this Anne Smith entry looks like this:

cn=Anne Smith,ou=Server Development,c=uk,o=example

Note that the conventional format for a distinguished name places the lowest DIT component at the left. The next highest component follows, on up to the root.

Within a distinguished name, the lowest component is called the relative distinguished name (RDN). In the DN just presented, the RDN is cn=Anne Smith. The RDN for the entry immediately above Anne Smith's RDN is ou=Server Development. And the RDN for the entry immediately above ou=Server Development is c=uk, and so on. A DN is thus a sequence of RDNs separated by commas.

To locate a particular entry within the overall DIT, a client uniquely identifies that entry by using the full DN—not simply the RDN—of that entry. To avoid confusion between the two Anne Smiths in the global organization depicted in Figure 2-1, you use the full DN for each. If there are two employees with the same name in the same organizational unit, you can use other mechanisms. You may, for example, use a unique identification number to identify these employees.

2.2.2 Information Model

The LDAP information model determines the form and character of information in the directory. This model uses the concept of entries as its defining characteristic. In a directory, an entry is a collection of information about an object. A telephone directory, for example, contains entries for people. A library card catalog contains entries for books. An online directory may contain entries for employees, conference rooms, e-commerce partners, or shared network resources such as printers.

In a typical telephone directory, a person entry contains an address and a phone number. In an online directory, each of these pieces of information is called an attribute. A typical employee entry contains attributes for a job title, an e-mail address, and a phone number.

In Figure 2-2, the entry for Anne Smith in Great Britain (uk) has several attributes. Each provides specific information about her. Those listed in the balloon to the right of the tree are emailaddrs, printername, jpegPhoto, and app preferences. Note that the rest of the bullets in Figure 2-2 are also entries with attributes, although these attributes are not shown.

Figure 2-2 Attributes of the Entry for Anne Smith

Described in text.

Each attribute consists of an attribute type and one or more attribute values. The attribute type is the kind of information that the attribute contains—jobTitle, for instance. The attribute value is the actual information. The value for the jobTitle attribute, for example, might be manager.

2.2.3 Functional Model

The LDAP functional model determines what operations can be performed on directory entries. Table 2-1 lists and describes the three types of functions:

Table 2-1 LDAP Functions

Function Description

Search and read

The read operation retrieves the attributes of an entry whose name is known. The list operation enumerates the children of a given entry. The search operation selects entries from a defined area of the tree based on some selection criteria known as a search filter. For each matching entry, a requested set of attributes (with or without values) is returned. The searched entries can span a single entry, an entry's children, or an entire subtree. Alias entries can be followed automatically during a search, even if they cross server boundaries. An abandon operation is also defined, allowing an operation in progress to be canceled.


This category defines four operations that modify the directory:

  • Modify—change existing entries. You can add and delete values.

  • Add—insert entries into the directory

  • Delete—remove entries from the directory

  • Modify RDN—change the name of an entry


This category defines a bind operation. A bind enables a client to initiate a session and prove its identity to the directory. Oracle Internet Directory supports several authentication methods, from simple clear-text passwords to public keys. The unbind operation is used to terminate a directory session.

2.2.4 Security Model

The LDAP security model enables directory information to be secured. This model has several parts: Authentication

Authentication is the process by which the directory server establishes the identity of the user connecting to the directory. Directory authentication occurs when an LDAP bind operation establishes an LDAP session. Every session has an associated user identity, also referred to as an authorization ID.

Oracle Internet Directory provides three authentication options: anonymous, simple, and SSL. Anonymous Authentication

If your directory is available to everyone, users may log in anonymously. In anonymous authentication, users leave the user name and password fields blank when they log in. They then exercise whatever privileges are specified for anonymous users. Simple Authentication

In simple authentication, the client uses an unencrypted DN and password to identify itself to the server. The server verifies that the client's DN and password match the DN and password stored in the directory. Authentication Using Secure Sockets Layer (SSL)

Secure Sockets Layer (SSL) is an industry standard protocol for securing network connections. It uses a certificate exchange to authenticate users. These certificates are verified by trusted certificate authorities. A certificate ensures that an entity's identity information is correct. An entity can be an end user, a database, an administrator, a client, or a server. A Certificate Authority (CA) is an application that creates public key certificates that are given a high level of trust by all parties involved.

You can use SSL in one of the three authentication modes presented in Table 2-2.

Table 2-2 SSL Authentication Modes

SSL Mode Description

No authentication

Neither the client nor the server authenticates itself to the other. No certificates are sent or exchanged. In this case, only SSL encryption and decryption are used.

One-way authentication

Only the directory server authenticates itself to the client. The directory server sends the client a certificate verifying that the server is authentic.

Two-way authentication

Both client and server authenticate themselves to each other, exchanging certificates.

In an Oracle Internet Directory environment, SSL authentication between a client and a directory server involves three basic steps:

  1. The user initiates an LDAP connection to the directory server by using SSL on an SSL port. The default SSL port is 3131.

  2. SSL performs the handshake between the client and the directory server.

  3. If the handshake is successful, the directory server verifies that the user has the appropriate authorization to access the directory.

    See Also:

    Oracle Advanced Security Administrator's Guide for more information about SSL. Access Control and Authorization

The authorization process ensures that a user reads or updates only the information for which he or she has privileges. The directory server ensures that the user— identified by the authorization ID associated with the session—has the requisite permissions to perform a given directory operation. Absent these permissions, the operation is disallowed.

The mechanism that the directory server uses to ensure that the proper authorizations are in place is called access control. And an access control item (ACI) is the directory metadata that captures the administrative policies relating to access control.

An ACI is stored in Oracle Internet Directory as user-modifiable operational attributes. Typically a whole list of these ACI attribute values is associated with a directory object. This list is called an access control list (ACL). The attribute values on that list govern the access policies for the directory object.

ACIs are stored as text strings in the directory. These strings must conform to a well-defined format. Each valid value of an ACI attribute represents a distinct access control policy. These individual policy components are referred to as ACI Directives or ACIs and their format is called the ACI Directive format.

Access control policies can be prescriptive: their security directives can be set to apply downward to all entries at lower positions in the directory information tree (DIT). The point from which an access control policy applies is called an access control policy point (ACP). Data Integrity

Oracle Internet Directory uses SSL to ensure that data is not modified, deleted, or replayed during transmission. This feature uses cryptographic checksums to generate a secure message digest. The checksums are created using either the MD5 algorithm or the Secure Hash Algorithm (SHA). The message digest is included in each network packet. Data Privacy

Oracle Internet Directory uses public key encryption over SSL to ensure that data is not disclosed during transmission. In public-key encryption, the sender of a message encrypts the message with the public key of the recipient. Upon delivery, the recipient decrypts the message using his or her private key. The directory supports two levels of encryption:

  • DES40

    The DES40 algorithm, available internationally, is a DES variant in which the secret key is preprocessed to provide forty effective key bits. It is designed for use by customers outside the USA and Canada who want to use a DES-based encryption algorithm.

  • RC4_40

    Oracle is licensed to export the RC4 data encryption algorithm with a 40-bit key size to virtually all destinations where Oracle products are available. This makes it possible for international corporations to safeguard their entire operations with fast cryptography. Password Policies

A password policy is a set of rules that govern how passwords are used. When a user attempts to bind to the directory, the directory server uses the password policy to ensure that the password provided meets the various requirements set in that policy.

When you establish a password policy, you set the following types of rules, to mention just a few:

  • The maximum length of time a given password is valid

  • The minimum number of characters a password must contain

  • The ability of users to change their passwords

2.3 About the Standard LDAP APIs

The standard LDAP APIs enable you to perform the fundamental LDAP operations described in "LDAP Models". These APIs are available in C, PL/SQL, and Java. The first two are part of the directory SDK. The last is part of the JNDI package. All three use TCP/IP connections. They are based on LDAP Version 3, and they support SSL connections to Oracle Internet Directory.

This section contains these topics:

2.3.1 API Usage Model

Typically, an application uses the functions in the API in four steps:

  1. Initialize the library and obtain an LDAP session handle.

  2. Authenticate to the LDAP server if necessary.

  3. Perform some LDAP operations and obtain results and errors, if any.

  4. Close the session.

Figure 2-3 illustrates these steps.

Figure 2-3 Steps in Typical DBMS_LDAP Usage

Described in text

2.3.2 Getting Started with the C API

When you build applications with the C API, you must include the header file ldap.h, located at $ORACLE_HOME/ldap/public. In addition, you must dynamically link to the library located at $ORACLE_HOME/lib/libclntsh.so.10.1.

See Also:

Section 8.3, "Sample C API Usage" to learn how to use the SSL and non-SSL modes.

2.3.3 Getting Started with the DBMS_LDAP Package

The DBMS_LDAP package enables PL/SQL applications to access data located in enterprise-wide LDAP servers. The names and syntax of the function calls are similar to those of the C API. These functions comply with current recommendations of the Internet Engineering Task Force (IETF) for the C API. Note though that the PL/SQL API contains only a subset of the functions available in the C API. Most notably, only synchronous calls to the LDAP server are available in the PL/SQL API.

To begin using the PL/SQL LDAP API, use this command sequence to load DBMS_LDAP into the database:

  1. Log in to the database, using SQL*Plus. Run the tool in the Oracle home in which your database is present. Connect as SYSDBA.

  2. Load the API into the database, using this command:

    SQL> @?/rdbms/admin/catladap.sql

2.3.4 Getting Started with the Java API

Java developers can use the Java Naming and Directory Interface (JNDI) to gain access to information in Oracle Internet Directory. The JNDI is found at this link:


Although no Java APIs are provided in this chapter, Section 2.4.3, "Initializing the Session by Using JNDI" shows you how to use wrapper methods for the JNDI to establish a basic connection.

2.4 Initializing an LDAP Session

All LDAP operations based on the C API require clients to establish an LDAP session with the LDAP server. For LDAP operations based on the PL/SQL API, a database session must first initialize and open an LDAP session. Most Java operations require a Java Naming and Directory Interface (JNDI) connection. The oracle.ldap.util.jndi package, provided here, simplifies the work involved in achieving this connection.

The section contains the following topics:

2.4.1 Initializing the Session by Using the C API

The C function ldap_init() initializes a session with an LDAP server. The server is not actually contacted until an operation is performed that requires it, allowing options to be set after initialization.

ldap_init has the following syntax:

LDAP *ldap_init
const char      *hostname,
int             portno

Table 2-3 lists and defines the function parameters.

Table 2-3 Parameters for ldap_init()

Parameter Description

Contains a space-separated list of directory host names or IP addresses represented by dotted strings. You can pair each host name with a port number if you use a colon to separate the two.

The hosts are tried in the order listed until a successful connection is made.

Note: A suitable representation for including a literal IPv6[10] address in the host name parameter is desired, but has not yet been determined or implemented in practice.


Contains the TCP port number of the directory you would like to connect to. The default LDAP port of 3060 can be obtained by supplying the constant LDAP_PORT. If a host includes a port number, this parameter is ignored.

ldap_init() and ldap_open() both return a session handle, or pointer, to an opaque structure that must be passed to subsequent calls to the session. These routines return NULL if the session cannot be initialized. You can check the error reporting mechanism for your operating system to determine why the call failed.

2.4.2 Initializing the Session by Using DBMS_LDAP

In the PL/SQL API, the function DBMS_LDAP.init() initiates an LDAP session. This function has the following syntax:

FUNCTION init (hostname IN VARCHAR2, portnum  IN PLS_INTEGER )

The function init requires a valid host name and port number to establish an LDAP session. It allocates a data structure for this purpose and returns a handle of the type DBMS_LDAP.SESSION to the caller. The handle returned from the call should be used in all subsequent LDAP operations defined by DBMS_LDAP for the session. The API uses these session handles to maintain state about open connections, outstanding requests, and other information.

A single database session can obtain as many LDAP sessions as required, although the number of simultaneous active connections is limited to 64. One database session typically has multiple LDAP sessions when data must be obtained from multiple servers simultaneously or when open sessions that use multiple LDAP identities are required.


The handles returned from calls to DBMS_LDAP.init() are dynamic constructs. They do not persist across multiple database sessions. Attempting to store their values in a persistent form, and to reuse stored values at a later stage, can yield unpredictable results.

2.4.3 Initializing the Session by Using JNDI

The oracle.ldap.util.jndi package supports basic connections by providing wrapper methods for the JNDI implementation. If you want to use the JNDI to establish a connection, see the following link:


Here is an implementation of oracle.ldap.util.jndi that establishes a non-SSL connection:

import oracle.ldap.util.jndi
import javax.naming.*;

public static void main(String args[])
       InitialDirContext ctx = ConnectionUtil.getDefaultDirCtx(args[0], // host
                                                         args[1],  // port
                                                         args[2],  // DN
                                                         args[3];  // password)
       // Do work
  catch(NamingException ne)
    // javax.naming.NamingException is thrown when an error occurs


  • DN and password represent the bind DN and password. For anonymous binds, set these to "".

  • You can use ConnectionUtil.getSSLDirCtx() to establish a no-authentication SSL connection.

2.5 Authenticating an LDAP Session

Individuals or applications seeking to perform operations against an LDAP server must first be authenticated. If the dn and passwd parameters of these entities are null, the LDAP server assigns a special identity, called anonymous, to these users. Typically, the anonymous user is the least privileged user of the directory.

When a bind operation is complete, the directory server remembers the new identity until another bind occurs or the LDAP session terminates (unbind_s). The LDAP server uses the identity to enforce the security model specified by the enterprise in which it is deployed. The identity helps the LDAP server determine whether the user or application identified has sufficient privileges to perform search, update, or compare operations in the directory.

Note that the password for the bind operation is sent over the network in clear text. If your network is not secure, consider using SSL for authentication and other LDAP operations that involve data transfer.

This section contains these topics:

2.5.1 Authenticating an LDAP Session by Using the C API

The C function ldap_simple_bind_s() enables users and applications to authenticate to the directory server using a DN and password.

The function ldap_simple_bind_s() has this syntax:

int ldap_simple_bind_s
LDAP* ld,
char* dn,
char* passwd

Table 2-4 lists and describes the parameters for this function.

Table 2-4 Arguments for ldap_simple_bind_s()

Argument Description

A valid LDAP session handle


The identity that the application uses for authentication


The password for the authentication identity

If the dn and passwd parameters for are NULL, the LDAP server assigns a special identity, called anonymous, to the user or application.

2.5.2 Authenticating an LDAP Session by Using DBMS_LDAP

The PL/SQL function simple_bind_s enables users and applications to use a DN and password to authenticate to the directory. simple_bind_s has this syntax:

FUNCTION simple_bind_s ( ld IN SESSION, dn IN VARCHAR2, passwd IN VARCHAR2)

Note that this function requires as its first parameter the LDAP session handle obtained from init.

The following PL/SQL code snippet shows how the PL/SQL initialization and authentication functions just described might be implemented.

retval    PLS_INTEGER;
my_session       DBMS_LDAP.session;

retval    := -1;
-- Initialize the LDAP session
my_session       := DBMS_LDAP.init('yow.example.com',3060);
--Authenticate to the directory
retval  :=DBMS_LDAP.simple_bind_s(my_session,'cn=orcladmin', 

In the previous example, an LDAP session is initialized on the LDAP server yow.example.com. This server listens for requests at TCP/IP port number 3060. The identity cn=orcladmin, whose password is welcome, is then authenticated. After authentication is complete, regular LDAP operations can begin.

2.6 Searching the Directory

Searches are the most common LDAP operations. Applications can use complex search criteria to select and retrieve entries from the directory.

This section contains these topics:

2.6.1 Program Flow for Search Operations

The programming required to initiate a typical search operation and retrieve results can be broken down into the following steps:

  1. Decide what attributes must be returned; then place them into an array.

  2. Initiate the search, using the scope options and filters of your choice.

  3. Obtain an entry from result set.

  4. Obtain an attribute from the entry obtained in step 3.

  5. Obtain the values of the attributes obtained in step 4; then copy these values into local variables.

  6. Repeat step 4 until all attributes of the entry are examined.

  7. Repeat Step 3 until there are no more entries

Figure 2-4 uses a flowchart to represent these steps.

Figure 2-4 Flow of Search-Related Operations

Described in text

2.6.2 Search Scope

The scope of a search determines how many entries the directory server examines relative to the search base. You can choose one of the three options described in Table 2-5 and illustrated in Figure 2-5.

Table 2-5 Options for search_s() or search_st() Functions

Option Description

The directory server looks only for the entry corresponding to the search base.


The directory server confines its search to the entries that are the immediate children of the search base entry.


The directory server looks at the search base entry and the entire subtree beneath it.

Figure 2-5 The Three Scope Options

Described in text.

In Figure 2-5, the search base is the shaded circle. The shaded rectangle identifies the entries that are searched.

2.6.3 Filters

A search filter is an expression that enables you to confine your search to certain types of entries. The search filter required by the search_s() and search_st() functions follows the string format defined in RFC 1960 of the Internet Engineering Task Force (IETF). As Table 2-6 shows, there are six kinds of search filters. These are entered in the format attribute operator value.

Table 2-6 Search Filters

Filter Type Format Example Matches



Surnames exactly equal to Keaton.



Surnames approximately equal to Ketan.



Surnames containing the string keaton.

Surnames starting with keaton.

Surnames ending with keaton.

Surnames starting with ke, containing at and ending with on.

Greater than or equal


Surnames lexicographically greater than or equal to Keaton.

Less than or equal


Surnames lexicographically less than or equal to Keaton.



All entries having the sn attribute.


(sn:dn:=Mary Smith)

All entries with a surname attribute in the entry or in the DN of the entry matching "Mary Smith".


  • While Oracle Internet Directory supports extensible filters, ldapsearch and the Oracle LDAP API do not. You must use a different API, such as JNDI, to use this type of filter.

  • Oracle Internet Directory does not support extensible matching using matching rules specified in the filter.

You can use boolean operators and prefix notation to combine these filters to form more complex filters. Table 2-7 provides examples. In these examples, the & character represents AND, the | character represents OR, and the ! character represents NOT.

Table 2-7 Boolean Operators

Filter Type Format Example Matches


(&(filter1)(filter2)). . .)

Entries with surname of Keaton and object class of InetOrgPerson.


(|(filter1)(filter2)). . .)

Entries with surname approximately equal to ketan or common name ending in keaton.



Entries without a mail attribute.

The complex filters in Table 2-7 can themselves be combined to create even more complex, nested filters.

See Also:

for more information about LDAP filters.

2.6.4 Searching the Directory by Using the C API

The C function ldap_search_s() performs a synchronous search of the directory.

The syntax for ldap_search_s()looks like this:

int ldap_search_s
LDAP*         ld,
char*         base,
int           scope,
char*         filter
int           attrsonly,
LDAPMessage** res

ldap_search_s works with several supporting functions to refine the search. The steps that follow show how all of these C functions fit into the program flow of a search operation. Chapter 8, "C API Reference", examines all of these functions in depth.

  1. Decide what attributes must be returned; then place them into an array of strings. The array must be null terminated.

  2. Initiate the search, using ldap_search_s(). Refine your search with scope options and filters.

  3. Obtain an entry from the result set, using either the ldap_first_entry() function or the ldap_next_entry() function.

  4. Obtain an attribute from the entry obtained in step 3. Use either the ldap_first_attribute() function or the ldap_next_attribute() function for this purpose.

  5. Obtain all the values for the attribute obtained in step 4; then copy these values into local variables. Use the ldap_get_values() function or the ldap_get_values_len() function for this purpose.

  6. Repeat step 4 until all attributes of the entry are examined.

  7. Repeat step 3 until there are no more entries.

Table 2-8 Arguments for ldap_search_s()

Argument Description

A valid LDAP session handle


The DN of the search base.


The breadth and depth of the DIT to be searched.


The filter used to select entries of interest.


The attributes of interest in the entries returned.


If set to 1, only returns attributes.


This argument returns the search results.

2.6.5 Searching the Directory by Using DBMS_LDAP

You use the function DBMS_LDAP.search_s()to perform directory searches if you use the PL/SQL API.

Here is the syntax for DBMS_LDAP.search_s():

FUNCTION search_s
ld       IN  SESSION,
base     IN  VARCHAR2,
scope    IN  PLS_INTEGER,
filter   IN  VARCHAR2,
attronly IN  PLS_INTEGER,
res      OUT MESSAGE

The function takes the arguments listed and described in Table 2-9.

Table 2-9 Arguments for DBMS_LDAP.search_s() and DBMS_LDAP.search_st()

Argument Description

A valid session handle


The DN of the base entry in the LDAP server where search should start


The breadth and depth of the DIT that must be searched


The filter used to select entries of interest


The attributes of interest in the entries returned


If set to 1, only returns the attributes


An OUT parameter that returns the result set for further processing

search_s works with several supporting functions to refine the search. The steps that follow show how all of these PL/SQL functions fit into the program flow of a search operation.

  1. Decide what attributes need to be returned; then place them into the DBMS_LDAP.STRING_COLLECTION data-type.

  2. Perform the search, using either DBMS_LDAP.search_s()or DBMS_LDAP.search_st(). Refine your search with scope options and filters.

  3. Obtain an entry from the result set, using eitherDBMS_LDAP.first_entry() or DBMS_LDAP.next_entry().

  4. Obtain an attribute from the entry obtained in step 3. Use either DBMS_LDAP.first_attribute() or DBMS_LDAP.next_attribute() for this purpose.

  5. Obtain all the values for the attribute obtained in step 4; then copy these values into local variables. Use either DBMS_LDAP.get_values() or DBMS_LDAP.get_values_len() for this purpose.

  6. Repeat step 4 until all attributes of the entry are examined.

  7. Repeat step 3 until there are no more entries.

2.7 Terminating the Session

This section contains these topics:

2.7.1 Terminating the Session by Using the C API

After an LDAP session handle is obtained and all directory-related work is complete, the LDAP session must be destroyed. In the C API, the ldap_unbind_s() function is used for this purpose.

ldap_unbind_s() has this syntax:

int ldap_unbind_s
        LDAP*    ld

A successful call to ldap_unbind_s()closes the TCP/IP connection to the directory. It de-allocates system resources consumed by the LDAP session. Finally it returns the integer LDAP_SUCCESS to its callers. After ldap_unbind_s()is invoked, no other LDAP operations are possible. A new session must be started with ldap_init().

2.7.2 Terminating the Session by Using DBMS_LDAP

The DBMS_LDAP.unbind_s() function destroys an LDAP session if the PL/SQL API is used. unbind_s has the following syntax:


unbind_s closes the TCP/IP connection to the directory. It de-allocates system resources consumed by the LDAP session. Finally it returns the integer DBMS_LDAP.SUCCESS to its callers. After the unbind_s is invoked, no other LDAP operations are possible. A new session must be initiated with the init function.