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