mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

Mark Craig
04.28.2012 e41f3472a5e929c9605376f108abd7c9c70f8c93
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
<?xml version="1.0" encoding="UTF-8"?>
<!--
  ! CCPL HEADER START
  !
  ! This work is licensed under the Creative Commons
  ! Attribution-NonCommercial-NoDerivs 3.0 Unported License.
  ! To view a copy of this license, visit
  ! http://creativecommons.org/licenses/by-nc-nd/3.0/
  ! or send a letter to Creative Commons, 444 Castro Street,
  ! Suite 900, Mountain View, California, 94041, USA.
  !
  ! You can also obtain a copy of the license at
  ! trunk/opendj3/legal-notices/CC-BY-NC-ND.txt.
  ! See the License for the specific language governing permissions
  ! and limitations under the License.
  !
  ! If applicable, add the following below this CCPL HEADER, with the fields
  ! enclosed by brackets "[]" replaced with your own identifying information:
  !      Portions Copyright [yyyy] [name of copyright owner]
  !
  ! CCPL HEADER END
  !
  !      Copyright 2011-2012 ForgeRock AS
  !    
-->
<chapter xml:id='chap-controls'
 xmlns='http://docbook.org/ns/docbook' version='5.0' xml:lang='en'
 xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
 xsi:schemaLocation='http://docbook.org/ns/docbook http://docbook.org/xml/5.0/xsd/docbook.xsd'
 xmlns:xlink='http://www.w3.org/1999/xlink'
 xmlns:xinclude='http://www.w3.org/2001/XInclude'>
 <title>Working With Controls</title>
 
 <para>This chapter demonstrates how to use LDAP controls.</para>
 
 <section xml:id="about-ldap-controls">
  <title>About LDAP Controls</title>
  <para>Controls 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
  <emphasis>request controls</emphasis>, and those sent by servers are termed
  <emphasis>response controls</emphasis>.</para>
 </section>
 
 <section xml:id="get-supported-controls">
  <title>Determining Supported Controls</title>
 
  <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 couple of methods to check whether the
  directory server supports a control.</para>
 
  <programlisting language="java">
/**
 * Controls supported by the LDAP server.
 */
private static Collection&lt;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 &amp;&amp; !controls.isEmpty()) {
        return controls.contains(control);
    }
    return false;
}
</programlisting>
 </section>
 
 <section xml:id="use-assertion-request-control">
  <title>Assertion Request Control</title>
 
  <para>The <link xlink:href="http://tools.ietf.org/html/rfc4528"
  xlink:show="new" >LDAP assertion control</link> 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.</para>
 
  <programlisting language="java">
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();
    }
}</programlisting>
 
  <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>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>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>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-managedsait-control">
  <title>ManageDsaIT Request Control</title>
 
  <para>The ManageDsaIT control, described in <link xlink:show="new"
  xlink:href="http://tools.ietf.org/html/rfc3296">RFC 3296, <citetitle>Named
  Subordinate References in LDAP Directories</citetitle></link>, lets your
  application handle references and other special entries as normal entries.
  Use it when you want to read from or write to reference or special
  entry.</para>
 
  <programlisting language="java">
