Skip Headers

Oracle® Internet Directory Application Developer's Guide
10g (9.0.4)

Part Number B10461-01
Go To Documentation Library
Home
Go To Product List
Solution Area
Go To Table Of Contents
Contents
Go To Index
Index

Go to previous page Go to next page

3
Developing Applications with Oracle Extensions to the Standard LDAP APIs

This chapters explains the concepts behind Oracle extensions to LDAP APIs, and describes the abstract entities that are modeled by the extensions as well as the usage model of those extensions.

This chapter contains these topics:

Overview of Oracle Extensions to the Standard API

Based on the entities on which they operate, the functionalities provided by the API extensions can be categorized as follows:

The primary users of the extensions described in this chapter are backend applications that must perform LDAP lookups for users, groups, applications, or hosted companies. This section describes how these applications integrate these API extensions into their logic--that is, the usage of the API extensions only. It contains these topics:

Figure 3-1 shows the placement of the API extensions in relation to existing APIs:

Figure 3-1 Oracle API Extensions

Text description of oiddg008.gif follows

Text description of the illustration oiddg008.gif

As Figure 3-1 shows, in the PL/SQL and Java languages, the API extensions are layered on top of existing APIs:

Applications must access the underlying APIs for such common things as establishing and closing connections, and looking up directory entries not covered by the API extensions.

Figure 3-2 shows the programmatic flow of control for using the API extensions described in this chapter.

Figure 3-2 Programmatic Flow of API Extensions

Text description of oiddg009.gif follows

Text description of the illustration oiddg009.gif

As Figure 3-2 shows, the applications first establish a connection to Oracle Internet Directory. They can then use existing API functions and the API extensions interchangeably.

Using the API Extensions in PL/SQL

Most of the extensions described in this chapter provide helper functions to access data in relation to such specific LDAP entities as users, groups, realms, and applications. In many cases, you must pass a reference to one of these entities to the API functions. These API extensions use opaque data structures, called handles. For example, an application that needs to authenticate a user would follow these steps:

  1. Establish an LDAP connection, or get it from a pool of connections.

  2. Create a user handle based on user input. This could be a DN, or a GUID, or a simple Oracle Application Server Single Sign-On ID.

  3. Authenticate the user with the LDAP connection handle, user handle, and credentials.

  4. Free the user handle.

  5. Close the LDAP connection, or return the connection back to the pool of connections.

Figure 3-3 illustrates this usage model.

Figure 3-3 Programming Abstractions for the PL/SQL Language

Text description of orclapi4.gif follows

Text description of the illustration orclapi4.gif

Using the API Extensions in Java

This section describes:

The oracle.java.util Package

Instead of handles, LDAP entities--that is, users, groups, realms, and applications--are modeled as Java objects in the oracle.java.util package. All other utility functionality is modeled either as individual objects--as, for example, GUID--or as static member functions of a utility class.

For example, to authenticate a user, an application must follow these steps:

  1. Create oracle.ldap.util.user object, given the user DN.

  2. Create a DirContext JNDI object with all of the required properties, or get one from a pool of DirContext objects.

  3. Invoke the User.authenticate function, passing in a reference to the DirContext object and the user credentials.

  4. If DirContext object was retrieved from a pool of existing DirContext objects, return it to that pool.

Unlike C and PL/SQL, Java language usage does not need to explicitly free objects because the Java garbage collection mechanism can do it.

PropertySetCollection, PropertySet, and Property Classes

Many of the methods in the user, subscriber, and group classes return a PropertySetCollection object. The object represents a collection of results. It is a collection of one or more LDAP entries. Each of these entries is represented by a PropertySet object, identified by a DN. A property set can contain attributes, each represented as a property. A property is a collection of one or more values for the particular attribute it represents. An example of the use of these classes follows:

PropertySetCollection psc = Util.getGroupMembership( ctx,
                                                     myuser,
                                                     null,
                                                     true );
    // for loop to go through each PropertySet
    for (int i = 0; i < psc.size(); i++ ) {

    PropertySet ps = psc.getPropertySet(i);

    // Print the DN of each PropertySet
    System.out.println("dn:  " + ps .getDN());

    // Get the values for the "objectclass" Property
    Property objectclass = ps.getProperty( "objectclass" );

    // for loop to go through each value of Property "objectclass"
    for (int j = 0; j< objectclass.size(); j++) {
		
        // Print each "objectclass" value
        System.out.println("objectclass:  " + objectclass.getValue(j));
    }
}

