xref: /netbsd-src/external/bsd/openldap/dist/doc/guide/admin/access-control.sdf (revision e670fd5c413e99c2f6a37901bb21c537fcd322d2)
1# $OpenLDAP$
2# Copyright 1999-2021 The OpenLDAP Foundation, All Rights Reserved.
3# COPYING RESTRICTIONS APPLY, see COPYRIGHT.
4
5H1: Access Control
6
7H2: Introduction
8
9As the directory gets populated with more and more data of varying sensitivity,
10controlling the kinds of access granted to the directory becomes more and more
11critical. For instance, the directory may contain data of a confidential nature
12that you may need to protect by contract or by law. Or, if using the directory
13to control access to other services, inappropriate access to the directory may
14create avenues of attack to your sites security that result in devastating
15damage to your assets.
16
17Access to your directory can be configured via two methods, the first using
18{{SECT:The slapd Configuration File}} and the second using the {{slapd-config}}(5)
19format ({{SECT:Configuring slapd}}).
20
21The default access control policy is allow read by all clients. Regardless of
22what access control policy is defined, the {{rootdn}} is always allowed full
23rights (i.e. auth, search, compare, read and write) on everything and anything.
24
25As a consequence, it's useless (and results in a performance penalty) to explicitly
26list the {{rootdn}} among the {{<by>}} clauses.
27
28The following sections will describe Access Control Lists in greater depth and
29follow with some examples and recommendations. See {{slapd.access}}(5) for
30complete details.
31
32H2: Access Control via Static Configuration
33
34Access to entries and attributes is controlled by the
35access configuration file directive. The general form of an
36access line is:
37
38>    <access directive> ::= access to <what>
39>        [by <who> [<access>] [<control>] ]+
40>    <what> ::= * |
41>        [dn[.<basic-style>]=<regex> | dn.<scope-style>=<DN>]
42>        [filter=<ldapfilter>] [attrs=<attrlist>]
43>    <basic-style> ::= regex | exact
44>    <scope-style> ::= base | one | subtree | children
45>    <attrlist> ::= <attr> [val[.<basic-style>]=<regex>] | <attr> , <attrlist>
46>    <attr> ::= <attrname> | entry | children
47>    <who> ::= * | [anonymous | users | self
48>            | dn[.<basic-style>]=<regex> | dn.<scope-style>=<DN>]
49>        [dnattr=<attrname>]
50>        [group[/<objectclass>[/<attrname>][.<basic-style>]]=<regex>]
51>        [peername[.<basic-style>]=<regex>]
52>        [sockname[.<basic-style>]=<regex>]
53>        [domain[.<basic-style>]=<regex>]
54>        [sockurl[.<basic-style>]=<regex>]
55>        [set=<setspec>]
56>        [aci=<attrname>]
57>    <access> ::= [self]{<level>|<priv>}
58>    <level> ::= none | disclose | auth | compare | search | read | write | manage
59>    <priv> ::= {=|+|-}{m|w|r|s|c|x|d|0}+
60>    <control> ::= [stop | continue | break]
61
62where the <what> part selects the entries and/or attributes to which
63the access applies, the {{EX:<who>}} part specifies which entities
64are granted access, and the {{EX:<access>}} part specifies the
65access granted. Multiple {{EX:<who> <access> <control>}} triplets
66are supported, allowing many entities to be granted different access
67to the same set of entries and attributes. Not all of these access
68control options are described here; for more details see the
69{{slapd.access}}(5) man page.
70
71
72H3: What to control access to
73
74The <what> part of an access specification determines the entries
75and attributes to which the access control applies.  Entries are
76commonly selected in two ways: by DN and by filter.  The following
77qualifiers select entries by DN:
78
79>    to *
80>    to dn[.<basic-style>]=<regex>
81>    to dn.<scope-style>=<DN>
82
83The first form is used to select all entries.  The second form may
84be used to select entries by matching a regular expression against
85the target entry's {{normalized DN}}.   (The second form is not
86discussed further in this document.)  The third form is used to
87select entries which are within the requested scope of DN.  The
88<DN> is a string representation of the Distinguished Name, as
89described in {{REF:RFC4514}}.
90
91The scope can be either {{EX:base}}, {{EX:one}}, {{EX:subtree}},
92or {{EX:children}}.  Where {{EX:base}} matches only the entry with
93provided DN, {{EX:one}} matches the entries whose parent is the
94provided DN, {{EX:subtree}} matches all entries in the subtree whose
95root is the provided DN, and {{EX:children}} matches all entries
96under the DN (but not the entry named by the DN).
97
98For example, if the directory contained entries named:
99
100>    0: o=suffix
101>    1: cn=Manager,o=suffix
102>    2: ou=people,o=suffix
103>    3: uid=kdz,ou=people,o=suffix
104>    4: cn=addresses,uid=kdz,ou=people,o=suffix
105>    5: uid=hyc,ou=people,o=suffix
106
107\Then:
108. {{EX:dn.base="ou=people,o=suffix"}} match 2;
109. {{EX:dn.one="ou=people,o=suffix"}} match 3, and 5;
110. {{EX:dn.subtree="ou=people,o=suffix"}} match 2, 3, 4, and 5; and
111. {{EX:dn.children="ou=people,o=suffix"}} match 3, 4, and 5.
112
113
114Entries may also be selected using a filter:
115
116>    to filter=<ldap filter>
117
118where <ldap filter> is a string representation of an LDAP
119search filter, as described in {{REF:RFC4515}}.  For example:
120
121>    to filter=(objectClass=person)
122
123Note that entries may be selected by both DN and filter by
124including both qualifiers in the <what> clause.
125
126>    to dn.one="ou=people,o=suffix" filter=(objectClass=person)
127
128Attributes within an entry are selected by including a comma-separated
129list of attribute names in the <what> selector:
130
131>    attrs=<attribute list>
132
133A specific value of an attribute is selected by using a single
134attribute name and also using a value selector:
135
136>    attrs=<attribute> val[.<style>]=<regex>
137
138There are two special {{pseudo}} attributes {{EX:entry}} and
139{{EX:children}}.  To read (and hence return) a target entry, the
140subject must have {{EX:read}} access to the target's {{entry}}
141attribute.  To perform a search, the subject must have
142{{EX:search}} access to the search base's {{entry}} attribute.
143To add or delete an entry, the subject must have
144{{EX:write}} access to the entry's {{EX:entry}} attribute AND must
145have {{EX:write}} access to the entry's parent's {{EX:children}}
146attribute.  To rename an entry, the subject must have {{EX:write}}
147access to entry's {{EX:entry}} attribute AND have {{EX:write}}
148access to both the old parent's and new parent's {{EX:children}}
149attributes.  The complete examples at the end of this section should
150help clear things up.
151
152Lastly, there is a special entry selector {{EX:"*"}} that is used to
153select any entry.  It is used when no other {{EX:<what>}}
154selector has been provided.  It's equivalent to "{{EX:dn=.*}}"
155
156
157H3: Who to grant access to
158
159The <who> part identifies the entity or entities being granted
160access. Note that access is granted to "entities" not "entries."
161The following table summarizes entity specifiers:
162
163!block table; align=Center; coltags="EX,N"; \
164    title="Table 6.3: Access Entity Specifiers"
165Specifier|Entities
166*|All, including anonymous and authenticated users
167anonymous|Anonymous (non-authenticated) users
168users|Authenticated users
169self|User associated with target entry
170dn[.<basic-style>]=<regex>|Users matching a regular expression
171dn.<scope-style>=<DN>|Users within scope of a DN
172!endblock
173
174The DN specifier behaves much like <what> clause DN specifiers.
175
176Other control factors are also supported.  For example, a {{EX:<who>}}
177can be restricted by an entry listed in a DN-valued attribute in
178the entry to which the access applies:
179
180>    dnattr=<dn-valued attribute name>
181
182The dnattr specification is used to give access to an entry
183whose DN is listed in an attribute of the entry (e.g., give
184access to a group entry to whoever is listed as the owner of
185the group entry).
186
187Some factors may not be appropriate in all environments (or any).
188For example, the domain factor relies on IP to domain name lookups.
189As these can easily be spoofed, the domain factor should be avoided.
190
191
192H3: The access to grant
193
194The kind of <access> granted can be one of the following:
195
196!block table; colaligns="LRL"; coltags="EX,EX,N"; align=Center; \
197    title="Table 6.4: Access Levels"
198Level        Privileges    Description
199none        =0             no access
200disclose    =d             needed for information disclosure on error
201auth        =dx            needed to authenticate (bind)
202compare     =cdx           needed to compare
203search      =scdx          needed to apply search filters
204read        =rscdx         needed to read search results
205write       =wrscdx        needed to modify/rename
206manage      =mwrscdx       needed to manage
207!endblock
208
209Each level implies all lower levels of access. So, for example,
210granting someone {{EX:write}} access to an entry also grants them
211{{EX:read}}, {{EX:search}}, {{EX:compare}}, {{EX:auth}} and
212{{EX:disclose}} access.  However, one may use the privileges specifier
213to grant specific permissions.
214
215
216H3: Access Control Evaluation
217
218When evaluating whether some requester should be given access to
219an entry and/or attribute, slapd compares the entry and/or attribute
220to the {{EX:<what>}} selectors given in the configuration file.
221For each entry, access controls provided in the database which holds
222the entry (or the global access directives if not held in any database) apply
223first, followed by the global access directives. However, when dealing with
224an access list, because the global access list is effectively appended
225to each per-database list, if the resulting list is non-empty then the
226access list will end with an implicit {{EX:access to * by * none}} directive.
227If there are no access directives applicable to a backend, then a default
228read is used.
229
230Within this
231priority, access directives are examined in the order in which they
232appear in the config file.  Slapd stops with the first {{EX:<what>}}
233selector that matches the entry and/or attribute. The corresponding
234access directive is the one slapd will use to evaluate access.
235
236Next, slapd compares the entity requesting access to the {{EX:<who>}}
237selectors within the access directive selected above in the order
238in which they appear. It stops with the first {{EX:<who>}} selector
239that matches the requester. This determines the access the entity
240requesting access has to the entry and/or attribute.
241
242Finally, slapd compares the access granted in the selected
243{{EX:<access>}} clause to the access requested by the client. If
244it allows greater or equal access, access is granted. Otherwise,
245access is denied.
246
247The order of evaluation of access directives makes their placement
248in the configuration file important. If one access directive is
249more specific than another in terms of the entries it selects, it
250should appear first in the config file. Similarly, if one {{EX:<who>}}
251selector is more specific than another it should come first in the
252access directive. The access control examples given below should
253help make this clear.
254
255
256
257H3: Access Control Examples
258
259The access control facility described above is quite powerful.  This
260section shows some examples of its use for descriptive purposes.
261
262A simple example:
263
264>    access to * by * read
265
266This access directive grants read access to everyone.
267
268>    access to *
269>        by self write
270>        by anonymous auth
271>        by * read
272
273This directive allows the user to modify their entry, allows anonymous
274to authenticate against these entries, and allows all others to
275read these entries.  Note that only the first {{EX:by <who>}} clause
276which matches applies.  Hence, the anonymous users are granted
277{{EX:auth}}, not {{EX:read}}.  The last clause could just as well
278have been "{{EX:by users read}}".
279
280It is often desirable to restrict operations based upon the level
281of protection in place.  The following shows how security strength
282factors (SSF) can be used.
283
284>    access to *
285>        by ssf=128 self write
286>        by ssf=64 anonymous auth
287>        by ssf=64 users read
288
289This directive allows users to modify their own entries if security
290protections have of strength 128 or better have been established,
291allows authentication access to anonymous users, and read access
292when 64 or better security protections have been established.  If
293client has not establish sufficient security protections, the
294implicit {{EX:by * none}} clause would be applied.
295
296The following example shows the use of a style specifiers to select
297the entries by DN in two access directives where ordering is
298significant.
299
300>    access to dn.children="dc=example,dc=com"
301>         by * search
302>    access to dn.children="dc=com"
303>         by * read
304
305Read access is granted to entries under the {{EX:dc=com}} subtree,
306except for those entries under the {{EX:dc=example,dc=com}} subtree,
307to which search access is granted.  No access is granted to
308{{EX:dc=com}} as neither access directive matches this DN.  If the
309order of these access directives was reversed, the trailing directive
310would never be reached, since all entries under {{EX:dc=example,dc=com}}
311are also under {{EX:dc=com}} entries.
312
313Also note that if no {{EX:access to}} directive matches or no {{EX:by
314<who>}} clause, {{B:access is denied}}.  That is, every {{EX:access
315to}} directive ends with an implicit {{EX:by * none}} clause. When dealing
316with an access list, because the global access list is effectively appended
317to each per-database list, if the resulting list is non-empty then the access
318list will end with an implicit {{EX:access to * by * none}} directive. If
319there are no access directives applicable to a backend, then a default read is
320used.
321
322The next example again shows the importance of ordering, both of
323the access directives and the {{EX:by <who>}} clauses.  It also
324shows the use of an attribute selector to grant access to a specific
325attribute and various {{EX:<who>}} selectors.
326
327>    access to dn.subtree="dc=example,dc=com" attrs=homePhone
328>        by self write
329>        by dn.children="dc=example,dc=com" search
330>        by peername.regex=IP=10\..+ read
331>    access to dn.subtree="dc=example,dc=com"
332>        by self write
333>        by dn.children="dc=example,dc=com" search
334>        by anonymous auth
335
336This example applies to entries in the "{{EX:dc=example,dc=com}}"
337subtree. To all attributes except {{EX:homePhone}}, an entry can
338write to itself, entries under {{EX:example.com}} entries can search
339by them, anybody else has no access (implicit {{EX:by * none}})
340excepting for authentication/authorization (which is always done
341anonymously).  The {{EX:homePhone}} attribute is writable by the
342entry, searchable by entries under {{EX:example.com}}, readable by
343clients connecting from network 10, and otherwise not readable
344(implicit {{EX:by * none}}).  All other access is denied by the
345implicit {{EX:access to * by * none}}.
346
347Sometimes it is useful to permit a particular DN to add or
348remove itself from an attribute. For example, if you would like to
349create a group and allow people to add and remove only
350their own DN from the member attribute, you could accomplish
351it with an access directive like this:
352
353>    access to attrs=member,entry
354>         by dnattr=member selfwrite
355
356The dnattr {{EX:<who>}} selector says that the access applies to
357entries listed in the {{EX:member}} attribute. The {{EX:selfwrite}} access
358selector says that such members can only add or delete their
359own DN from the attribute, not other values. The addition of
360the entry attribute is required because access to the entry is
361required to access any of the entry's attributes.
362
363!if 0
364For more details on how to use the {{EX:access}} directive,
365consult the {{Advanced Access Control}} chapter.
366!endif
367
368
369H2: Access Control via Dynamic Configuration
370
371Access to slapd entries and attributes is controlled by the
372olcAccess attribute, whose values are a sequence of access directives.
373The general form of the olcAccess configuration is:
374
375>    olcAccess: <access directive>
376>    <access directive> ::= to <what>
377>        [by <who> [<access>] [<control>] ]+
378>    <what> ::= * |
379>        [dn[.<basic-style>]=<regex> | dn.<scope-style>=<DN>]
380>        [filter=<ldapfilter>] [attrs=<attrlist>]
381>    <basic-style> ::= regex | exact
382>    <scope-style> ::= base | one | subtree | children
383>    <attrlist> ::= <attr> [val[.<basic-style>]=<regex>] | <attr> , <attrlist>
384>    <attr> ::= <attrname> | entry | children
385>    <who> ::= * | [anonymous | users | self
386>            | dn[.<basic-style>]=<regex> | dn.<scope-style>=<DN>]
387>        [dnattr=<attrname>]
388>        [group[/<objectclass>[/<attrname>][.<basic-style>]]=<regex>]
389>        [peername[.<basic-style>]=<regex>]
390>        [sockname[.<basic-style>]=<regex>]
391>        [domain[.<basic-style>]=<regex>]
392>        [sockurl[.<basic-style>]=<regex>]
393>        [set=<setspec>]
394>        [aci=<attrname>]
395>    <access> ::= [self]{<level>|<priv>}
396>    <level> ::= none | disclose | auth | compare | search | read | write | manage
397>    <priv> ::= {=|+|-}{m|w|r|s|c|x|d|0}+
398>    <control> ::= [stop | continue | break]
399
400where the <what> part selects the entries and/or attributes to which
401the access applies, the {{EX:<who>}} part specifies which entities
402are granted access, and the {{EX:<access>}} part specifies the
403access granted. Multiple {{EX:<who> <access> <control>}} triplets
404are supported, allowing many entities to be granted different access
405to the same set of entries and attributes. Not all of these access
406control options are described here; for more details see the
407{{slapd.access}}(5) man page.
408
409
410H3: What to control access to
411
412The <what> part of an access specification determines the entries
413and attributes to which the access control applies.  Entries are
414commonly selected in two ways: by DN and by filter.  The following
415qualifiers select entries by DN:
416
417>    to *
418>    to dn[.<basic-style>]=<regex>
419>    to dn.<scope-style>=<DN>
420
421The first form is used to select all entries.  The second form may
422be used to select entries by matching a regular expression against
423the target entry's {{normalized DN}}.   (The second form is not
424discussed further in this document.)  The third form is used to
425select entries which are within the requested scope of DN.  The
426<DN> is a string representation of the Distinguished Name, as
427described in {{REF:RFC4514}}.
428
429The scope can be either {{EX:base}}, {{EX:one}}, {{EX:subtree}},
430or {{EX:children}}.  Where {{EX:base}} matches only the entry with
431provided DN, {{EX:one}} matches the entries whose parent is the
432provided DN, {{EX:subtree}} matches all entries in the subtree whose
433root is the provided DN, and {{EX:children}} matches all entries
434under the DN (but not the entry named by the DN).
435
436For example, if the directory contained entries named:
437
438>    0: o=suffix
439>    1: cn=Manager,o=suffix
440>    2: ou=people,o=suffix
441>    3: uid=kdz,ou=people,o=suffix
442>    4: cn=addresses,uid=kdz,ou=people,o=suffix
443>    5: uid=hyc,ou=people,o=suffix
444
445\Then:
446. {{EX:dn.base="ou=people,o=suffix"}} match 2;
447. {{EX:dn.one="ou=people,o=suffix"}} match 3, and 5;
448. {{EX:dn.subtree="ou=people,o=suffix"}} match 2, 3, 4, and 5; and
449. {{EX:dn.children="ou=people,o=suffix"}} match 3, 4, and 5.
450
451
452Entries may also be selected using a filter:
453
454>    to filter=<ldap filter>
455
456where <ldap filter> is a string representation of an LDAP
457search filter, as described in {{REF:RFC4515}}.  For example:
458
459>    to filter=(objectClass=person)
460
461Note that entries may be selected by both DN and filter by
462including both qualifiers in the <what> clause.
463
464>    to dn.one="ou=people,o=suffix" filter=(objectClass=person)
465
466Attributes within an entry are selected by including a comma-separated
467list of attribute names in the <what> selector:
468
469>    attrs=<attribute list>
470
471A specific value of an attribute is selected by using a single
472attribute name and also using a value selector:
473
474>    attrs=<attribute> val[.<style>]=<regex>
475
476There are two special {{pseudo}} attributes {{EX:entry}} and
477{{EX:children}}.  To read (and hence return) a target entry, the
478subject must have {{EX:read}} access to the target's {{entry}}
479attribute.  To perform a search, the subject must have
480{{EX:search}} access to the search base's {{entry}} attribute.
481To add or delete an entry, the subject must have
482{{EX:write}} access to the entry's {{EX:entry}} attribute AND must
483have {{EX:write}} access to the entry's parent's {{EX:children}}
484attribute.  To rename an entry, the subject must have {{EX:write}}
485access to entry's {{EX:entry}} attribute AND have {{EX:write}}
486access to both the old parent's and new parent's {{EX:children}}
487attributes.  The complete examples at the end of this section should
488help clear things up.
489
490Lastly, there is a special entry selector {{EX:"*"}} that is used to
491select any entry.  It is used when no other {{EX:<what>}}
492selector has been provided.  It's equivalent to "{{EX:dn=.*}}"
493
494
495H3: Who to grant access to
496
497The <who> part identifies the entity or entities being granted
498access. Note that access is granted to "entities" not "entries."
499The following table summarizes entity specifiers:
500
501!block table; align=Center; coltags="EX,N"; \
502    title="Table 5.3: Access Entity Specifiers"
503Specifier|Entities
504*|All, including anonymous and authenticated users
505anonymous|Anonymous (non-authenticated) users
506users|Authenticated users
507self|User associated with target entry
508dn[.<basic-style>]=<regex>|Users matching a regular expression
509dn.<scope-style>=<DN>|Users within scope of a DN
510!endblock
511
512The DN specifier behaves much like <what> clause DN specifiers.
513
514Other control factors are also supported.  For example, a {{EX:<who>}}
515can be restricted by an entry listed in a DN-valued attribute in
516the entry to which the access applies:
517
518>    dnattr=<dn-valued attribute name>
519
520The dnattr specification is used to give access to an entry
521whose DN is listed in an attribute of the entry (e.g., give
522access to a group entry to whoever is listed as the owner of
523the group entry).
524
525Some factors may not be appropriate in all environments (or any).
526For example, the domain factor relies on IP to domain name lookups.
527As these can easily be spoofed, the domain factor should be avoided.
528
529
530H3: The access to grant
531
532The kind of <access> granted can be one of the following:
533
534!block table; colaligns="LRL"; coltags="EX,EX,N"; align=Center; \
535    title="Table 5.4: Access Levels"
536Level        Privileges    Description
537none         =0            no access
538disclose     =d            needed for information disclosure on error
539auth         =dx           needed to authenticate (bind)
540compare      =cdx          needed to compare
541search       =scdx         needed to apply search filters
542read         =rscdx        needed to read search results
543write        =wrscdx       needed to modify/rename
544manage       =mwrscdx      needed to manage
545!endblock
546
547Each level implies all lower levels of access. So, for example,
548granting someone {{EX:write}} access to an entry also grants them
549{{EX:read}}, {{EX:search}}, {{EX:compare}}, {{EX:auth}} and
550{{EX:disclose}} access.  However, one may use the privileges specifier
551to grant specific permissions.
552
553
554H3: Access Control Evaluation
555
556When evaluating whether some requester should be given access to
557an entry and/or attribute, slapd compares the entry and/or attribute
558to the {{EX:<what>}} selectors given in the configuration.  For
559each entry, access controls provided in the database which holds
560the entry (or the global access directives if not held in any database) apply
561first, followed by the global access directives (which are held in
562the {{EX:frontend}} database definition). However, when dealing with
563an access list, because the global access list is effectively appended
564to each per-database list, if the resulting list is non-empty then the
565access list will end with an implicit {{EX:access to * by * none}} directive.
566If there are no access directives applicable to a backend, then a default
567read is used.
568
569Within this priority,
570access directives are examined in the order in which they appear
571in the configuration attribute.  Slapd stops with the first
572{{EX:<what>}} selector that matches the entry and/or attribute. The
573corresponding access directive is the one slapd will use to evaluate
574access.
575
576Next, slapd compares the entity requesting access to the {{EX:<who>}}
577selectors within the access directive selected above in the order
578in which they appear. It stops with the first {{EX:<who>}} selector
579that matches the requester. This determines the access the entity
580requesting access has to the entry and/or attribute.
581
582Finally, slapd compares the access granted in the selected
583{{EX:<access>}} clause to the access requested by the client. If
584it allows greater or equal access, access is granted. Otherwise,
585access is denied.
586
587The order of evaluation of access directives makes their placement
588in the configuration file important. If one access directive is
589more specific than another in terms of the entries it selects, it
590should appear first in the configuration. Similarly, if one {{EX:<who>}}
591selector is more specific than another it should come first in the
592access directive. The access control examples given below should
593help make this clear.
594
595
596
597H3: Access Control Examples
598
599The access control facility described above is quite powerful.  This
600section shows some examples of its use for descriptive purposes.
601
602A simple example:
603
604>    olcAccess: to * by * read
605
606This access directive grants read access to everyone.
607
608>    olcAccess: to *
609>        by self write
610>        by anonymous auth
611>        by * read
612
613This directive allows the user to modify their entry, allows anonymous
614to authenticate against these entries, and allows all others to
615read these entries.  Note that only the first {{EX:by <who>}} clause
616which matches applies.  Hence, the anonymous users are granted
617{{EX:auth}}, not {{EX:read}}.  The last clause could just as well
618have been "{{EX:by users read}}".
619
620It is often desirable to restrict operations based upon the level
621of protection in place.  The following shows how security strength
622factors (SSF) can be used.
623
624>    olcAccess: to *
625>        by ssf=128 self write
626>        by ssf=64 anonymous auth
627>        by ssf=64 users read
628
629This directive allows users to modify their own entries if security
630protections of strength 128 or better have been established,
631allows authentication access to anonymous users, and read access
632when strength 64 or better security protections have been established.  If
633the client has not establish sufficient security protections, the
634implicit {{EX:by * none}} clause would be applied.
635
636The following example shows the use of style specifiers to select
637the entries by DN in two access directives where ordering is
638significant.
639
640>    olcAccess: to dn.children="dc=example,dc=com"
641>         by * search
642>    olcAccess: to dn.children="dc=com"
643>         by * read
644
645Read access is granted to entries under the {{EX:dc=com}} subtree,
646except for those entries under the {{EX:dc=example,dc=com}} subtree,
647to which search access is granted.  No access is granted to
648{{EX:dc=com}} as neither access directive matches this DN.  If the
649order of these access directives was reversed, the trailing directive
650would never be reached, since all entries under {{EX:dc=example,dc=com}}
651are also under {{EX:dc=com}} entries.
652
653Also note that if no {{EX:olcAccess: to}} directive matches or no {{EX:by
654<who>}} clause, {{B:access is denied}}.  When dealing with an access list,
655because the global access list is effectively appended to each per-database
656list, if the resulting list is non-empty then the access list will end with
657an implicit {{EX:access to * by * none}} directive. If there are no access
658directives applicable to a backend, then a default read is used.
659
660The next example again shows the importance of ordering, both of
661the access directives and the {{EX:by <who>}} clauses.  It also
662shows the use of an attribute selector to grant access to a specific
663attribute and various {{EX:<who>}} selectors.
664
665>    olcAccess: to dn.subtree="dc=example,dc=com" attrs=homePhone
666>        by self write
667>        by dn.children=dc=example,dc=com" search
668>        by peername.regex=IP=10\..+ read
669>    olcAccess: to dn.subtree="dc=example,dc=com"
670>        by self write
671>        by dn.children="dc=example,dc=com" search
672>        by anonymous auth
673
674This example applies to entries in the "{{EX:dc=example,dc=com}}"
675subtree. To all attributes except {{EX:homePhone}}, an entry can
676write to itself, entries under {{EX:example.com}} entries can search
677by them, anybody else has no access (implicit {{EX:by * none}})
678excepting for authentication/authorization (which is always done
679anonymously).  The {{EX:homePhone}} attribute is writable by the
680entry, searchable by entries under {{EX:example.com}}, readable by
681clients connecting from network 10, and otherwise not readable
682(implicit {{EX:by * none}}).  All other access is denied by the
683implicit {{EX:access to * by * none}}.
684
685Sometimes it is useful to permit a particular DN to add or
686remove itself from an attribute. For example, if you would like to
687create a group and allow people to add and remove only
688their own DN from the member attribute, you could accomplish
689it with an access directive like this:
690
691>    olcAccess: to attrs=member,entry
692>         by dnattr=member selfwrite
693
694The dnattr {{EX:<who>}} selector says that the access applies to
695entries listed in the {{EX:member}} attribute. The {{EX:selfwrite}} access
696selector says that such members can only add or delete their
697own DN from the attribute, not other values. The addition of
698the entry attribute is required because access to the entry is
699required to access any of the entry's attributes.
700
701
702
703H3: Access Control Ordering
704
705Since the ordering of {{EX:olcAccess}} directives is essential to their
706proper evaluation, but LDAP attributes normally do not preserve the
707ordering of their values, OpenLDAP uses a custom schema extension to
708maintain a fixed ordering of these values. This ordering is maintained
709by prepending a {{EX:"{X}"}} numeric index to each value, similarly to
710the approach used for ordering the configuration entries. These index
711tags are maintained automatically by slapd and do not need to be specified
712when originally defining the values. For example, when you create the
713settings
714
715>    olcAccess: to attrs=member,entry
716>         by dnattr=member selfwrite
717>    olcAccess: to dn.children="dc=example,dc=com"
718>         by * search
719>    olcAccess: to dn.children="dc=com"
720>         by * read
721
722when you read them back using slapcat or ldapsearch they will contain
723
724>    olcAccess: {0}to attrs=member,entry
725>         by dnattr=member selfwrite
726>    olcAccess: {1}to dn.children="dc=example,dc=com"
727>         by * search
728>    olcAccess: {2}to dn.children="dc=com"
729>         by * read
730
731The numeric index may be used to specify a particular value to change
732when using ldapmodify to edit the access rules. This index can be used
733instead of (or in addition to) the actual access value. Using this
734numeric index is very helpful when multiple access rules are being managed.
735
736For example, if we needed to change the second rule above to grant
737write access instead of search, we could try this LDIF:
738
739>    changetype: modify
740>    delete: olcAccess
741>    olcAccess: to dn.children="dc=example,dc=com" by * search
742>    -
743>    add: olcAccess
744>    olcAccess: to dn.children="dc=example,dc=com" by * write
745>    -
746
747But this example {{B:will not}} guarantee that the existing values remain in
748their original order, so it will most likely yield a broken security
749configuration. Instead, the numeric index should be used:
750
751>    changetype: modify
752>    delete: olcAccess
753>    olcAccess: {1}
754>    -
755>    add: olcAccess
756>    olcAccess: {1}to dn.children="dc=example,dc=com" by * write
757>    -
758
759This example deletes whatever rule is in value #1 of the {{EX:olcAccess}}
760attribute (regardless of its value) and adds a new value that is
761explicitly inserted as value #1. The result will be
762
763>    olcAccess: {0}to attrs=member,entry
764>         by dnattr=member selfwrite
765>    olcAccess: {1}to dn.children="dc=example,dc=com"
766>         by * write
767>    olcAccess: {2}to dn.children="dc=com"
768>         by * read
769
770which is exactly what was intended.
771
772!if 0
773For more details on how to use the {{EX:access}} directive,
774consult the {{Advanced Access Control}} chapter.
775!endif
776
777
778H2: Access Control Common Examples
779
780H3: Basic ACLs
781
782Generally one should start with some basic ACLs such as:
783
784>    access to attrs=userPassword
785>        by self =xw
786>        by anonymous auth
787>        by * none
788>
789>
790>      access to *
791>        by self write
792>        by users read
793>        by * none
794
795The first ACL allows users to update (but not read) their passwords, anonymous
796users to authenticate against this attribute, and (implicitly) denying all
797access to others.
798
799The second ACL allows users full access to their entry, authenticated users read
800access to anything, and (implicitly) denying all access to others (in this case,
801anonymous users).
802
803
804H3: Matching Anonymous and Authenticated users
805
806An anonymous user has a empty DN. While the {{dn.exact=""}} or {{dn.regex="^$"}}
807 could be used, {{slapd}}(8)) offers an anonymous shorthand which should be
808used instead.
809
810>    access to *
811>      by anonymous none
812>      by * read
813
814denies all access to anonymous users while granting others read.
815
816Authenticated users have a subject DN. While {{dn.regex=".+"}} will match any
817authenticated user, OpenLDAP provides the users short hand which should be used
818instead.
819
820>    access to *
821>      by users read
822>      by * none
823
824This ACL grants read permissions to authenticated users while denying others
825(i.e.: anonymous users).
826
827
828H3: Controlling rootdn access
829
830You could specify the {{rootdn}} in {{slapd.conf}}(5) or {{slapd.d}} without
831specifying a {{rootpw}}. Then you have to add an actual directory entry with
832the same dn, e.g.:
833
834>    dn: cn=Manager,o=MyOrganization
835>    cn: Manager
836>    sn: Manager
837>    objectClass: person
838>    objectClass: top
839>    userPassword: {SSHA}someSSHAdata
840
841Then binding as the {{rootdn}} will require a regular bind to that DN, which
842in turn requires auth access to that entry's DN and {{userPassword}}, and this
843can be restricted via ACLs. E.g.:
844
845>    access to dn.base="cn=Manager,o=MyOrganization"
846>      by peername.regex=127\.0\.0\.1 auth
847>      by peername.regex=192\.168\.0\..* auth
848>      by users none
849>      by * none
850
851The ACLs above will only allow binding using rootdn from localhost and
852192.168.0.0/24.
853
854
855H3: Managing access with Groups
856
857There are a few ways to do this. One approach is illustrated here. Consider the
858following DIT layout:
859
860>    +-dc=example,dc=com
861>    +---cn=administrators,dc=example,dc=com
862>    +---cn=fred blogs,dc=example,dc=com
863
864and the following group object (in LDIF format):
865
866>    dn: cn=administrators,dc=example,dc=com
867>    cn: administrators of this region
868>    objectclass: groupOfNames  (important for the group acl feature)
869>    member: cn=fred blogs,dc=example,dc=com
870>    member: cn=somebody else,dc=example,dc=com
871
872One can then grant access to the members of this this group by adding appropriate
873{{by group}} clause to an access directive in {{slapd.conf}}(5). For instance,
874
875>    access to dn.children="dc=example,dc=com"
876>        by self write
877>        by group.exact="cn=Administrators,dc=example,dc=com" write
878>        by * auth
879
880Like by {{dn}} clauses, one can also use {{expand}} to expand the group name
881based upon the regular expression matching of the target, that is, the to {{dn.regex}}).
882For instance,
883
884>    access to dn.regex="(.+,)?ou=People,(dc=[^,]+,dc=[^,]+)$"
885>             attrs=children,entry,uid
886>        by group.expand="cn=Managers,$2" write
887>        by users read
888>        by * auth
889
890
891The above illustration assumed that the group members are to be found in the
892{{member}} attribute type of the {{groupOfNames}} object class. If you need to
893use a different group object and/or a different attribute type then use the
894following {{slapd.conf}}(5) (abbreviated) syntax:
895
896>    access to <what>
897>            by group/<objectclass>/<attributename>=<DN> <access>
898
899For example:
900
901>    access to *
902>      by group/organizationalRole/roleOccupant="cn=Administrator,dc=example,dc=com" write
903
904In this case, we have an ObjectClass {{organizationalRole}} which contains the
905administrator DN's in the {{roleOccupant}} attribute. For instance:
906
907>    dn: cn=Administrator,dc=example,dc=com
908>    cn: Administrator
909>    objectclass: organizationalRole
910>    roleOccupant: cn=Jane Doe,dc=example,dc=com
911
912Note: the specified member attribute type MUST be of DN or {{NameAndOptionalUID}} syntax,
913and the specified object class SHOULD allow the attribute type.
914
915Dynamic Groups are also supported in Access Control. Please see {{slapo-dynlist}}(5)
916and the {{SECT:Dynamic Lists}} overlay section.
917
918
919H3:  Granting access to a subset of attributes
920
921You can grant access to a set of attributes by specifying a list of attribute names
922in the ACL {{to}} clause. To be useful, you also need to grant access to the
923{{entry}} itself. Also note how {{children}} controls the ability to add, delete,
924and rename entries.
925
926>    # mail: self may write, authenticated users may read
927>    access to attrs=mail
928>      by self write
929>      by users read
930>      by * none
931>
932>    # cn, sn: self my write, all may read
933>    access to attrs=cn,sn
934>      by self write
935>      by * read
936>
937>    # immediate children: only self can add/delete entries under this entry
938>    access to attrs=children
939>      by self write
940>
941>    # entry itself: self may write, all may read
942>    access to attrs=entry
943>      by self write
944>      by * read
945>
946>    # other attributes: self may write, others have no access
947>    access to *
948>      by self write
949>      by * none
950
951ObjectClass names may also be specified in this list, which will affect
952all the attributes that are required and/or allowed by that {{objectClass}}.
953Actually, names in {{attrlist}} that are prefixed by {{@}} are directly treated
954as objectClass names. A name prefixed by {{!}} is also treated as an objectClass,
955but in this case the access rule affects the attributes that are not required
956nor allowed by that {{objectClass}}.
957
958
959H3: Allowing a user write to all entries below theirs
960
961For a setup where a user can write to its own record and to all of its children:
962
963>    access to dn.regex="(.+,)?(uid=[^,]+,o=Company)$"
964>       by dn.exact,expand="$2" write
965>       by anonymous auth
966
967(Add more examples for above)
968
969
970H3: Allowing entry creation
971
972Let's say, you have it like this:
973
974>        o=<basedn>
975>            ou=domains
976>                associatedDomain=<somedomain>
977>                    ou=users
978>                        uid=<someuserid>
979>                        uid=<someotheruserid>
980>                    ou=addressbooks
981>                        uid=<someuserid>
982>                            cn=<someone>
983>                            cn=<someoneelse>
984
985and, for another domain <someotherdomain>:
986
987>        o=<basedn>
988>            ou=domains
989>                associatedDomain=<someotherdomain>
990>                    ou=users
991>                        uid=<someuserid>
992>                        uid=<someotheruserid>
993>                    ou=addressbooks
994>                        uid=<someotheruserid>
995>                            cn=<someone>
996>                            cn=<someoneelse>
997
998then, if you wanted user {{uid=<someuserid>}} to {{B:ONLY}} create an entry
999for its own thing, you could write an ACL like this:
1000
1001>    # this rule lets users of "associatedDomain=<matcheddomain>"
1002>    # write under "ou=addressbook,associatedDomain=<matcheddomain>,ou=domains,o=<basedn>",
1003>    # i.e. a user can write ANY entry below its domain's address book;
1004>    # this permission is necessary, but not sufficient, the next
1005>    # will restrict this permission further
1006>
1007>
1008>    access to dn.regex="^ou=addressbook,associatedDomain=([^,]+),ou=domains,o=<basedn>$" attrs=children
1009>            by dn.regex="^uid=([^,]+),ou=users,associatedDomain=$1,ou=domains,o=<basedn>$$" write
1010>            by * none
1011>
1012>
1013>    # Note that above the "by" clause needs a "regex" style to make sure
1014>    # it expands to a DN that starts with a "uid=<someuserid>" pattern
1015>    # while substituting the associatedDomain submatch from the "what" clause.
1016>
1017>
1018>    # This rule lets a user with "uid=<matcheduid>" of "<associatedDomain=matcheddomain>"
1019>    # write (i.e. add, modify, delete) the entry whose DN is exactly
1020>    # "uid=<matcheduid>,ou=addressbook,associatedDomain=<matcheddomain>,ou=domains,o=<basedn>"
1021>    # and ANY entry as subtree of it
1022>
1023>
1024>    access to dn.regex="^(.+,)?uid=([^,]+),ou=addressbook,associatedDomain=([^,]+),ou=domains,o=<basedn>$"
1025>            by dn.exact,expand="uid=$2,ou=users,associatedDomain=$3,ou=domains,o=<basedn>" write
1026>            by * none
1027>
1028>
1029>    # Note that above the "by" clause uses the "exact" style with the "expand"
1030>    # modifier because now the whole pattern can be rebuilt by means of the
1031>    # submatches from the "what" clause, so a "regex" compilation and evaluation
1032>    # is no longer required.
1033
1034
1035H3: Tips for using regular expressions in Access Control
1036
1037Always use {{dn.regex=<pattern>}} when you intend to use regular expression
1038matching. {{dn=<pattern>}} alone defaults to {{dn.exact<pattern>}}.
1039
1040Use {{(.+)}} instead of {{(.*)}} when you want at least one char to be matched.
1041{{(.*)}} matches the empty string as well.
1042
1043Don't use regular expressions for matches that can be done otherwise in a safer
1044and cheaper manner. Examples:
1045
1046>    dn.regex=".*dc=example,dc=com"
1047
1048is unsafe and expensive:
1049
1050    * unsafe because any string containing {{dc=example,dc=com }}will match,
1051not only those that end with the desired pattern; use {{.*dc=example,dc=com$}} instead.
1052    * unsafe also because it would allow any {{attributeType}} ending with {{dc}}
1053 as naming attribute for the first RDN in the string, e.g. a custom attributeType
1054{{mydc}} would match as well. If you really need a regular expression that allows
1055just {{dc=example,dc=com}} or any of its subtrees, use {{^(.+,)?dc=example,dc=com$}},
1056which means: anything to the left of dc=..., if any (the question mark after the
1057pattern within brackets), must end with a comma;
1058    * expensive because if you don't need submatches, you could use scoping styles, e.g.
1059
1060>    dn.subtree="dc=example,dc=com"
1061
1062to include {{dc=example,dc=com}} in the matching patterns,
1063
1064>    dn.children="dc=example,dc=com"
1065
1066to exclude {{dc=example,dc=com}} from the matching patterns, or
1067
1068>    dn.onelevel="dc=example,dc=com"
1069
1070to allow exactly one sublevel matches only.
1071
1072Always use {{^}} and {{$}} in regexes, whenever appropriate, because
1073{{ou=(.+),ou=(.+),ou=addressbooks,o=basedn}} will match
1074{{something=bla,ou=xxx,ou=yyy,ou=addressbooks,o=basedn,ou=addressbooks,o=basedn,dc=some,dc=org}}
1075
1076Always use {{([^,]+)}} to indicate exactly one RDN, because {{(.+)}} can
1077include any number of RDNs; e.g. {{ou=(.+),dc=example,dc=com}} will match
1078{{ou=My,o=Org,dc=example,dc=com}}, which might not be what you want.
1079
1080Never add the rootdn to the by clauses. ACLs are not even processed for operations
1081performed with rootdn identity (otherwise there would be no reason to define a
1082rootdn at all).
1083
1084Use shorthands. The user directive matches authenticated users and the anonymous
1085directive matches anonymous users.
1086
1087Don't use the {{dn.regex}} form for <by> clauses if all you need is scoping
1088and/or substring replacement; use scoping styles (e.g. {{exact}}, {{onelevel}},
1089{{children}} or {{subtree}}) and the style modifier expand to cause substring expansion.
1090
1091For instance,
1092
1093>    access to dn.regex=".+,dc=([^,]+),dc=([^,]+)$"
1094>      by dn.regex="^[^,],ou=Admin,dc=$1,dc=$2$$" write
1095
1096although correct, can be safely and efficiently replaced by
1097
1098>    access to dn.regex=".+,(dc=[^,]+,dc=[^,]+)$"
1099>      by dn.onelevel,expand="ou=Admin,$1" write
1100
1101where the regex in the {{<what>}} clause is more compact, and the one in the {{<by>}}
1102clause is replaced by a much more efficient scoping style of onelevel with substring expansion.
1103
1104
1105H3: Granting and Denying access based on security strength factors (ssf)
1106
1107You can restrict access based on the security strength factor (SSF)
1108
1109>    access to dn="cn=example,cn=edu"
1110>          by * ssf=256 read
1111
11120 (zero) implies no protection,
11131 implies integrity protection only,
111456 DES or other weak ciphers,
1115112 triple DES and similar ciphers,
1116128 RC4, Blowfish and other similar ciphers,
1117256 modern ciphers.
1118
1119Other possibilities:
1120
1121>    transport_ssf=<n>
1122>    tls_ssf=<n>
1123>    sasl_ssf=<n>
1124
1125256 is recommended.
1126
1127See {{slapd.conf}}(5) for information on {{ssf}}.
1128
1129
1130H3: When things aren't working as expected
1131
1132Consider this example:
1133
1134>    access to *
1135>      by anonymous auth
1136>
1137>    access to *
1138>      by self write
1139>
1140>    access to *
1141>      by users read
1142
1143You may think this will allow any user to login, to read everything and change
1144his own data if he is logged in. But in this example only the login works and
1145an ldapsearch returns no data. The Problem is that SLAPD goes through its access
1146config line by line and stops as soon as it finds a match in the part of the
1147access rule.(here: {{to *}})
1148
1149To get what we wanted the file has to read:
1150
1151>    access to *
1152>      by anonymous auth
1153>      by self write
1154>      by users read
1155
1156The general rule is: "special access rules first, generic access rules last"
1157
1158See also {{slapd.access}}(5), loglevel 128 and {{slapacl}}(8) for debugging
1159information.
1160
1161
1162H2: Sets - Granting rights based on relationships
1163
1164Sets are best illustrated via examples. The following sections will present
1165a few set ACL examples in order to facilitate their understanding.
1166
1167(Sets in Access Controls FAQ Entry: {{URL:http://www.openldap.org/faq/data/cache/1133.html}})
1168
1169Note: Sets are considered experimental.
1170
1171
1172H3: Groups of Groups
1173
1174The OpenLDAP ACL for groups doesn't expand groups within groups, which are
1175groups that have another group as a member. For example:
1176
1177> dn: cn=sudoadm,ou=group,dc=example,dc=com
1178> cn: sudoadm
1179> objectClass: groupOfNames
1180> member: uid=john,ou=people,dc=example,dc=com
1181> member: cn=accountadm,ou=group,dc=example,dc=com
1182>
1183> dn: cn=accountadm,ou=group,dc=example,dc=com
1184> cn: accountadm
1185> objectClass: groupOfNames
1186> member: uid=mary,ou=people,dc=example,dc=com
1187
1188If we use standard group ACLs with the above entries and allow members of the
1189{{F:sudoadm}} group to write somewhere, {{F:mary}} won't be included:
1190
1191> access to dn.subtree="ou=sudoers,dc=example,dc=com"
1192>         by group.exact="cn=sudoadm,ou=group,dc=example,dc=com" write
1193>         by * read
1194
1195With sets we can make the ACL be recursive and consider group within groups. So
1196for each member that is a group, it is further expanded:
1197
1198> access to dn.subtree="ou=sudoers,dc=example,dc=com"
1199>       by set="[cn=sudoadm,ou=group,dc=example,dc=com]/member* & user" write
1200>       by * read
1201
1202This set ACL means: take the {{F:cn=sudoadm}} DN, check its {{F:member}}
1203attribute(s) (where the "{{F:*}}" means recursively) and intersect the result
1204with the authenticated user's DN. If the result is non-empty, the ACL is
1205considered a match and write access is granted.
1206
1207The following drawing explains how this set is built:
1208!import "set-recursivegroup.png"; align="center"; title="Building a recursive group"
1209FT[align="Center"] Figure X.Y: Populating a recursive group set
1210
1211First we get the {{F:uid=john}} DN. This entry doesn't have a {{F:member}}
1212attribute, so the expansion stops here.  Now we get to {{F:cn=accountadm}}.
1213This one does have a {{F:member}} attribute, which is {{F:uid=mary}}. The
1214{{F:uid=mary}} entry, however, doesn't have member, so we stop here again. The
1215end comparison is:
1216
1217> {"uid=john,ou=people,dc=example,dc=com","uid=mary,ou=people,dc=example,dc=com"} & user
1218
1219If the authenticated user's DN is any one of those two, write access is
1220granted. So this set will include {{F:mary}} in the {{F:sudoadm}} group and she
1221will be allowed the write access.
1222
1223H3: Group ACLs without DN syntax
1224
1225The traditional group ACLs, and even the previous example about recursive groups, require
1226that the members are specified as DNs instead of just usernames.
1227
1228With sets, however, it's also possible to use simple names in group ACLs, as this example will
1229show.
1230
1231Let's say we want to allow members of the {{F:sudoadm}} group to write to the
1232{{F:ou=sudoers}} branch of our tree. But our group definition now is using {{F:memberUid}} for
1233the group members:
1234
1235> dn: cn=sudoadm,ou=group,dc=example,dc=com
1236> cn: sudoadm
1237> objectClass: posixGroup
1238> gidNumber: 1000
1239> memberUid: john
1240
1241With this type of group, we can't use group ACLs. But with a set ACL we can
1242grant the desired access:
1243
1244> access to dn.subtree="ou=sudoers,dc=example,dc=com"
1245>       by set="[cn=sudoadm,ou=group,dc=example,dc=com]/memberUid & user/uid" write
1246>       by * read
1247
1248We use a simple intersection where we compare the {{F:uid}} attribute
1249of the connecting (and authenticated) user with the {{F:memberUid}} attributes
1250of the group. If they match, the intersection is non-empty and the ACL will
1251grant write access.
1252
1253This drawing illustrates this set when the connecting user is authenticated as
1254{{F:uid=john,ou=people,dc=example,dc=com}}:
1255!import "set-memberUid.png"; align="center"; title="Sets with memberUid"
1256FT[align="Center"] Figure X.Y: Sets with {{F:memberUid}}
1257
1258In this case, it's a match. If it were {{F:mary}} authenticating, however, she
1259would be denied write access to {{F:ou=sudoers}} because her {{F:uid}}
1260attribute is not listed in the group's {{F:memberUid}}.
1261
1262H3: Following references
1263
1264We will now show a quite powerful example of what can be done with sets. This
1265example tends to make OpenLDAP administrators smile after they have understood
1266it and its implications.
1267
1268Let's start with an user entry:
1269
1270> dn: uid=john,ou=people,dc=example,dc=com
1271> uid: john
1272> objectClass: inetOrgPerson
1273> givenName: John
1274> sn: Smith
1275> cn: john
1276> manager: uid=mary,ou=people,dc=example,dc=com
1277
1278Writing an ACL to allow the manager to update some attributes is quite simple
1279using sets:
1280
1281> access to dn.exact="uid=john,ou=people,dc=example,dc=com"
1282>    attrs=carLicense,homePhone,mobile,pager,telephoneNumber
1283>    by self write
1284>    by set="this/manager & user" write
1285>    by * read
1286
1287In that set, {{F:this}} expands to the entry being accessed, so that
1288{{F:this/manager}} expands to {{F:uid=mary,ou=people,dc=example,dc=com}} when
1289john's entry is accessed.  If the manager herself is accessing John's entry,
1290the ACL will match and write access to those attributes will be granted.
1291
1292So far, this same behavior can be obtained with the {{F:dnattr}} keyword. With
1293sets, however, we can further enhance this ACL. Let's say we want to allow the
1294secretary of the manager to also update these attributes. This is how we do it:
1295
1296> access to dn.exact="uid=john,ou=people,dc=example,dc=com"
1297>    attrs=carLicense,homePhone,mobile,pager,telephoneNumber
1298>    by self write
1299>    by set="this/manager & user" write
1300>    by set="this/manager/secretary & user" write
1301>    by * read
1302
1303Now we need a picture to help explain what is happening here (entries shortened
1304for clarity):
1305
1306!import "set-following-references.png"; align="center"; title="Sets jumping through entries"
1307FT[align="Center"] Figure X.Y: Sets jumping through entries
1308
1309In this example, Jane is the secretary of Mary, which is the manager of John.
1310This whole relationship is defined with the {{F:manager}} and {{F:secretary}}
1311attributes, which are both of the distinguishedName syntax (i.e., full DNs).
1312So, when the {{F:uid=john}} entry is being accessed, the
1313{{F:this/manager/secretary}} set becomes
1314{{F:{"uid=jane,ou=people,dc=example,dc=com"}}} (follow the references in the
1315picture):
1316
1317> this = [uid=john,ou=people,dc=example,dc=com]
1318> this/manager = \
1319>   [uid=john,ou=people,dc=example,dc=com]/manager = uid=mary,ou=people,dc=example,dc=com
1320> this/manager/secretary = \
1321>   [uid=mary,ou=people,dc=example,dc=com]/secretary = uid=jane,ou=people,dc=example,dc=com
1322
1323The end result is that when Jane accesses John's entry, she will be granted
1324write access to the specified attributes. Better yet, this will happen to any
1325entry she accesses which has Mary as the manager.
1326
1327This is all cool and nice, but perhaps gives too much power to secretaries. Maybe we need to further
1328restrict it. For example, let's only allow executive secretaries to have this power:
1329
1330> access to dn.exact="uid=john,ou=people,dc=example,dc=com"
1331>   attrs=carLicense,homePhone,mobile,pager,telephoneNumber
1332>   by self write
1333>   by set="this/manager & user" write
1334>   by set="this/manager/secretary &
1335>           [cn=executive,ou=group,dc=example,dc=com]/member* &
1336>           user" write
1337>   by * read
1338
1339It's almost the same ACL as before, but we now also require that the connecting user be a member
1340of the (possibly nested) {{F:cn=executive}} group.
1341
1342
1343