[Date Prev][Date Next] [Chronological] [Thread] [Top]

Complementing "set" ACLs documentation



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