The entity myuser is a user object. The psc object contains all the nested groups that myuser belongs to. The code loops through the resulting entries and prints out all the objectclass values of each entry.

See Also:

"Java Sample Code" for more sample uses of the PropertySetCollection, PropertySet, and Property classes

Installation and First Use of Oracle Extensions to the Standard API

Table 3-1 provides information about installation and first use for each API.

Table 3-1  Information about Installation and First Use
Language Installation and First Use Information

Java API

Installed as part of the LDAP client installation.

PL/SQL API

Installed as part of the Oracle9i Database Server. You must load it by using a script, called catldap.sql, located in $ORACLE_HOME/rdbms/admin.

C API

To build applications with the C API, you need to:

Include the header file located at $ORACLE_HOME/ldap/public/ldap.h.

Dynamically link to the library located at $ORACLE_HOME/lib/libclntsh.so.9.0.

User Management Functionality

This section describes user management functionality for the Java, PL/SQ, and C L LDAP APIs.

Directory-enabled applications need to access Oracle Internet Directory for the following user-related operations:

A user is typically identified by the applications by one of the following techniques:

This section contains these topics:

User Management APIs

This section summarizes the user management functionality of each API.

Java API for User Management Functionality

As described in the example in the previous section, all user-related functionality is abstracted in a Java class called oracle.ldap.util.User. The high-level usage model for this functionality is:

  1. Construct oracle.ldap.util.User object based on DN, GUID, or simple name.

  2. Invoke User.authenticate(DirContext, Credentials) to authenticate the user if necessary.

  3. Invoke User.getProperties(DirContext) to get the attributes of the user entry itself.

  4. Invoke User.getExtendedProperties(DirContext, PropCategory, PropType) to get the extended properties of the user. PropCategory here is either shared or application-specific. PropType is the object representing the type of property desired. If PropType is NULL, then all properties in a given category are retrieved.

  5. Invoke PropertyType.getDefinition(DirContext) to get the metadata required to parse the properties returned in step 4.

  6. Parse the extended properties and continue with application-specific logic. This parsing is also done by the application specific logic.

C API for User Management Functionality

Oracle Internet Directory 10g (9.0.4) does not support the C API for user management functionality.

User Authentication

This section describes user authentication functionality for the Java, PL/SQ, and C L LDAP APIs.

Java API for User Authentication

User authentication is a common LDAP operation that essentially compares a particular attribute and its attribute value. Oracle Internet Directory supports the following:

The following is a piece of sample code demonstrating the usage:

        // User user1 - is a valid User Object
        try
        {
                user1.authenticateUser(ctx,
User.CREDTYPE_PASSWD, ?welcome?);

                // or
                // user1.authenticateUser(ctx, <any
attribute>, <attribute value>);
        }
        catch (UtilException ue)
        {
                // Handle the password policy error
accordingly
                if (ue instanceof PasswordExpiredException)
                        // do something
                else if (ue instanceof GraceLoginException)
                        // do something
        }

C API for User Authentication

Oracle Internet Directory 10g (9.0.4) does not support the C API for user authentication functionality.

User Creation

This section describes user creation functionality for the Java, PL/SQ, and C L LDAP APIs.

Java API for User Creation

The subscriber class offers the createUser() method to programmatically create users. The object classes required by a user entry are configurable through Oracle Delegated Administration Services. The createUser() method assumes that the client understands the requirement and supplies the values for the mandatory attributes during user creation. If the programmer does not supply the required information the server will return an error.

The following snippet of sample code demonstrates the usage.

// Subscriber sub is a valid Subscriber object
// DirContext ctx is a valid DirContext

// Create ModPropertySet object to define all the attributes and their values. 
ModPropertySet mps = new ModPropertySet();
mps.addProperty(LDIF.ATTRIBUTE_CHANGE_TYPE_ADD,?cn?, ?Anika?);
mps.addProperty(LDIF.ATTRIBUTE_CHANGE_TYPE_ADD,?sn?, ?Anika?);
mps.addProperty(LDIF.ATTRIBUTE_CHANGE_TYPE_ADD,?mail?, 
?Anika@oracle.com?);

