Mozilla LDAP SDK Programmer's Guide/Getting Server Information With LDAP Java SDK

From MozillaWiki
Jump to: navigation, search

This section explains how to access and modify information about your LDAP server over the LDAP protocol.

About DSEs

The acronym DSE refers to a DSA-specific entry in the directory. A DSA is a directory system agent, an X.500 term for a directory server. A DSE contains information specific to the server.

LDAP v3 uses the concept of the root DSE. In a directory tree, the root of the tree is the root DSE. The root DSE is not part of any naming context. In other words, the entry is superior to dc=example,dc=com, cn=config, and similar suffixes in the directory tree. Servers that do not support LDAP v3 therefore do not necessarily have a root DSE.

The root DSE can contain the following information:

  • The naming contexts the server supports, such as dc=example,dc=com or cn=config
  • URLs to alternate servers that can be contacted if the server is unavailable
  • The LDAP v3 extended operations the server supports
  • The LDAP v3 controls the server supports
  • The SASL mechanisms the server supports
  • The versions of LDAP the server supports
  • Additional, server-specific information

Getting the Root DSE With LDAP Java SDK

The root DSE for an LDAP server specifies information about the server. The attributes of the root DSE and what the attributes provide are shown here.

  • altServer: LDAP URLs that identify other servers to contact when the server is not available.
  • namingContexts: Naming contexts, such as dc=example,dc=com, supported by the server.
  • supportedControl: Object identifiers (OIDs) of LDAP v3 controls supported by the server.
    If this attribute is not present, the server does not support LDAP v3 controls.
  • supportedExtension: Object identifiers (OIDs) of LDAP v3 extended operations supported by the server.
    If this attribute is not present, the server does not support LDAP v3 extended operations.
  • supportedLDAPVersion: Versions of LDAP, 2 or 3, supported by the server.
  • supportedSASLMechanisms: Names of SASL mechanisms supported by the server.
    If this attribute is not present, the server does not support any SASL mechanisms.

To access the root DSE of an LDAP server, do the following:

  1. Turn off automatic referral handling, and connect to the LDAP server.
    See Creating a Connection and Setting Preferences With LDAP Java SDK and Connecting to an LDAP Server With LDAP Java SDK. See also Handling Referrals With Directory SDK for Java for instructions.
  2. Search the directory with the following criteria:
    • Set the search scope to a base search.
    • Specify an empty string for the base DN.
    • Use the search filter (objectclass=*).

Refer to Searching the Directory With LDAP Java SDK for instructions.

If an LDAPException is returned with a result code such as OPERATION_ERROR, PROTOCOL_ERROR, REFERRAL, or NO_SUCH_OBJECT, the LDAP server probably does not support LDAP v3.

The following code excerpt retrieves the root DSE, and then displays the attributes.

/* Create a new connection. */
LDAPConnection ld = new LDAPConnection();
String hostname = "localhost";
int portnumber = LDAPv3.DEFAULT_PORT;

try {
    /* Connect to the LDAP server. */
    ld.connect(3, hostname, portnumber);

    int MY_SCOPE = LDAPv3.SCOPE_BASE;
    String MY_FILTER = "(objectclass=*)";
    String MY_SEARCHBASE = "";
    LDAPSearchResults res = ld.search(MY_SEARCHBASE,
        MY_SCOPE, MY_FILTER, null, false);

    /* There should be only one result (the root DSE). */
    while (res.hasMoreElements()) {
        LDAPEntry findEntry = (LDAPEntry)res.nextElement();

        /* Get the attributes of the root DSE. */
        LDAPAttributeSet findAttrs = findEntry.getAttributeSet();
        Enumeration enumAttrs = findAttrs.getAttributes();

        /* Iterate through each attribute. */
        while (enumAttrs.hasMoreElements()) {
            LDAPAttribute anAttr = (LDAPAttribute)enumAttrs.nextElement();

            /* Get and print the attribute name. */
            String attrName = anAttr.getName();
            System.out.println(attrName);

            /* Get the values of the attribute. */
            Enumeration enumVals = anAttr.getStringValues();

            /* Get and print each value. */
            if (enumVals == null) {
                System.out.println("\tNo values found.");
                continue;
            }
            while (enumVals.hasMoreElements()) {
                String aVal = (String)enumVals.nextElement();
                System.out.println("\t" + aVal);
            }
        }
    }
} catch( LDAPException e ) {
    System.out.println("Error: " + e.toString());
}

