From 2dddd0e4b83f2fbe48431098ee624e763c49e975 Mon Sep 17 00:00:00 2001
From: Mark Craig <mark.craig@forgerock.com>
Date: Mon, 02 Jan 2012 16:50:03 +0000
Subject: [PATCH] Some information on reading the root DSE

---
 opendj3/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/getinfo/Main.java         |  193 +++++++++++++++++++++
 opendj3/src/main/docbkx/dev-guide/chap-extended-ops.xml                                                |   48 +++++
 opendj3/src/main/docbkx/dev-guide/chap-getting-directory-info.xml                                      |  141 +++++++++++++++
 opendj3/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/getinfo/package-info.java |   34 +++
 opendj3/src/main/docbkx/dev-guide/chap-controls.xml                                                    |   68 +++++++
 5 files changed, 477 insertions(+), 7 deletions(-)

diff --git a/opendj3/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/getinfo/Main.java b/opendj3/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/getinfo/Main.java
new file mode 100644
index 0000000..5ca3b6a
--- /dev/null
+++ b/opendj3/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/getinfo/Main.java
@@ -0,0 +1,193 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opendj3/legal-notices/CDDLv1_0.txt
+ * or http://forgerock.org/license/CDDLv1.0.html.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opendj3/legal-notices/CDDLv1_0.txt.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2012 ForgeRock AS
+ */
+package org.forgerock.opendj.examples.getinfo;
+
+import java.io.IOException;
+
+import org.forgerock.i18n.LocalizedIllegalArgumentException;
+import org.forgerock.opendj.ldap.Connection;
+import org.forgerock.opendj.ldap.ErrorResultException;
+import org.forgerock.opendj.ldap.LDAPConnectionFactory;
+import org.forgerock.opendj.ldap.ResultCode;
+import org.forgerock.opendj.ldap.SearchScope;
+import org.forgerock.opendj.ldap.responses.SearchResultEntry;
+import org.forgerock.opendj.ldif.LDIFEntryWriter;
+
+
+
+/**
+ * Demonstrates accessing server information about capabilities and schema.
+ */
+public final class Main
+{
+  // Connection information
+  private static String host;
+  private static int port;
+  // The kind of server information to request (all, controls, extops)
+  private static String infoType;
+
+
+
+  /**
+   * Access the directory over LDAP to request information about capabilities
+   * and schema.
+   *
+   * @param args The command line arguments
+   */
+  public static void main(final String[] args)
+  {
+    parseArgs(args);
+    connect();
+  }
+
+
+
+  /**
+   * Authenticate over LDAP.
+   */
+  private static void connect()
+  {
+    final LDAPConnectionFactory factory = new LDAPConnectionFactory(
+      host, port);
+    Connection connection = null;
+
+    try
+    {
+      connection = factory.getConnection();
+      connection.bind("", "".toCharArray()); // Anonymous bind
+
+      final String attributeList;
+      if (infoType.toLowerCase().equals("controls"))
+        attributeList = "supportedControl";
+      else if (infoType.toLowerCase().equals("extops"))
+        attributeList = "supportedExtension";
+      else
+        attributeList = "+";          // All operational attributes
+
+      final SearchResultEntry entry = connection.searchSingleEntry(
+          "",                         // DN is "" for root DSE.
+          SearchScope.BASE_OBJECT,    // Read only the root DSE.
+          "objectclass=*",            // Every object matches this filter.
+          attributeList);             // Return these requested attributes.
+
+      final LDIFEntryWriter writer = new LDIFEntryWriter(System.out);
+      writer.writeComment("Root DSE for LDAP server at " + host + ":" + port);
+      if (entry != null) writer.writeEntry(entry);
+      writer.flush();
+    }
+    catch (final ErrorResultException e)
+    {
+      System.err.println(e.getMessage());
+      System.exit(e.getResult().getResultCode().intValue());
+      return;
+    }
+    catch (final InterruptedException e)
+    {
+      System.err.println(e.getMessage());
+      System.exit(ResultCode.CLIENT_SIDE_USER_CANCELLED.intValue());
+      return;
+    }
+    catch (LocalizedIllegalArgumentException e)
+    {
+      System.err.println(e.getMessageObject().toString());
+      System.exit(ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue());
+      return;
+    }
+    catch (UnsupportedOperationException e)
+    {
+      System.err.println(e.getMessage());
+      System.exit(ResultCode.CLIENT_SIDE_LOCAL_ERROR.intValue());
+      return;
+    }
+    catch (IllegalStateException e)
+    {
+      System.err.println(e.getMessage());
+      System.exit(ResultCode.CLIENT_SIDE_LOCAL_ERROR.intValue());
+      return;
+    }
+    catch (IOException e)
+    {
+      System.err.println(e.getMessage());
+      System.exit(ResultCode.CLIENT_SIDE_LOCAL_ERROR.intValue());
+      return;
+    }
+    finally
+    {
+      if (connection != null) connection.close();
+    }
+  }
+
+
+
+  /**
+   * Parse command line arguments.
+   * @param args host port bind-dn bind-password info-type
+   */
+  private static void parseArgs(String[] args)
+  {
+    if (args.length != 3) giveUp();
+
+    host = args[0];
+    port = Integer.parseInt(args[1]);
+    infoType = args[2]; // all, controls, or extops
+    if (!
+         (
+           infoType.toLowerCase().equals("all") ||
+           infoType.toLowerCase().equals("controls") ||
+           infoType.toLowerCase().equals("extops")
+         )
+       )
+           giveUp();
+  }
+
+
+
+  private static void giveUp()
+  {
+    printUsage();
+    System.exit(1);
+  }
+
+
+
+  private static void printUsage()
+  {
+    System.err.println(
+      "Usage: host port info-type");
+    System.err.println(
+      "\tAll arguments are required.");
+    System.err.println(
+      "\tinfo-type to get can be either all, controls, or extops.");
+  }
+
+
+
+  private Main()
+  {
+    // Not used.
+  }
+}
diff --git a/opendj3/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/getinfo/package-info.java b/opendj3/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/getinfo/package-info.java
new file mode 100644
index 0000000..8a0a6b1
--- /dev/null
+++ b/opendj3/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/getinfo/package-info.java
@@ -0,0 +1,34 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opendj3/legal-notices/CDDLv1_0.txt
+ * or http://forgerock.org/license/CDDLv1.0.html.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opendj3/legal-notices/CDDLv1_0.txt.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2012 ForgeRock AS
+ */
+
+/**
+ * Demonstrates accessing server information about capabilities and schema.
+ */
+package org.forgerock.opendj.examples.getinfo;
+
+
+
diff --git a/opendj3/src/main/docbkx/dev-guide/chap-controls.xml b/opendj3/src/main/docbkx/dev-guide/chap-controls.xml
index cfe5a15..9a419f4 100644
--- a/opendj3/src/main/docbkx/dev-guide/chap-controls.xml
+++ b/opendj3/src/main/docbkx/dev-guide/chap-controls.xml
@@ -20,7 +20,7 @@
   !
   ! CCPL HEADER END
   !