// Create user by specifying the nickname and the ModPropertySet defined above
User newUser = sub.createUser( ctx, mps);

// Print the newly created user DN
System.out.println( newUser.getDN(ctx) );
        
// ? perform other operations with this new user

PL/SQL API for User Creation

Oracle Internet Directory 10g (9.0.4) does not support the PL/SQL API for user creation functionality.

C API for User Creation

Oracle Internet Directory 10g (9.0.4) does not support the PL/SQL API for user creation functionality.

User Object Retrieval

This section describes user object retrieval functionality for the Java, PL/SQ, and C L LDAP APIs.

Java API for User Object Retrieval

The subscriber class offers the getUser() method to replace the public constructors of the User class. A user object is returned based on the specified information.

The following is a piece of sample code demonstrating the usage:

// DirContext ctx is contains a valid OID connection with
sufficient privilege to perform the operations

// Creating RootOracleContext object
RootOracleContext roc = new RootOracleContext(ctx);

// Obtain a Subscriber object representing the default
subscriber
Subscriber sub = roc.getSubscriber(ctx,
Util.IDTYPE_DEFAULT, null, null);

// Obtain a User object representing the user whose
nickname is ?Anika?
User user1 = sub.getUser(ctx, Util.IDTYPE_SIMPLE, ?Anika?,
null);
// ? do work with this user

The getUser() method can retrieve users based on DN, GUID
and simple name.  A getUsers() method is also available to
perform a filtered search to return more than one user at a
time.  The returned object is an array of User objects.
For example,

// Obtain an array of User object where the users? nickname
starts with ?Ani?
User[] userArr = sub.getUsers(ctx, Util.IDTYPE_SIMPLE,
?Ani*?, null);
// ? do work with the User array

PL/SQL API for User Object Retrieval

Oracle Internet Directory 10g (9.0.4) does not support the PL/SQL API for user object retrieval functionality.

C API for User Object Retrieval

Oracle Internet Directory 10g (9.0.4) does not support the C API for user object retrieval functionality.

Group Management Functionality

This section describes the group management functionality for the Java, PL/SQ, and C L LDAP APIs.

Groups are modeled in Oracle Internet Directory as a collection of distinguished names. Directory-enabled applications need to access Oracle Internet Directory to get the properties of a group, and verify that a given user is a member of that group.

A group is typically identified by one of the following:

Identity Management Realm Functionality

This section describes the identity management realm functionality for the Java, PL/SQ, and C L LDAP APIs.

An identity management realm is an entity or organization that subscribes to the services offered in the Oracle product stack. Directory-enabled applications need to access Oracle Internet Directory to get realm properties--for example, user search base or password policy.

A realm is typically identified by one of the following:

Realm Object Retrieval for the Java API

The RootOracleContext class represents the root Oracle Context. Much of the information needed for identity management realm creation is stored within the root Oracle Context. The RootOracleContext class offers the getSubscriber() method. It replaces the public constructors of the subscriber class and returns an identity management realm object based on the specified information.

The following is a piece of sample code demonstrating the usage:

        // DirContext ctx is contains a valid OID
connection with sufficient privilege to perform the
operations

        // Creating RootOracleContext object
        RootOracleContext roc = new RootOracleContext(ctx);

        // Obtain a Subscriber object representing the
Subscriber with simple name ?Oracle?
        Subscriber sub = roc.getSubscriber(ctx,
Util.IDTYPE_SIMPLE, ?Oracle?, null);

     // ? do work with the Subscriber object 

Server Discovery Functionality

Directory server discovery (DSD) enables automatic discovery of the Oracle directory server by directory clients. It allows deployments to manage the directory host name and port number information in the central DNS server. All directory clients perform a DNS query at runtime and connect to the directory server. Directory server location information is stored in a DNS service location record (SRV).

An SRV contains:

DSD also allows clients to discover the directory host name information from the ldap.ora file itself.

This section contains these topics:

Benefits of Oracle Internet Directory Discovery Interfaces

