Working With ControlsThis chapter demonstrates how to use LDAP controls.About LDAP ControlsControls provide a mechanism whereby the semantics and arguments of
existing LDAP operations may be extended. One or more controls may be
attached to a single LDAP message. A control only affects the semantics of
the message it is attached to. Controls sent by clients are termed
request controls, and those sent by servers are termed
response controls.Determining Supported ControlsFor OpenDJ, the controls supported are listed in the
Administration Guide appendix, LDAP
Controls. You can access the list of OIDs for
supported LDAP controls by reading the supportedControl
attribute of the root DSE.$ 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.9The following excerpt shows couple of methods to check whether the
directory server supports a control.
/**
* Controls supported by the LDAP server.
*/
private static Collection<String> controls;
/**
* 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();
}
/**
* 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;
}
Assertion Request ControlThe LDAP assertion control lets you specify a condition
that must be true in order for the operation you request to be processed
normally. The following excerpt shows, for example, how you might check
that no description exists on the entry before adding your description.
if (isSupported(AssertionRequestControl.OID)) {
// Modify Babs Jensen's description if her entry does not have
// a description, yet.
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.addModification(ModificationType.ADD, "description",
"Created with the help of the LDAP assertion control");
connection.modify(request);
LDIFEntryWriter writer = new LDIFEntryWriter(System.out);
try {
writer.writeEntry(connection.readEntry(dn, "description"));
writer.close();
} catch (final IOException e) {
e.printStackTrace();
}
}OpenDJ directory server supports the LDAP assertion control:dn: uid=bjensen,ou=People,dc=example,dc=com
description: Created with the help of the LDAP assertion controlAuthorization Identity ControlsThe LDAP Authorization Identity Controls let you get the
authorization identity established when you bind to the directory server.
The following excerpt shows simple use of the controls.
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();
}
}OpenDJ directory server supports the LDAP Authorization Identity
Controls:Binding as uid=bjensen,ou=People,dc=example,dc=com
Authorization ID returned: dn:uid=bjensen,ou=People,dc=example,dc=comEntry Change Notification Response ControlsWhen 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 persistent
searches for background information.
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();
}
}
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: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: -1GetEffectiveRights Request ControlYour 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 Access
Control Model for LDAP for background.
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();
}
}
OpenDJ SDK currently implements the request control, but not the
response control. The results are shown as values of the
aclRights and more verbose aclRightsInfo
attributes.
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)
Manage DSAIT Request ControlTODOMatched Values Request ControlTODOPassword Expired Response ControlTODOPassword Expiring Response ControlTODOPassword Policy ControlsTODOPermissive Modify Request ControlTODOPersistent Search Request ControlSee .Post-Read ControlsTODOPre-Read ControlsTODOProxied Authorization Request ControlsTODOServer-Side Sort ControlsTODOSimple Paged Results ControlTODOSub-entries Request ControlTODOSubtree Delete Request ControlTODOVirtual List View ControlsTODOCustom ControlsTODO