-  !      Copyright 2011 ForgeRock AS
+  !      Copyright 2011-2012 ForgeRock AS
   !    
 -->
 <chapter xml:id='chap-controls'
@@ -45,7 +45,71 @@
  
  <section xml:id="get-supported-controls">
   <title>Determining Supported Controls</title>
-  <para>TODO</para>
+
+  <para>For OpenDJ, the controls supported are listed in the
+  <citetitle>Administration Guide</citetitle> appendix, <link
+  xlink:href="admin-guide#appendix-controls"
+  xlink:role="http://docbook.org/xlink/role/olink"><citetitle>LDAP
+  Controls</citetitle></link>. You can access the list of OIDs for
+  supported LDAP controls by reading the <literal>supportedControl</literal>
+  attribute of the root DSE.</para>
+
+  <screen>$ ldapsearch
+ --baseDN ""
+ --searchScope base
+ --port 1389
+ "(objectclass=*)" supportedControl
+dn: 
+supportedControl: 1.2.826.0.1.3344810.2.3
+supportedControl: 1.2.840.113556.1.4.1413
+supportedControl: 1.2.840.113556.1.4.319
+supportedControl: 1.2.840.113556.1.4.473
+supportedControl: 1.2.840.113556.1.4.805
+supportedControl: 1.3.6.1.1.12
+supportedControl: 1.3.6.1.1.13.1
+supportedControl: 1.3.6.1.1.13.2
+supportedControl: 1.3.6.1.4.1.26027.1.5.2
+supportedControl: 1.3.6.1.4.1.42.2.27.8.5.1
+supportedControl: 1.3.6.1.4.1.42.2.27.9.5.2
+supportedControl: 1.3.6.1.4.1.42.2.27.9.5.8
+supportedControl: 1.3.6.1.4.1.4203.1.10.1
+supportedControl: 1.3.6.1.4.1.4203.1.10.2
+supportedControl: 1.3.6.1.4.1.7628.5.101.1
+supportedControl: 2.16.840.1.113730.3.4.12
+supportedControl: 2.16.840.1.113730.3.4.16
+supportedControl: 2.16.840.1.113730.3.4.17
+supportedControl: 2.16.840.1.113730.3.4.18
+supportedControl: 2.16.840.1.113730.3.4.19
+supportedControl: 2.16.840.1.113730.3.4.2
+supportedControl: 2.16.840.1.113730.3.4.3
+supportedControl: 2.16.840.1.113730.3.4.4
+supportedControl: 2.16.840.1.113730.3.4.5
+supportedControl: 2.16.840.1.113730.3.4.9</screen>
+
+  <para>The following excerpt shows the Java equivalent of the preceding
+  command.</para>
+
+  <programlisting language="java">
+final LDAPConnectionFactory factory = new LDAPConnectionFactory(
+  host, port);
+Connection connection = null;
+
+try
+{
+  connection = factory.getConnection();
+  connection.bind("", "".toCharArray());
+  
+  final SearchResultEntry entry = connection.searchSingleEntry(
+      "",                         // DN is "" for root DSE.
+      SearchScope.BASE_OBJECT,    // Read only the root DSE.
+      "objectclass=*",            // Every object matches this filter.
+      "supportedControl");        // Check supported controls.
+
+  final LDIFEntryWriter writer = new LDIFEntryWriter(System.out);
+  writer.writeComment("Supported controls for server " + host + ":" + port);
+  if (entry != null) writer.writeEntry(entry);
+  writer.flush();
+}</programlisting>
  </section>
  
  <section xml:id="use-assertion-request-control">