Typically, the LDAP host name and port information is provided statically in a file called ldap.ora which is located on the client in $ORACLE_HOME/network/admin. For large deployments with many clients, this information becomes very cumbersome to manage. For example, each time the host name or port number of a directory server is changed, the ldap.ora file on each client must be modified.

Directory server discovery eliminates the need to manage the host name and port number in the ldap.ora file. Because the host name information resides on one central DNS server, the information must be updated only once. All clients can then discover the new host name information dynamically from the DNS when they connect to it.

DSD provides a single interface to obtain directory server information without regard to the mechanism or standard used to obtain it. Currently, Oracle directory server information can be obtained either from DNS or from ldap.ora using a single interface.

Usage Model for Discovery Interfaces

The first step in discovering host name information is to create a discovery handle. A discovery handle specifies the source from which host name information will be discovered. In case of the Java API, the discovery handle is created by creating an instance of oracle.ldap.util.discovery.DiscoveryHelper class.

DiscoveryHelper disco = new DiscoveryHelper(DiscoveryHelper.DNS_DISCOVER);

The argument DiscoveryHelper.DNS_DISCOVER specifies the source. In this case the source is DNS.

Each source may require some inputs to be specified for discovery of host name information. In case of DNS these inputs are:

Detailed explanation of these options is given in Determining Server Name and Port Number From DNS.

// Set the property for the DNS_DN
disco.setProperty(DiscoveryHelper.DNS_DN,"dc=us,dc=fiction,dc=com");
// Set the property for the DNS_DISCOVER_METHOD
disco.setProperty(DiscoveryHelper.DNS_DISCOVER_METHOD
                                 ,DiscoveryHelper.USE_INPUT_DN_METHOD);
// Set the property for the SSLMODE                                        
disco.setProperty(DiscoveryHelper.SSLMODE,"0");

Now the information can be discovered.

// Call the discover method
disco.discover(reshdl);

The discovered information is returned in a result handle (reshdl object in above case). Now the results can be extracted from the result handle.

ArrayList result =
(ArrayList)reshdl.get(DiscoveryHelper.DIR_SERVERS);

if (result != null)
{
   if (result.size() == 0) return;
   System.out.println("The hostnames are :-");
   for (int i = 0; i< result.size();i++)
   {
      String host = (String)result.get(i);
System.out.println((i+1)+".	'"+host+"'");
   }
}

Determining Server Name and Port Number From DNS

Determining a host name and port number from a DNS lookup involves obtaining a domain and then searching for SRV resource records based on that domain. If there is more than one SRV resource record, then they are sorted on the basis of their weights and priorities. The SRV resource records contain host names and port numbers required for connection. This information is retrieved from the resource records and returned to the user.

There are three approaches for determining the domain name required for lookup:

Mapping the DN of the Naming Context

The first approach is to map the distinguished name (DN) of naming context into domain name using the algorithm given here.

The output domain name is initially empty. The DN is processed sequentially from right to left. An RDN is able to be converted if it meets the following conditions:

If the RDN can be converted, then the attribute value is used as a domain name component (label).

The first such value becomes the rightmost, and the most significant, domain name component. Successive converted RDN values extend to the left. If an RDN cannot be converted, then processing stops. If the output domain name is empty when processing stops, then the DN cannot be converted into a domain name.

For the DN cn=John Doe,ou=accounting,dc=example,dc=net, the client converts the dc components into the DNS name example.net.

Search by Domain Component of Local Machine

Sometimes a DN cannot be mapped to a domain name. For example, the DN o=Oracle IDC, Bangalore cannot be mapped to a domain name. In this case, the second approach uses the domain component of local machine on which the client is running. For example, if the client machine domain name is mc1.acme.com, then the domain name for the lookup is acme.com.

Search by Default SRV Record in DNS

The third approach looks for a default SRV record in the DNS. This record points to the default server in the deployment. The domain component is for this default record is _default.

Once the domain name has been determined, it is used to send a query to DNS. The DNS is queried for SRV records specified in Oracle Internet Directory-specific format. For example, if the domain name obtained is example.net, then, for non-SSL LDAP servers, the query is for SRV resource records having the owner name _ldap._tcp._oid.example.net.

It is possible that no SRV resource records are returned from the DNS. In such a case the DNS lookup is performed for the SRV resource records specified in standard format. For example, the owner name would be _ldap._tcp.example.net.

