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