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