See Also:

"Oracle Directory Server Administration" in the Oracle Internet Directory Administrator's Guide

The result of the query is a set of SRV records. These records are then sorted and the host information is extracted from them. This information is then returned to the user.


Note:

The approaches mentioned here can also be tried in succession, stopping when the query lookup of DNS is successful. Try the approaches in the order as described in this section. DNS is queried only for SRV records in Oracle Internet Directory-specific format. If none of the approaches is successful, then all the approaches are tried again, but this time DNS is queried for SRV records in standard format.


Environment Variables for DNS Server Discovery

The following environment variables have been provided for overriding the default DSD behavior.

Table 3-2  Environment Variables for DSD Behavior
Environment Variable Description

ORA_LDAP_DNS

IP address of the DNS server containing the SRV records. If the variable is not defined, then the DNS server address is obtained from the host machine.

ORA_LDAP_DNSPORT

Port number on which the DNS server listens for queries. If the variable is not defined, then the DNS server is assumed to be listening at standard port number 53.

ORA_LDAP_DOMAIN

Domain of the host machine. If the variable is not defined, then the domain is obtained from the host machine itself.

Programming Interfaces for DNS Server Discovery

The programming interface provided is a single interface to discover directory server information without regard to the mechanism or standard used to obtain it. Information can be discovered from various sources. Each source can use its own mechanism to discover the information. For example, the LDAP host and port information can be discovered from the DNS acting as the source. Here DSD is used to discover host name information from the DNS.

See Also:

For detailed reference information and class descriptions, refer to the Javadoc located on the product CD.

Java APIs for Server Discovery

A new Java class, the public class, has been introduced:

public     class                 oracle.ldap.util.discovery.DiscoveryHelper

This class provides a method for discovering specific information from the specified source.

Table 3-3  Methods for Directory Server Discovery
Method Description

discover

Discovers the specific information from a given source

setProperty

Sets the properties required for discovery

getProperty

Accesses the value of properties

Two new methods are added to the existing Java class oracle.ldap.util.jndi.ConnectionUtil:

Examples: Java API for Directory Server Discovery

The following is a sample Java program for directory server discovery:

import java.util.*;
import java.lang.*;
import oracle.ldap.util.discovery.*;
import oracle.ldap.util.jndi.*;

public class dsdtest
{
  public static void main(String s[]) throws Exception
  {
    HashMap reshdl = new HashMap();
    String result = new String();
    Object resultObj = new Object();
    DiscoveryHelper disco = new
DiscoveryHelper(DiscoveryHelper.DNS_DISCOVER);

// Set the property for the DNS_DN
disco.setProperty(DiscoveryHelper.DNS_DN,"dc=us,dc=fiction,dc=com")
;

// Set the property for the DNS_DISCOVER_METHOD
disco.setProperty(DiscoveryHelper.DNS_DISCOVER_METHOD
                                 ,DiscoveryHelper.USE_INPUT_DN_METHOD);

// Set the property for the SSLMODE
disco.setProperty(DiscoveryHelper.SSLMODE,"0");

// Call the discover method
int res=disco.discover(reshdl);
if (res!=0)
   System.out.println("Error Code returned by the discover method is :"+res) ;

// Print the results
printReshdl(reshdl);
}

public static void printReshdl(HashMap reshdl)
{
  ArrayList result = (ArrayList)reshdl.get(DiscoveryHelper.DIR_SERVERS);

if (result != null)
{
  if (result.size() == 0) return;
  System.out.println("The hostnames are :-");
  for (int i = 0; i< result.size();i++)
  {
      String host = (String)result.get(i);
      System.out.println((i+1)+".	'"+host+"'");
   }
  }
 }
}

Resource Information Management Functionality

To fulfill the requests of users, some Oracle components gather data from various repositories and services. To gather the data, these components require the following information:

This section contains these topics:

Resource Type Information

Information about the resources that an application uses to service a user request is called resource type information. A resource type can be, for example, an Oracle9i Database Server or a Java Database Connectivity Pluggable Data Source. Resource type information includes such items as the class used to authenticate a user, the user identifier, and the password.

You specify resource type information by using the Oracle Internet Directory Self-Service Console.

Resource Access Information