diff --git a/opendj3/src/main/docbkx/dev-guide/chap-extended-ops.xml b/opendj3/src/main/docbkx/dev-guide/chap-extended-ops.xml
index 4a3df2f..2bb50ea 100644
--- a/opendj3/src/main/docbkx/dev-guide/chap-extended-ops.xml
+++ b/opendj3/src/main/docbkx/dev-guide/chap-extended-ops.xml
@@ -41,7 +41,53 @@
  
  <section xml:id="get-supported-extended-operations">
   <title>Determining Supported Extended Operations</title>
-  <para>TODO</para>
+
+  <para>For OpenDJ, the extended operations supported are listed in the
+  <citetitle>Administration Guide</citetitle> appendix, <link
+  xlink:href="admin-guide#appendix-extended-ops"
+  xlink:role="http://docbook.org/xlink/role/olink"><citetitle>LDAP Extended
+  Operations</citetitle></link>. You can access the list of OIDs for
+  supported LDAP controls by reading the <literal>supportedExtension</literal>
+  attribute of the root DSE.</para>
+
+  <screen>$ ldapsearch
+ --baseDN ""
+ --searchScope base
+ --port 1389
+ "(objectclass=*)" supportedExtension
+dn: 
+supportedExtension: 1.3.6.1.1.8
+supportedExtension: 1.3.6.1.4.1.26027.1.6.1
+supportedExtension: 1.3.6.1.4.1.26027.1.6.2
+supportedExtension: 1.3.6.1.4.1.26027.1.6.3
+supportedExtension: 1.3.6.1.4.1.4203.1.11.1
+supportedExtension: 1.3.6.1.4.1.4203.1.11.3
+supportedExtension: 1.3.6.1.4.1.1466.20037</screen>
+
+  <para>The following excerpt shows the Java equivalent of the preceding
+  command.</para>
+
+  <programlisting language="java">
+final LDAPConnectionFactory factory = new LDAPConnectionFactory(
+  host, port);
+Connection connection = null;
+
+try
+{
+  connection = factory.getConnection();
+  connection.bind("", "".toCharArray());
+  
+  final SearchResultEntry entry = connection.searchSingleEntry(
+      "",                         // DN is "" for root DSE.
+      SearchScope.BASE_OBJECT,    // Read only the root DSE.
+      "objectclass=*",            // Every object matches this filter.
+      "supportedExtension");      // Check supported extended operations.
+
+  final LDIFEntryWriter writer = new LDIFEntryWriter(System.out);
+  writer.writeComment("Supported extended ops for server " + host + ":" + port);
+  if (entry != null) writer.writeEntry(entry);
+  writer.flush();
+}</programlisting>
  </section>
  
  <section xml:id="use-cancel-extended-operation">
