Full_Name: Andrew Findlay Version: HEAD 12 Jan 2009 OS: Linux URL: Submission from: (NULL) (88.97.25.132)
Using ACLs to make a non-leaf object non-disclosable does not protect the subtree beneath that object.
This is not what most people would expect (if I cannot see a given object then I would not expect to see things underneath it). It also provides a handy attack on supposedly non-detectable entries.
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.
The workaround is to make every entry in the dc=b subtree non-disclosable, but this can be awkward in some ACL schemes.
I have tested this with both BDB and HDB and got identical results. (I also tried to do it with IBM's ITDS and Sun's DSEE but they don't even support the non-disclose concept...)
There is no RFC for LDAP ACLs so the 'correct' behaviour is debatable...
Here are the files: --------------------------------- slapd.conf --------------------------------- # Logging - this goes to syslog as 'local4' # # 512+256 to enable stats logging # loglevel 768
# Schema definitions # include ../../etc/schema/core.schema include ../../etc/schema/cosine.schema include ../../etc/schema/inetorgperson.schema include ../../etc/schema/nis.schema
# These should have absolute pathnames on production systems pidfile ./slapd.pid argsfile ./slapd.args
######################################################################## # Default ACL # (This is overridden by the per-database ACLs) ########################################################################
access to * by * read
######################################################################## ####################################################################### # The main database ####################################################################### ########################################################################
database hdb suffix "dc=example,dc=org" rootdn "cn=root,dc=example,dc=org"
password-hash {SSHA}
# Cleartext passwords, especially for the rootdn, should # be avoided. See slappasswd(8) and slapd.conf(5) for details. # # The following two lines describe the same password: # rootpw secret # rootpw {SSHA}fFCeSYwjK/wERk1h4ceqYohqrGT/8VxJ # rootpw password
# The database directory MUST exist prior to running slapd AND # should only be accessable by the slapd/tools. Mode 700 recommended. # This should be an absolute pathname on production servers. # directory ./openldap-db
# Entry cache size # cachesize 4000
# How often we force a checkpoint on the underlying database # kilobytes and seconds # checkpoint 128 300
######################################################################## # Indices to maintain ########################################################################
index objectClass eq
######################################################################## # ACLs for this database ########################################################################
include ./slapd.conf.acls
----------------------------- slapd.conf.acls ------------------------------ # Allow unconditional access to the base object # access to dn.exact="dc=example,dc=org" by * read
# Allow read access to the whole of the A subtree # access to dn.subtree="dc=a,dc=example,dc=org" by * read
# Allow read access to B's people, but not to B # access to dn.subtree="dc=people,dc=b,dc=example,dc=org" by * read
access to * by * none
----------------------------- data LDIF ----------------------------------- ######################################################################## # Create the base object ######################################################################## # dn: dc=example,dc=org objectclass: organization objectclass: dcObject o: The Example Org dc: example description: See-under test
######################################################################## # Create departments ######################################################################## # A dn: dc=a,dc=example,dc=org objectclass: organizationalUnit objectclass: dcObject ou: Department A dc: a
dn: dc=people,dc=a,dc=example,dc=org objectclass: organizationalUnit objectclass: dcObject ou: People dc: people
# B dn: dc=b,dc=example,dc=org objectclass: organizationalUnit objectclass: dcObject ou: Department B dc: b
dn: dc=people,dc=b,dc=example,dc=org objectclass: organizationalUnit objectclass: dcObject ou: People dc: people
######################################################################## # Create accounts ######################################################################## #
dn: cn=a1,dc=people,dc=a,dc=example,dc=org objectclass: inetOrgPerson cn: a1 sn: One
dn: cn=b1,dc=people,dc=b,dc=example,dc=org objectclass: inetOrgPerson cn: b1 sn: One
----------------------------- tests -----------------------------------------
# Search for dept A: this should work ldapsearch -x -H ldap://:1389/ -b dc=example,dc=org dc=a
# Search for dept B: this should return zero results as B is protected by ACLs ldapsearch -x -H ldap://:1389/ -b dc=example,dc=org dc=b
# Try starting at dept B: this should return 'no such object' as B is protected by ACLs ldapsearch -x -H ldap://:1389/ -b dc=b,dc=example,dc=org dc=b
# Search for a user in dept A: this should work ldapsearch -x -H ldap://:1389/ -b dc=example,dc=org cn=a1
# Search for a user in dept B. # This exposes the supposedly non-detectable department B... ldapsearch -x -H ldap://:1389/ -b dc=example,dc=org cn=b1