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