Information for connecting and authenticating users to the databases is called resource access information. It is stored in an entry called a resource access descriptor (RAD) from which it can be retrieved and shared by various Oracle components.

For example, to service the request of a user for a sales report, Oracle Application Server Reports Services queries multiple databases. When it does this, it does the following:

  1. Retrieves the necessary connect information from the RAD

  2. Uses that information to connect to those databases and to authenticate the user requesting the data

Once it has done this, it compiles the report.

You specify resource access information by using the Oracle Internet Directory Self-Service Console. You can specify resource access information for each individual user or commonly for all users. In the latter case, all users connecting to a given application use, by default, the same information to connect to the necessary databases. Oracle Corporation recommends defining default resource access information whenever an application has its own integrated account management--for example, where each user is defined withn the application itself by means of a unique songle sign-on user name.

Location of Resource Information in the DIT

Figure 3-4 shows where resource information is located in the DIT.

Figure 3-4 Placement of Resource Access and Resource Type Information in the DIT

Text description of oidag126.gif follows

Text description of the illustration oidag126.gif

As Figure 3-4 shows, the resource access and resource type information is stored in the Oracle Context.

Resource access information for each user is stored in the cn=User Extensions node in the Oracle Context. In this example, the cn=User Extensions node contains resource access information for both the default user and for specific users. In the latter cases, the resource access information includes that needed for accessing both the Sales and the Bug databases.

Resource access information for each application is stored in the object identified by the application name--in this example, cn=Oracle Application Server Reports Services, cn=Products,cn=Oracle Context,dc=us,dc=acme,dc=com. This is the user information specific to that product.

Resource type information is stored in the container cn=resource types, cn=common,cn=products,cn=Oracle Context.

See Also:

SASL Authentication Functionality

Oracle Internet Directory supports two mechanisms for SASL-based authentication. This section describes the two methods. It contains these topics:

SASL Authentication by Using the DIGEST-MD5 Mechanism

SASL Digest-MD5 authentication is the required authentication mechanism for LDAP Version 3 servers (RFC 2829). LDAP Version 2 does not support Digest-MD5.

The Digest-MD5 mechanism is described in RFC 2831 of the Internet Engineering Task Force. It is based on the HTTP Digest Authentication (RFC 2617).

See Also:

Internet Engineering Task Force Web site: http://www.ietf.org for RFCs 2829, 2831, and 2617

This section contains these topics:

Steps Involved in SASL Authentication by Using DIGEST-MD5

SASL Digest-MD5 authenticates a user as follows:

  1. The directory server sends data that includes various authentication options that it supports and a special token to the LDAP client.

  2. The client responds by sending an encrypted response that indicates the authentication options that it has selected. The response is encrypted in such a way that proves that the client knows its password.

  3. The directory server then decrypts and verifies the client's response.

To use the Digest-MD5 authentication mechanism, you can use either the Java API or the C API to set up the authentication.

JAVA APIs for SASL Authentication by Using DIGEST-MD5

Context.SECURITY_AUTHENTICATION = "DIGEST-MD5".

Context.SECURITY_PRINCIPAL sets to the principal name.

The principal name is a server-specific format. It can be either of the following:

The Oracle directory server accepts just a fully qualified DN such as cn=user,ou=my department,o=my company.


Note:

The SASL DN must be normalized before it is passed to the C or Java API that calls the SASL bind. To generate SASL verifiers, Oracle Internet Directory supports only normalized DNs.


See Also:

"JNDI Sample Code"

C APIs for SASL authentication using DIGEST-MD5

An LDAP client can use the provided C APIs to set up SASL digest MD5 to connect to the directory server.

See Also:

SASL Authentication by Using External Mechanism

The following is from section 7.4 of RFC 2222 of the Internet Engineering Task Force.

Oracle Internet Directory provides the SASL external mechanism over an SSL mutual connection. The authorization identity (DN) is derived from the client certificate during the SSL network negotiation.

Dependencies and Limitations for the PL/SQ LDAP API

The PL/SQL LDAP API for this release has the following limitations:


Go to previous page Go to next page
Oracle
Copyright © 1999, 2003 Oracle Corporation.

All Rights Reserved.
Go To Documentation Library
Home
Go To Product List
Solution Area
Go To Table Of Contents
Contents
Go To Index
Index