diff --git a/opendj3/src/main/docbkx/dev-guide/chap-getting-directory-info.xml b/opendj3/src/main/docbkx/dev-guide/chap-getting-directory-info.xml
index d87860b..fdece0b 100644
--- a/opendj3/src/main/docbkx/dev-guide/chap-getting-directory-info.xml
+++ b/opendj3/src/main/docbkx/dev-guide/chap-getting-directory-info.xml
@@ -20,7 +20,7 @@
   !
   ! CCPL HEADER END
   !
-  !      Copyright 2011 ForgeRock AS
+  !      Copyright 2011-2012 ForgeRock AS
   !    
 -->
 <chapter xml:id='chap-getting-directory-info'
@@ -38,16 +38,149 @@
 
  <section xml:id="read-root-dse">
   <title>Reading Root DSEs</title>
-  <para>TODO</para>
+  
+  <para>The directory with distinguished name <literal>""</literal> (empty
+  string) is called the <firstterm>root DSE</firstterm>. DSE stands for
+  DSA-Specific Entry. DSA stands for Directory Server Agent, a single
+  directory server.</para>
+
+  <para>The root DSE serves to expose information over LDAP about what the
+  directory server supports in terms of LDAP controls, auth password schemes,
+  SASL mechanisms, LDAP protocol versions, naming contexts, features, LDAP
+  extended operations, and so forth. The root DSE holds all the information
+  as values of LDAP attributes. OpenDJ defines these attributes as operational.
+  In other words, OpenDJ only returns the attributes if you either request
+  them specifically, or request all operational attributes.</para>
+
+  <para>To access the list of what an OpenDJ server supports, for example,
+  get all operational attributes from the root DSE entry as in the following
+  excerpt.</para>
+
+  <programlisting language="java">
+final LDAPConnectionFactory factory = new LDAPConnectionFactory(
+  host, port);
+Connection connection = null;
+
+try
+{
+  connection = factory.getConnection();
+  connection.bind("", "".toCharArray());
+  
+  final SearchResultEntry entry = connection.searchSingleEntry(
+      "",                         // DN is "" for root DSE.
+      SearchScope.BASE_OBJECT,    // Read only the root DSE.
+      "objectclass=*",            // Every object matches this filter.
+      "+");                       // Return all operational attributes.
+
+  final LDIFEntryWriter writer = new LDIFEntryWriter(System.out);
+  writer.writeComment("Root DSE for LDAP server at " + host + ":" + port);
+  if (entry != null) writer.writeEntry(entry);
+  writer.flush();
+}</programlisting>
+
+  <para>Notice that by default you can access the root DSE after authenticating
+  anonymously. When you look at the entry in LDIF, you see that supported
+  capabilities are generally identified by object identifier (OID).</para>
+
+  <screen># Root DSE for LDAP server at localhost:1389
+dn: 
+supportedControl: 1.2.826.0.1.3344810.2.3
+supportedControl: 1.2.840.113556.1.4.1413
+supportedControl: 1.2.840.113556.1.4.319
+supportedControl: 1.2.840.113556.1.4.473
+supportedControl: 1.2.840.113556.1.4.805
+supportedControl: 1.3.6.1.1.12
+supportedControl: 1.3.6.1.1.13.1
+supportedControl: 1.3.6.1.1.13.2
+supportedControl: 1.3.6.1.4.1.26027.1.5.2
+supportedControl: 1.3.6.1.4.1.42.2.27.8.5.1
+supportedControl: 1.3.6.1.4.1.42.2.27.9.5.2
+supportedControl: 1.3.6.1.4.1.42.2.27.9.5.8
+supportedControl: 1.3.6.1.4.1.4203.1.10.1
+supportedControl: 1.3.6.1.4.1.4203.1.10.2
+supportedControl: 1.3.6.1.4.1.7628.5.101.1
+supportedControl: 2.16.840.1.113730.3.4.12
+supportedControl: 2.16.840.1.113730.3.4.16
+supportedControl: 2.16.840.1.113730.3.4.17
+supportedControl: 2.16.840.1.113730.3.4.18
+supportedControl: 2.16.840.1.113730.3.4.19
+supportedControl: 2.16.840.1.113730.3.4.2
+supportedControl: 2.16.840.1.113730.3.4.3
+supportedControl: 2.16.840.1.113730.3.4.4
+supportedControl: 2.16.840.1.113730.3.4.5
+supportedControl: 2.16.840.1.113730.3.4.9
+supportedAuthPasswordSchemes: MD5
+supportedAuthPasswordSchemes: SHA1
+supportedAuthPasswordSchemes: SHA256
+supportedAuthPasswordSchemes: SHA512
+supportedAuthPasswordSchemes: SHA384
+supportedSASLMechanisms: PLAIN
+supportedSASLMechanisms: EXTERNAL
+supportedSASLMechanisms: DIGEST-MD5
+supportedSASLMechanisms: CRAM-MD5
+supportedLDAPVersion: 2
+supportedLDAPVersion: 3
+pwdPolicySubentry: cn=Default Password Policy,cn=Password Policies,cn=config
+supportedFeatures: 1.3.6.1.1.14
+supportedFeatures: 1.3.6.1.4.1.4203.1.5.1
+supportedFeatures: 1.3.6.1.4.1.4203.1.5.2
+supportedFeatures: 1.3.6.1.4.1.4203.1.5.3
+subschemaSubentry: cn=schema
+ds-private-naming-contexts: cn=admin data
+ds-private-naming-contexts: cn=ads-truststore
+ds-private-naming-contexts: cn=backups
+ds-private-naming-contexts: cn=config
+ds-private-naming-contexts: cn=monitor
+ds-private-naming-contexts: cn=schema
+ds-private-naming-contexts: cn=tasks
+numSubordinates: 1
+structuralObjectClass: ds-root-dse
+namingContexts: dc=example,dc=com
+supportedExtension: 1.3.6.1.1.8
+supportedExtension: 1.3.6.1.4.1.26027.1.6.1
+supportedExtension: 1.3.6.1.4.1.26027.1.6.2
+supportedExtension: 1.3.6.1.4.1.26027.1.6.3
+supportedExtension: 1.3.6.1.4.1.4203.1.11.1
+supportedExtension: 1.3.6.1.4.1.4203.1.11.3
+supportedExtension: 1.3.6.1.4.1.1466.20037
+vendorName: ForgeRock AS.
+vendorVersion: OpenDJ 2.5.0
+hasSubordinates: true
+entryUUID: d41d8cd9-8f00-3204-a980-0998ecf8427e
+entryDN: </screen>
+
+  <para>Three key pieces of information in the entry shown above are attribute
+  values for <literal>namingContexts</literal> (showing the base DNs under
+  which your application can look for user data),
+  <literal>subschemaSubentry</literal> (indicating where the LDAP schema are
+  stored), and <literal>supportedLDAPVersion</literal> (with OpenDJ seen to
+  support both LDAPv2 and LDAPv3).</para>
  </section>
  
  <section xml:id="check-ldapv3-support">
   <title>Checking For LDAPv3 Support</title>
-  <para>TODO</para>
+
+  <para>As shown in the previous section, you can check that the root DSE
+  attribute <literal>supportedLDAPVersion</literal> has a value of 3.</para>
+
+  <para>LDAPv3 has been available since 1997. Client applications built with
+  OpenDJ SDK use LDAPv3.</para>
  </section>
  
  <section xml:id="get-schema-information">
   <title>Getting Schema Information</title>
-  <para>TODO</para>
+
+  <para>The root DSE attribute <literal>subschemaSubentry</literal> shows
+  the DN of the entry holding LDAP schema definitions. LDAP schema defines the
+  object classes, attributes types, attribute value syntaxes, matching rules
+  and so on that constrain entries held by the LDAP server.</para>
+
+  <para>The <literal>org.forgerock.opendj.ldap.schema</literal> package
+  is devoted to constructing and querying LDAP schemas. The
+  <literal>Schema</literal> class for example lets you
+  <literal>readSchemaForEntry()</literal> to get the relevant schema from the
+  subschema subentry, and then <literal>validateEntry()</literal> to check
+  an entry your application has constructed before sending the entry to the
+  server.</para>
  </section>
 </chapter>
\ No newline at end of file

--
Gitblit v1.10.0