Checking Support for LDAP v3 With LDAP Java SDK

You can determine what version an LDAP server supports by getting the supportedLDAPVersion attribute from the root DSE. This attribute should contain the value 3. The attribute can also contain other values, such as 2, so iterate through the values of this attribute.

You are not required to authenticate or bind before performing a search. Unlike LDAP v2, LDAP v3 states that clients do not need to bind to the server before performing LDAP operations. The following section of code connects to an LDAP server. The code then determines whether the server supports LDAP v3.

/* Create a new connection. */
LDAPConnection ld = new LDAPConnection();
String hostname = "localhost";
int portnumber = LDAPv3.DEFAULT_PORT;

boolean supportsV3 = false;

try {
    /* Connect to the LDAP server. */
    ld.connect( 3, hostname, portnumber );

    int MY_SCOPE = LDAPv3.SCOPE_BASE;
    String MY_FILTER = "(objectclass=*)";
    String MY_SEARCHBASE = "";
    LDAPSearchResults res = ld.search(MY_SEARCHBASE,
        MY_SCOPE, MY_FILTER, null, false);

    /* There should be only one result (the root DSE). */
    while (res.hasMoreElements()) {
        LDAPEntry findEntry = (LDAPEntry)res.nextElement();

        /* Get the supportedLDAPVersion attribute values. */
        LDAPAttribute versionAttr =
            findEntry.getAttribute("supportedLDAPVersion");
        
        /* Check for "3". */
        Enumeration enumVals = versionAttr.getStringValues();
        if (enumVals == null) {
            System.out.println("\tNo values found.");
            continue;
        }
        while (enumVals.hasMoreElements()) {
            String aVal = (String)enumVals.nextElement();
            if (aVal.equalsIgnoreCase("3")) {
                supportsV3 = true;
                break;
            }
        }
    }
} catch( LDAPException e ) {
    System.out.println("Error: " + e.toString());
}

if (supportsV3) {
    System.out.println("This server supports LDAP v3.");
} else {
    System.out.println("This server does not support LDAP v3.");
}

Getting Schema Information With LDAP Java SDK

In LDAP v3, you can get LDAP schema over LDAP. You can also modify schema over LDAP. This section explains how to carry out such modifications.

Understanding Schema Over LDAP

An entry can specify the schema that defines the object classes, attributes, syntaxes, and matching rules used by the directory. This entry is called the subschema entry.

To find the DN of the subschema entry, get the subschemaSubentry operational attribute from the root DSE or from any entry. This code excerpt demonstrates how to retrieve the subschema entry DN.

LDAPConnection ld = null;
try {
    ld = new LDAPConnection();
    ld.connect("localhost", LDAPv3.DEFAULT_PORT);

    String [] schemaAttr = {"subschemaSubentry"};
    LDAPEntry rootDSE = ld.read("", schemaAttr);
    LDAPAttribute resAttr = rootDSE.getAttribute(schemaAttr[0]);
    Enumeration enumVals = resAttr.getStringValues();
    if (enumVals != null) {
        while (enumVals.hasMoreElements()) {
            System.out.println(schemaAttr[0] + ": " +
                (String)enumVals.nextElement());
        }
    }
    ld.disconnect();
} catch(LDAPException e) {
    System.out.println("Error: " + e.toString());
}

The subschema entry can have the following attributes.

  • objectClasses: Specifies the object class definitions in the schema. Each value of this attribute is an object class that is known to the server.
  • attributeTypes: Specifies the attribute type definitions in the schema.
    Each value of this attribute is an attribute type that is known to the server.
  • matchingRules: Specifies the matching rule definitions in the schema.
    Each value of this attribute is a matching rule that is known to the server.
  • matchingRuleUse: Specifies the use of a matching rule in the schema.
    Each value of this attribute is a matching rule use description. A matching rule use description specifies the OIDs of the attributes that can be used with this extensible matching rule.
  • syntaxes: Specifies the syntax definitions in the schema.
    Each value of this attribute is syntax that is known to the server.

