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

Re: (ITS#5884) disclose ACL not safe on non-leaf objects



Hi Andrew,

andrew.findlay@skills-1st.co.uk wrote:
> On Mon, Jan 12, 2009 at 07:47:20PM +0000, hyc@symas.com wrote:
>
>   
>>> For example, if I have a DIT like this:
>>>
>>> dc=example,dc=org--+
>>>                     +--dc=a--+
>>>                     |        +--dc=people--+
>>>                     |                      +--cn=a1
>>>                     |
>>>                     +--dc=b--+
>>>                              +--dc=people--+
>>>                                            +--cn=b1
>>>
>>> and I give read access on dc=example,dc=org (base)
>>> and on dc=a,dc=example,dc=org (subtree)
>>> and dc=people,dc=b,dc=example,dc=org (subtree)
>>> but no access at all on dc=b,dc=example,dc=org
>>> then I would not expect to be able to read the cn=b1 entry, as doing so would
>>> expose the existence of dc=b.
>>>
>>> What actually happens is that any attempt to read dc=b itself returns
>>> correctly as if the entry does not exist, but a simple subtree search
>>> happily returns cn=b1.
>>>       
> I want to make the discoverability of entries dependent on the value of
> an attribute in a parent node, but I cannot see a way of doing it using
> the existing ACL syntax and behaviour.
>
> The closest I have got so far is to use the set syntax in a deny rule:
>
> # Blockers - look for exampleVisibility=block in all parent entries
> #
> access to *
>         by set="this/-*/exampleVisibility & [block]" none
>         by * break
>
> This allows any entry to block its subtree to *all* users by setting 
> exampleVisibility=block
> There does not seem to be any way to make the block dependent on
> *who* is requesting access, as sets are only valid in the 'by <who>'
> part of the rule.
>   
You can refer to *who* in the 'by' part of a set-based rule.

Here is an example to limit your "deny" ACL to a category of population:

access to *
    by set="(this/-*/exampleVisibility & [block])/-100 &
(user/bypassBlock & [TRUE])/-100"
    by * break

The trick is returning a non empty set. To do this, "/-100" return the
100th parent of each entry. The algorithm is coded so as to return the
highest existing parent if it less than 100 degrees away ("dc=org", in
your example). However, if one or the other of the sets is empty (ie
user doesn't match), this returns an empty set.

Obviously, 100 is a conservative value, and some performance improvement
may be obtained with a smaller value of 100. Or, a function that makes
it less of a hack :)

Regards,
Jonathan

-- 
Jonathan Clarke
--
LinID - Open Source Identity Management
---------------------------------------------------------------
Linagora
27 rue de Berri, 75008 Paris
Tel: 01 58 18 68 28 / 06 99 60 03 10
---------------------------------------------------------------
Ldap Synchronization Connector (LSC) - http://lsc-project.org/
---------------------------------------------------------------