if (isSupported(ManageDsaITRequestControl.OID)) {
    // This entry is a referral object:
    final String dn = "dc=references,dc=example,dc=com";
 
    final LDIFEntryWriter writer = new LDIFEntryWriter(System.out);
    try {
        System.out.println("Referral without the ManageDsaIT control.");
        SearchRequest request = Requests.newSearchRequest(dn,
                SearchScope.BASE_OBJECT, "(objectclass=*)", "");
        final ConnectionEntryReader reader = connection.search(request);
        while (reader.hasNext()) {
            if (reader.isReference()) {
                final SearchResultReference ref = reader.readReference();
                System.out.println("Reference: " + ref.getURIs().toString());
            }
        }
 
        System.out.println("Referral with the ManageDsaIT control.");
        request.addControl(ManageDsaITRequestControl.newControl(true));
        final SearchResultEntry entry = connection.searchSingleEntry(request);
        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 directory server supports the ManageDsaIT Request Control.</para>
 </section>
 
 <section xml:id="use-matched-values-request-control">
  <title>Matched Values Request Control</title>
 
  <para>RFC 3876, <link xlink:href="http://tools.ietf.org/html/rfc3876"
  xlink:show="new"><citetitle>Returning Matched Values with the
  LDAPv3</citetitle></link>, describes a control that lets your application
  pass a filter in a search request getting a multivalued attribute such that
  the directory server only returns attribute values that match the
  filter.</para>
 
  <para>Barbara Jensen's entry contains two common name values,
  <literal>Barbara Jensen</literal> and <literal>Babs Jensen</literal>. The
  following excerpt retrieves only the latter.</para>
 
  <programlisting language="java">
if (isSupported(MatchedValuesRequestControl.OID)) {
    final String dn = "uid=bjensen,ou=People,dc=example,dc=com";
    SearchRequest request =
            Requests.newSearchRequest(dn, SearchScope.BASE_OBJECT,
                    "(objectclass=*)", "cn");
    final String filter = "cn=Babs Jensen";
    request.addControl(MatchedValuesRequestControl.newControl(true, filter));
 
    final SearchResultEntry entry = connection.searchSingleEntry(request);
    System.out.println("Reading entry with matched values request.");
    final LDIFEntryWriter writer = new LDIFEntryWriter(System.out);
    try {
        writer.writeEntry(entry);
        writer.close();
    } catch (final IOException e) {
        e.printStackTrace();
    }
}
</programlisting>
 
  <para>OpenDJ directory server supports the matched values request
  control.</para>
 
  <programlisting language="ldif">Reading entry with matched values request.
dn: uid=bjensen,ou=People,dc=example,dc=com
cn: Babs Jensen
</programlisting>
 </section>
 
 <section xml:id="use-password-expired-control">
  <title>Password Expired Response Control</title>
  <para>TODO</para>
 </section>
 
 <section xml:id="use-password-expiring-control">
  <title>Password Expiring Response Control</title>
  <para>TODO</para>
 </section>
 
 <section xml:id="use-password-policy-controls">
  <title>Password Policy Controls</title>
  <para>TODO</para>
 </section>
 
 <section xml:id="use-permissive-modify-request-control">
  <title>Permissive Modify Request Control</title>
  <para>TODO</para>
 </section>
 
 <section xml:id="use-persistent-search-request-control">
  <title>Persistent Search Request Control</title>
 
  <para>See <xref linkend="use-entry-change-notification-control" />.</para>
 </section>
 
 <section xml:id="use-post-read-control">
  <title>Post-Read Controls</title>
  <para>TODO</para>
 </section>
 
 <section xml:id="use-pre-read-control">
  <title>Pre-Read Controls</title>
  <para>TODO</para>
 </section>
 
 <section xml:id="use-proxy-authz-control">
  <title>Proxied Authorization Request Controls</title>
  <para>TODO</para>
 </section>
 
 <section xml:id="use-server-side-sort-control">
  <title>Server-Side Sort Controls</title>
  <para>TODO</para>
 </section>
 
 <section xml:id="use-simple-paged-results-control">
  <title>Simple Paged Results Control</title>
  <para>TODO</para>
 </section>
 
 <section xml:id="use-subentry-request-control">
  <title>Sub-entries Request Control</title>
  <para>TODO</para>
 </section>
 
 <section xml:id="use-subtree-delete-control">
  <title>Subtree Delete Request Control</title>
  <para>TODO</para>
 </section>
 
 <section xml:id="use-vlv-control">
  <title>Virtual List View Controls</title>
  <para>TODO</para>
 </section>
 
 <section xml:id="custom-control">
  <title>Custom Controls</title>
  <para>TODO</para>
 </section>
</chapter>