In LDAP Java SDK, the schema and elements in the schema are represented by classes in the netscape.ldap package. These classes include the following.

  • LDAPSchema: Schema used by an LDAP server
  • LDAPSchemaElement: Base class that represents a generic element in the schema
  • LDAPObjectClassSchema: Object class description in the schema
  • LDAPAttributeSchema: Attribute type description in the schema
  • LDAPMatchingRuleSchema: Matching rule description in the schema
  • LDAPMatchingRuleUseSchema: Use of a matching rule in the schema
  • LDAPSyntaxSchema: Syntax description in the schema

These classes with their methods handle the subschema entry by using standard LDAP operations, such as search and modify.

Getting Information About LDAP Schema

To get the schema for an LDAP v3 server, construct a new LDAPSchema object. Then, invoke the fetchSchema method, passing in an LDAPConnection object.

LDAPConnection ld = new LDAPConnection();
/* Construct an LDAPSchema object to hold the schema to retrieve. */
LDAPSchema dirSchema = new LDAPSchema();
try {
    ld.connect(hostname, portnumber, bindDN, bindPW);
    /* Get the schema. Anonymous access is OK. */
    dirSchema.fetchSchema(ld);
    /* Use the schema. */
} catch (Exception e) {
    System.err.println(e.toString());
}

Working With Object Class Descriptions

In the LDAP Java classes, the object class descriptions in a schema are represented by objects of the LDAPObjectClassSchema class. To get the object class descriptions from the schema, invoke one of the following methods:

  • To get an enumeration of LDAPObjectClassSchema objects that represent the object classes in the schema, invoke the getObjectClasses method.
  • To get a specific object class description, invoke the getObjectClass method and pass in the name of the object class.
  • To get an enumeration of the names of object classes in the schema, invoke the getObjectClassNames method.

An object class description consists of the following information, which you can retrieve by invoking methods of the LDAPObjectClassSchema object:

  • An OID that identifies the object class, retrieved by invoking the getOID method
  • A name that identifies the object class, retrieved by invoking the getName method
  • A description that identifies the object class, retrieved by invoking the getDescription method
  • A name that identifies the parent object class, retrieved by invoking the getSuperior method
  • The list of required attributes, retrieved by invoking the getRequiredAttributes method
  • The list of optional attributes that are allowed, retrieved by invoking the getOptionalAttributes method

To add an object class description to the schema, construct a new LDAPObjectClassSchema object. You can specify the pieces of information in the object as individual arguments or in a description formatted according to RFC 4517, Lightweight Directory Access Protocol (LDAP): Syntaxes and Matching Rules.

Then, you can either invoke the add method of this object or the addObjectClass method of the LDAPSchema object.

To remove an object class description, invoke the remove method of this object.

Working With Attribute Type Descriptions

In the LDAP Java classes, the attribute type descriptions in a schema are represented by objects of the LDAPAttributeSchema class.

To get the attribute type descriptions from the schema, invoke one of the following methods:

  • To get an enumeration of LDAPAttributeSchema objects that represent the attribute types in the schema, invoke the getAttributes method.
  • To get a specific attribute type description, invoke the getAttribute method and pass in the name of the attribute type.
  • To get an enumeration of the names of attribute types in the schema, invoke the getAttributeNames method.

An attribute type description consists of the following information, which you can retrieve by invoking methods of the LDAPAttributeSchema object:

  • An OID that identifies the attribute type, retrieved by invoking the getOID method
  • A name that identifies the attribute type, retrieved by invoking the getName method
  • A description that identifies the attribute type, retrieved by invoking the getDescription method
  • The syntax used by the attribute type, retrieved by invoking the getSyntax method
  • An indication whether the attribute type is single-valued or multivalued, retrieved by invoking the isSingleValued method

To add an attribute type description to the schema, construct a new <classname>LDAPAttributeSchema</classname> object. You can specify the pieces of information in the object as individual arguments or in a description formatted according to RFC 4517, Lightweight Directory Access Protocol (LDAP): Syntaxes and Matching Rules.

