From cf136586c780f03c81e504ec2b8018a0598a9c28 Mon Sep 17 00:00:00 2001
From: Mark Craig <mark.craig@forgerock.com>
Date: Thu, 03 May 2012 13:44:47 +0000
Subject: [PATCH] A bit more for the LDAP controls chapter
---
opendj3/src/main/docbkx/dev-guide/chap-controls.xml | 273 ++++++++++++++++++++++++++++++++++++++++++++++++------
1 files changed, 242 insertions(+), 31 deletions(-)
diff --git a/opendj3/src/main/docbkx/dev-guide/chap-controls.xml b/opendj3/src/main/docbkx/dev-guide/chap-controls.xml
index add663c..af21720 100644
--- a/opendj3/src/main/docbkx/dev-guide/chap-controls.xml
+++ b/opendj3/src/main/docbkx/dev-guide/chap-controls.xml
@@ -86,30 +86,43 @@
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>
+ <para>The following excerpt shows couple of methods to check whether the
+ directory server supports a control.</para>
<programlisting language="java">
-final LDAPConnectionFactory factory = new LDAPConnectionFactory(
- host, port);
-Connection connection = null;
+/**
+ * Controls supported by the LDAP server.
+ */
+private static Collection<String> controls;
-try
-{
- connection = factory.getConnection();
+/**
+ * Populate the list of supported LDAP control OIDs.
+ *
+ * @param connection
+ * Active connection to the LDAP server.
+ * @throws ErrorResultException
+ * Failed to get list of controls.
+ */
+static void checkSupportedControls(Connection connection)
+ throws ErrorResultException {
+ controls = RootDSE.readRootDSE(connection).getSupportedControls();
+}
- // Perform an anonymous search on the root DSE.
- 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>
+/**
+ * Check whether a control is supported. Call {@code checkSupportedControls}
+ * first.
+ *
+ * @param control
+ * Check support for this control, provided by OID.
+ * @return True if the control is supported.
+ */
+static boolean isSupported(final String control) {
+ if (controls != null && !controls.isEmpty()) {
+ return controls.contains(control);
+ }
+ return false;
+}
+</programlisting>
</section>
<section xml:id="use-assertion-request-control">
@@ -125,11 +138,11 @@
if (isSupported(AssertionRequestControl.OID)) {
// Modify Babs Jensen's description if her entry does not have
// a description, yet.
- String dn = "uid=bjensen,ou=People,dc=example,dc=com";
+ final String dn = "uid=bjensen,ou=People,dc=example,dc=com";
ModifyRequest request = Requests.newModifyRequest(dn);
- request.addControl(AssertionRequestControl.newControl(true,
- Filter.valueOf("!(description=*)")));
+ request.addControl(AssertionRequestControl.newControl(true, Filter
+ .valueOf("!(description=*)")));
request.addModification(ModificationType.ADD, "description",
"Created with the help of the LDAP assertion control");
@@ -140,26 +153,223 @@
writer.writeEntry(connection.readEntry(dn, "description"));
writer.close();
} catch (final IOException e) {
- // Ignore.
+ e.printStackTrace();
}
}</programlisting>
- <para>OpenDJ directory server supports the LDAP assertion control.</para>
+ <para>OpenDJ directory server supports the LDAP assertion control:</para>
+
+ <programlisting language="ldif">dn: uid=bjensen,ou=People,dc=example,dc=com
+description: Created with the help of the LDAP assertion control</programlisting>
</section>
-
+
<section xml:id="use-authorization-identity-control">
<title>Authorization Identity Controls</title>
- <para>TODO</para>
+
+ <para>The <link xlink:href="http://tools.ietf.org/html/rfc3829"
+ xlink:show="new">LDAP Authorization Identity Controls</link> let you get the
+ authorization identity established when you bind to the directory server.
+ The following excerpt shows simple use of the controls.</para>
+
+ <programlisting language="java">
+if (isSupported(AuthorizationIdentityRequestControl.OID)) {
+ final String name = "uid=bjensen,ou=People,dc=example,dc=com";
+ final char[] password = "hifalutin".toCharArray();
+
+ System.out.println("Binding as " + name);
+ BindRequest request = Requests.newSimpleBindRequest(name, password);
+ request.addControl(AuthorizationIdentityRequestControl.newControl(true));
+
+ final BindResult result = connection.bind(request);
+ try {
+ final AuthorizationIdentityResponseControl control =
+ result.getControl(AuthorizationIdentityResponseControl.DECODER,
+ new DecodeOptions());
+ System.out.println("Authorization ID returned: "
+ + control.getAuthorizationID());
+ } catch (final DecodeException e) {
+ e.printStackTrace();
+ }
+}</programlisting>
+
+ <para>OpenDJ directory server supports the LDAP Authorization Identity
+ Controls:</para>
+
+ <programlisting>Binding as uid=bjensen,ou=People,dc=example,dc=com
+Authorization ID returned: dn:uid=bjensen,ou=People,dc=example,dc=com</programlisting>
</section>
<section xml:id="use-entry-change-notification-control">
<title>Entry Change Notification Response Controls</title>
- <para>TODO</para>
+
+ <para>When performing a persistent search, your application can retrieve
+ information using this response control about why the directory server
+ returned the entry. See the Internet-Draft on <link xlink:show="new"
+ xlink:href="tools.ietf.org/html/draft-ietf-ldapext-psearch">persistent
+ searches</link> for background information.</para>
+
+ <programlisting language="java">
+if (isSupported(PersistentSearchRequestControl.OID)) {
+ SearchRequest request =
+ Requests.newSearchRequest(
+ "dc=example,dc=com",
+ SearchScope.WHOLE_SUBTREE,
+ "(objectclass=inetOrgPerson)",
+ "cn");
+ request.addControl(PersistentSearchRequestControl.newControl(
+ true, true, true, // isCritical, changesOnly, returnECs
+ PersistentSearchChangeType.ADD,
+ PersistentSearchChangeType.DELETE,
+ PersistentSearchChangeType.MODIFY,
+ PersistentSearchChangeType.MODIFY_DN));
+
+ final ConnectionEntryReader reader = connection.search(request);
+
+ try {
+ while (reader.hasNext()) {
+ if (!reader.isReference()) {
+ final SearchResultEntry entry = reader.readEntry();
+ System.out.println("Entry changed: "
+ + entry.getName().toString());
+
+ EntryChangeNotificationResponseControl control =
+ entry.getControl(
+ EntryChangeNotificationResponseControl.DECODER,
+ new DecodeOptions());
+
+ PersistentSearchChangeType type = control.getChangeType();
+ System.out.println("Change type: " + type.toString());
+ if (type.equals(PersistentSearchChangeType.MODIFY_DN)) {
+ System.out.println("Previous DN: "
+ + control.getPreviousName().toString());
+ }
+ System.out.println("Change number: "
+ + control.getChangeNumber());
+ System.out.println(); // Add a blank line.
+ }
+ }
+ } catch (final DecodeException e) {
+ e.printStackTrace();
+ } catch (final ErrorResultIOException e) {
+ e.printStackTrace();
+ } catch (final SearchResultReferenceIOException e) {
+ e.printStackTrace();
+ }
+}
+</programlisting>
+
+ <para>OpenDJ directory server supports persistent searches and the entry
+ change notification response control. When another application renames
+ Anne-Louise Barnes's entry, the sample code picks up information from the
+ entry change notification response control:</para>
+
+ <programlisting>Entry changed: uid=bdobbs,ou=People,dc=example,dc=com
+Change type: modifyDN
+Previous DN: uid=abarnes,ou=People,dc=example,dc=com
+Change number: -1</programlisting>
</section>
<section xml:id="use-get-effective-rights-control">
- <title>Get Effective Rights Request Control</title>
- <para>TODO</para>
+ <title>GetEffectiveRights Request Control</title>
+
+ <para>Your application can attach the GetEffectiveRights request control to
+ a search in order to determine what access a user has to perform operations
+ on entries found. See the Internet-Draft on the <link xlink:show="new"
+ xlink:href="http://tools.ietf.org/html/draft-ietf-ldapext-acl-model">Access
+ Control Model for LDAP</link> for background.</para>
+
+ <programlisting language="java">
+if (isSupported(GetEffectiveRightsRequestControl.OID)) {
+ final String authDN = "uid=kvaughan,ou=People,dc=example,dc=com";
+
+ SearchRequest request =
+ Requests.newSearchRequest(
+ "dc=example,dc=com", SearchScope.WHOLE_SUBTREE,
+ "(uid=bjensen)", "cn", "aclRights", "aclRightsInfo");
+ request.addControl(
+ GetEffectiveRightsRequestControl.newControl(true, authDN, "cn"));
+
+ final ConnectionEntryReader reader = connection.search(request);
+ final LDIFEntryWriter writer = new LDIFEntryWriter(System.out);
+ try {
+ while (reader.hasNext()) {
+ if (!reader.isReference()) {
+ final SearchResultEntry entry = reader.readEntry();
+ writer.writeEntry(entry);
+ }
+ }
+ writer.close();
+ } catch (final ErrorResultIOException e) {
+ e.printStackTrace();
+ } catch (final SearchResultReferenceIOException e) {
+ e.printStackTrace();
+ } catch (final IOException e) {
+ e.printStackTrace();
+ }
+}
+</programlisting>
+
+ <para>OpenDJ SDK currently implements the request control, but not the
+ response control. The results are shown as values of the
+ <literal>aclRights</literal> and more verbose <literal>aclRightsInfo</literal>
+ attributes.</para>
+
+ <programlisting language="ldif">
+dn: uid=bjensen,ou=People,dc=example,dc=com
+aclRightsInfo;logs;attributeLevel;selfwrite_delete;cn: acl_summary(main)
+ : access allowed(write) on entry/attr(uid=bjensen,ou=People,dc=example,dc=com
+ , distinguishedName) to (uid=kvaughan,ou=People,dc=example,dc=com) (not proxied
+ ) ( reason: evaluated allow , deciding_aci: allow all Admin group)
+aclRightsInfo;logs;entryLevel;read: acl_summary(main): access allowed(read
+ ) on entry/attr(uid=bjensen,ou=People,dc=example,dc=com, objectClass) to (
+ uid=kvaughan,ou=People,dc=example,dc=com) (not proxied) ( reason
+ : evaluated allow , deciding_aci: Anonymous read-search access)
+aclRightsInfo;logs;attributeLevel;proxy;cn: acl_summary(main)
+ : access not allowed(proxy) on entry/attr(uid=bjensen,ou=People,dc=example,
+ dc=com, cn) to (uid=kvaughan,ou=People,dc=example,dc=com) (not proxied
+ ) (reason: no acis matched the subject )
+aclRights;attributeLevel;cn: search:1,read:1,compare:1,write:1,selfwrite_add:1,
+ selfwrite_delete:1,proxy:0
+aclRightsInfo;logs;attributeLevel;write;cn: acl_summary(main): access allowed
+ (write) on entry/attr(uid=bjensen,ou=People,dc=example,dc=com, cn) to (
+ uid=kvaughan,ou=People,dc=example,dc=com) (not proxied
+ ) ( reason: evaluated allow , deciding_aci: allow all Admin group)
+aclRights;entryLevel: add:1,delete:1,read:1,write:1,proxy:0
+aclRightsInfo;logs;attributeLevel;search;cn: acl_summary(main): access allowed(
+ search) on entry/attr(uid=bjensen,ou=People,dc=example,dc=com, cn) to (
+ uid=kvaughan,ou=People,dc=example,dc=com) (not proxied
+ ) ( reason: evaluated allow , deciding_aci: Anonymous read-search access)
+aclRightsInfo;logs;entryLevel;write: acl_summary(main): access allowed(write
+ ) on entry/attr(uid=bjensen,ou=People,dc=example,dc=com, NULL) to (
+ uid=kvaughan,ou=People,dc=example,dc=com) (not proxied
+ ) ( reason: evaluated allow , deciding_aci: allow all Admin group)
+aclRightsInfo;logs;attributeLevel;selfwrite_add;cn: acl_summary(main
+ ): access allowed(write) on entry/attr(uid=bjensen,ou=People,dc=example,
+ dc=com, distinguishedName) to (uid=kvaughan,ou=People,dc=example,dc=com) (
+ not proxied) ( reason: evaluated allow , deciding_aci: allow all Admin group)
+aclRightsInfo;logs;entryLevel;add: acl_summary(main): access allowed(add
+ ) on entry/attr(uid=bjensen,ou=People,dc=example,dc=com, NULL) to (
+ uid=kvaughan,ou=People,dc=example,dc=com) (not proxied
+ ) ( reason: evaluated allow , deciding_aci: allow all Admin group)
+aclRightsInfo;logs;attributeLevel;read;cn: acl_summary(main): access allowed(
+ read) on entry/attr(uid=bjensen,ou=People,dc=example,dc=com, cn) to (
+ uid=kvaughan,ou=People,dc=example,dc=com) (not proxied
+ ) ( reason: evaluated allow , deciding_aci: Anonymous read-search access)
+cn: Barbara Jensen
+cn: Babs Jensen
+aclRightsInfo;logs;entryLevel;proxy: acl_summary(main): access not allowed(
+ proxy) on entry/attr(uid=bjensen,ou=People,dc=example,dc=com, NULL) to (
+ uid=kvaughan,ou=People,dc=example,dc=com) (not proxied
+ ) ( reason: no acis matched the subject )
+aclRightsInfo;logs;attributeLevel;compare;cn: acl_summary(main): access allowed
+ (compare) on entry/attr(uid=bjensen,ou=People,dc=example,dc=com, cn) to (
+ uid=kvaughan,ou=People,dc=example,dc=com) (not proxied
+ ) ( reason: evaluated allow , deciding_aci: Anonymous read-search access)
+aclRightsInfo;logs;entryLevel;delete: acl_summary(main): access allowed(
+ delete) on entry/attr(uid=bjensen,ou=People,dc=example,dc=com, NULL) to (
+ uid=kvaughan,ou=People,dc=example,dc=com) (not proxied
+ ) ( reason: evaluated allow , deciding_aci: allow all Admin group)
+</programlisting>
</section>
<section xml:id="use-manage-dsait-control-control">
@@ -194,7 +404,8 @@
<section xml:id="use-persistent-search-request-control">
<title>Persistent Search Request Control</title>
- <para>TODO</para>
+
+ <para>See <xref linkend="use-entry-change-notification-control" />.</para>
</section>
<section xml:id="use-post-read-control">
--
Gitblit v1.10.0