Hi,
I will try to explain "set" ACLs complementing the information originally written by Mark Valence in the openldap-devel archive (http://www.openldap.org/lists/openldap-devel/200006/msg00046.html). Set ACLs are a bit tricky and difficult to understand without the appropiate documentation. I hope this information helps to understand this kind of ACLs.
1. SYNTAX ---------
First of all, the sintax in Backus-Naur form:
<set> := <base> | "(" <set> ")" | <set> <conj> <set> | <set> "/" <attribute> "*" | <set> "/" <attribute> | <set> "/-" <level> | <set> "/-*" <base> := "this" | "user" | "[" <any text> "]" <conj> := "&" | "|" | "+" <attribute> := an attributeType as defined in the schema
Of course, anywhere in the string, submatch replacements can appear in the form $<digit> or ${<digits>} if "set.regex=" is used instead "set=".
1.1. this, user and [] ----------------------
Keyword "this" means the object being accessed. So, if you are trying to read "cn=ignacio,ou=users,dc=foo,dc=com", "this" refers to "cn=ignacio,ou=users,dc=foo,dc=com" object. Keywork "user" means the object used to authenticate. If you are trying to read "cn=ignacio,ou=users,dc=foo,dc=com" authenticated as "cn=admin,dc=foo,dc=com", "user" refers to "cn=admin,dc=foo,dc=com" object. Keyword "[<text>]" means any text you need to use. For example "[cn=admin,dc=foo,dc=com]", "[FOO]". In other words, like strings in any programming language.
1.2. Object attributes ----------------------
Using the keywords of the previous section, you can access to the value of an attribute of a given object using the "/" operator.
So, with an object like the next:
dn: cn=ignacio,ou=users,dc=foo,dc=com uid: ignacio cn: ignacio description: Ignacio Gallegos Sanchez homeDirectory: /home/ignacio objectClass: posixAccount objectClass: top objectClass: account uidNumber: 800 structuralObjectClass: account gidNumber: 800 userPassword: MyPassword
The expression "[cn=ignacio,ou=users,dc=foo,dc=com]/cn" will return "ignacio". The expression "this/uidNumber" will return "800" only if the target object is "cn=ignacio,ou=users,dc=foo,dc=com".
1.3. Operators &, | and + -------------------------
With a brief explanation: * & is a logic AND operator * | is a logic OR operator * + concatenates strings
With examples: * "[A] & [A]" will return "A" * "[A] & [B]" will return an empty set * "[A] | [B]" will return "{ A, B }" * "[A] + [B]" will return "AB" * "[ignacio] & user/cn" will return "ignacio" ONLY if the client is authenticated with a user with a "CN" with value "ignacio" * "this & user" will return the object DN if the object used to authenticate is the target object, and will return nothing if not.
1.4. Group recursion --------------------
Using the "*" character we can obtain the group members in a recursive manner.
The sintax is: <object>/<attribute>*
For example, if we have the next objects:
dn: cn=mail,ou=groups,dc=foo,dc=com objectClass: groupOfNames objectClass: top cn: mail member: cn=ignacio,ou=users,dc=foo,dc=com member: cn=claudia,ou=users,dc=foo,dc=com member: cn=clara,ou=users,dc=foo,dc=com
dn: cn=web,ou=groups,dc=foo,dc=com objectClass: groupOfNames objectClass: top cn: web member: cn=oliver,ou=users,dc=foo,dc=com member: cn=sandra,ou=users,dc=foo,dc=com
dn: cn=all_services,ou=groups,dc=foo,dc=com objectClass: groupOfNames objectClass: top cn: all_services member: cn=web,ou=groups,dc=foo,dc=com member: cn=mail,ou=groups,dc=foo,dc=com member: cn=julian,ou=users,dc=foo,dc=com
The expression "[cn=all_services,ou=groups,dc=foo,dc=com]/member*" will return:
{ "member: cn=ignacio,ou=users,dc=foo,dc=com", "member: cn=claudia,ou=users,dc=foo,dc=com", "member: cn=clara,ou=users,dc=foo,dc=com", "member: cn=oliver,ou=users,dc=foo,dc=com", "member: cn=sandra,ou=users,dc=foo,dc=com", "member: cn=julian,ou=users,dc=foo,dc=com" }
1.5. Distingued Name Levels ---------------------------
We can have the different levels of the DN of a given object using the /-<number> operator, or all levels with "/-*".
So if the user is "cn=ignacio,ou=admins,ou=users,dc=foo,dc=com":
* "user" resolves to "cn=ignacio,ou=admins,ou=users,dc=foo,dc=com" * "user/-1" resolves to "ou=admins,ou=users,dc=foo,dc=com" * "user/-2" resolves to "ou=users,dc=foo,dc=com" * "user/-3" resolves to "dc=foo,dc=com" * "user/-*" resolves to { "cn=ignacio,ou=admins,ou=users,dc=foo,dc=com", "ou=admins,ou=users,dc=foo,dc=com", "ou=users,dc=foo,dc=com", "dc=foo,dc=com", "dc=com", "" }
2. ACCESS CONTROL EVALUATION ----------------------------
After the previous examples, it's time to put it all together. -- The way "set" ACLs works is to grant the access if the expression returns something, don't grant access if the expression returns an empty set --, independtly the authenticated user is. This seems very simple (it's indeed) but can be very dangerous: we can grant access to an object by an unwanted user if we dont write the expression carefully.
As usual, it's better to understand it with examples:
* access to dn="ou=users,dc=foo,dc=com" by set="[A]" write
Will grant write access to any user, because the set expression always return "A"
* access to dn="ou=users,dc=foo,dc=com" by set="[A] & [B]" write
Will NOT grant write access to any user, because the set expressions always returns an empty set.
* access to dn="ou=users,dc=foo,dc=com" by set="user" write
Will grant write access to any user, because the set expression always return the user DN.
* access to dn="ou=users,dc=foo,dc=com" by set="user/description" write
Will grant write access only if the object used to authenticate has the attribute "description"
* access to dn="ou=users,dc=foo,dc=com" by set="user & [cn=ignacio,ou=users,dc=foo,dc=com]" write
Will grant write access if the user DN is "cn=ignacio,ou=users,dc=foo,dc=com", because this is the only case the expression "user & [cn=ignacio,ou=users,dc=foo,dc=com]" will return something.
* access to dn="ou=users,dc=foo,dc=com" by set="user/-2 & [dc=foo,dc=com]" write
Will grant write access to any user two levels over "dc=foo,dc=com" domain, independly the "ou" is. In other words, "cn=ignacio,ou=users,dc=foo,dc=com" and "cn=clara,ou=admins,dc=foo,dc=com" will have write access, but "cn=claudia,ou=mail,ou=admins,dc=foo,dc=com" will not.
* access to dn="ou=users,dc=foo,dc=com" by set="user/description & this/description" write
Will grant write access to any user which description match the accessed object description.
* access to dn="ou=users,dc=foo,dc=com" by set="(user/domain & this/domain)/-2 & [dc=foo,dc=com]" write
Will grant write access to any user wich domain attribute match accessed object attribute and also domain is equal to "dc=foo,dc=com".
* access to dn.regex="cn=(.+?),ou=users,(.+?)$" by set.regex="($1 & [ignacio]) & ($2 & [dc=foo,dc=com])" write
Will grant write access if the user cn is "ignacio" and domain is "dc=foo, dc=com".
Best Regards, Ignacio Gallegos Sánchez