Then, you can either invoke the add method of this object or the addAttributeType method of the LDAPSchema object.

To remove an attributeType description, invoke the remove method of this object.

Working With Matching Rule Descriptions

In the LDAP Java classes, the matching rule and matching rule use descriptions in a schema are represented by objects of the LDAPMatchingRuleSchema class. To get the matching rule descriptions from the schema, invoke one of the following methods:

  • To get an enumeration of LDAPMatchingRuleSchema objects that represent the matching rules in the schema, invoke the getMatchingRules method.
  • To get a specific matching rule description, invoke the getMatchingRule method and pass in the name of the matching rule.
  • To get an enumeration of the names of matching rules in the schema, invoke the getMatchingRuleNames method.

A matching rule description consists of the following information, which you can retrieve by invoking methods of the LDAPMatchingRuleSchema object:

  • An OID that identifies the matching rule, retrieved by invoking the getOID method
  • A name that identifies the matching rule, retrieved by invoking the getName method
  • A description that identifies the matching rule, retrieved by invoking the getDescription method
  • The syntax of the matching rule, retrieved by invoking the getSyntax method

To add a matching rule description to the schema, construct a new LDAPMatchingSchema object. You can specify the pieces of information in the object as individual arguments or in a description formatted according to RFC 4517, Lightweight Directory Access Protocol (LDAP): Syntaxes and Matching Rules.

Then, you can either invoke the add method of this object or the addMatchingRule method of the LDAPSchema object.

To remove a matching rule description, invoke the remove method of this object.

Example of Working With Schema

The following example illustrates how to get the schema and how to add object classes and attribute types.

import netscape.ldap.*;
import java.util.*;
 
public class GetSchema {
    public static void main(String[] args) {
        try {
            UserArgs userArgs = new UserArgs("GetSchema", args, true);
            LDAPConnection ld = new LDAPConnection();
            ld.connect(userArgs.getHost(), userArgs.getPort());
            ld.authenticate(userArgs.getBindDN(), userArgs.getPassword());
 
            /* Get the schema. */
            LDAPSchema dirSchema = new LDAPSchema();
            dirSchema.fetchSchema(ld);
 
            /* Get and print the inetOrgPerson object class. */
            LDAPObjectClassSchema objClass =
                dirSchema.getObjectClass("inetOrgPerson");
            if (objClass != null)
                System.out.println("inetOrgPerson := " +
                    objClass.toString());
 
            /* Get and print the userPassword attribute. */
            LDAPAttributeSchema attrType =
                dirSchema.getAttribute("userpassword");
            if (attrType != null)
                System.out.println("userPassword := " +
                    attrType.toString());
 
            /* Add a new object class. Requires write access. */
            String[] requiredAttrs = {"cn", "mail"};
            String[] optionalAttrs = {"sn", "telephoneNumber"};
            LDAPObjectClassSchema newObjClass =
                new LDAPObjectClassSchema("newInetOrgPerson",
                    "1.2.3.4.5.6.7", "top", "Experiment",
                    requiredAttrs, optionalAttrs);
 
            /* Add the new object class to the schema. */
            newObjClass.add(ld);
 
            /* Create a new attribute type "hairColor". */
            LDAPAttributeSchema newAttrType =
                new LDAPAttributeSchema("hairColor",
                    "1.2.3.4.5.4.3.2.1", "Blonde, red, etc",
                    LDAPAttributeSchema.cis, false);
 
            /* Add the new attribute type to the schema. */
            newAttrType.add(ld);
 
            /* Fetch schema again to verify changes */
            dirSchema.fetchSchema(ld);
 
            /* Get and print the new attribute type. */
            newAttrType = dirSchema.getAttribute("hairColor");
            if (newAttrType != null)
                System.out.println("hairColor := " +
                    newAttrType.toString());
 
            /* Get and print the new object class. */
            newObjClass = dirSchema.getObjectClass("newInetOrgPerson");
            if (newObjClass != null)
                System.out.println("newInetOrgPerson := " +
                    newObjClass.toString());
 
            ld.disconnect();
        } catch ( Exception e ) {
            System.err.println(e.toString());
            System.exit(1);
        }
    }
}