| | |
| | | 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"> |
| | |
| | | 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"); |
| | | |
| | |
| | | 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"> |
| | |
| | | |
| | | <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"> |