Gavin Henry wrote:
is there a possibility to create an acl statement that grants access to any (unknown) value of an attribute but denys access to all values of the same attribute?
Can you explain that again?
BTW: Your answer didn't find its way into the openldap-technical archive: http://www.openldap.org/lists/openldap-technical/201208/threads.html
Nevertheless, please let me try to explain using a short (but complete) example:
Sample slapd.conf: ================== include /openldap/schema/core.schema pidfile /openldap/schema/slapd.pid argsfile /openldap/schema/slapd.args
access to * by self write by users read by anonymous auth
database mdb suffix "o=test" rootdn "cn=Manager,o=test" rootpw secret directory /openldap/var/openldap-data/test index objectClass eq
access to dn.one="ou=persons,o=test" attrs=description by users write by * none
Sample val.ldif: ================ dn: o=test objectClass: organization objectClass: top o: test
dn: ou=persons,o=test objectClass: organizationalUnit objectClass: top ou: persons
dn: cn=PersonA,ou=persons,o=test objectClass: person objectClass: top cn: PersonA sn: PersonA userPassword:: UGVyc29uQQ==
Sample modifications.ldif: ========================== #mod 1 (should succeed) dn: cn=PersonA,ou=persons,o=test changetype: modify add: description description: Description of A
#mod 2 (should succeed) dn: cn=PersonA,ou=persons,o=test changetype: modify add: description description: Another description of A description: Just another description of A
#mod 3 (should succeed) dn: cn=PersonA,ou=persons,o=test changetype: modify delete: description description: Another description of A description: Just another description of A
#mod 4 (should fail) dn: cn=PersonA,ou=persons,o=test changetype: modify delete: description
slapd startup: (version: git master) ==================================== deepee@test:~$ /openldap/libexec/slapd -f slapd.conf.acl -u openldap -g openldap -d 128 -h "ldap://0.0.0.0:1389/ ldapi://%2Ftmp%2Fldapi_acl/" 50258437 @(#) $OpenLDAP: slapd 2.X (Aug 10 2012 20:44:06) $ deepee@test:/.../slapd Backend ACL: access to * by self write by users read by anonymous auth
Backend ACL: access to dn.one="ou=persons,o=test" attrs=description by users write by * none
Backend ACL: access to * by * none
50258437 config_back_db_open: line 0: warning: cannot assess the validity of the ACL scope within backend naming context 50258437 mdb_monitor_db_open: monitoring disabled; configure monitor database to enable 50258437 slapd starting
ldapmodify: =========== deepee@test:~$ cat /tmp/val.ldif | /openldap/bin/ldapmodify -c -x -H "ldap://localhost:1389" -D "cn=PersonA,ou=persons,o=test" -w PersonA modifying entry "cn=PersonA,ou=persons,o=test"
modifying entry "cn=PersonA,ou=persons,o=test"
modifying entry "cn=PersonA,ou=persons,o=test"
modifying entry "cn=PersonA,ou=persons,o=test"
slapd.log (level 128): ====================== 50258ca0 => access_allowed: result not in cache (userPassword) 50258ca0 => access_allowed: auth access to "cn=PersonA,ou=persons,o=test" "userPassword" requested 50258ca0 => dn: [1] ou=persons,o=test 50258ca0 => acl_get: [1] matched 50258ca0 => acl_get: [2] attr userPassword 50258ca0 => acl_mask: access to entry "cn=PersonA,ou=persons,o=test", attr "userPassword" requested 50258ca0 => acl_mask: to value by "", (=0) 50258ca0 <= check a_dn_pat: self 50258ca0 <= check a_dn_pat: users 50258ca0 <= check a_dn_pat: anonymous 50258ca0 <= acl_mask: [3] applying auth(=xd) (stop) 50258ca0 <= acl_mask: [3] mask: auth(=xd) 50258ca0 => slap_access_allowed: auth access granted by auth(=xd) 50258ca0 => access_allowed: auth access granted by auth(=xd) 50258ca0 => access_allowed: result not in cache (description) 50258ca0 => access_allowed: add access to "cn=PersonA,ou=persons,o=test" "description" requested 50258ca0 => dn: [1] ou=persons,o=test 50258ca0 => acl_get: [1] matched 50258ca0 => acl_get: [1] attr description 50258ca0 => acl_mask: access to entry "cn=PersonA,ou=persons,o=test", attr "description" requested 50258ca0 => acl_mask: to value by "cn=persona,ou=persons,o=test", (=0) 50258ca0 <= check a_dn_pat: users 50258ca0 <= acl_mask: [1] applying write(=wrscxd) (stop) 50258ca0 <= acl_mask: [1] mask: write(=wrscxd) 50258ca0 => slap_access_allowed: add access granted by write(=wrscxd) 50258ca0 => access_allowed: add access granted by write(=wrscxd) 50258ca0 acl: internal mod entryCSN: modify access granted 50258ca0 acl: internal mod modifiersName: modify access granted 50258ca0 acl: internal mod modifyTimestamp: modify access granted 50258ca0 => access_allowed: result not in cache (description) 50258ca0 => access_allowed: add access to "cn=PersonA,ou=persons,o=test" "description" requested 50258ca0 => dn: [1] ou=persons,o=test 50258ca0 => acl_get: [1] matched 50258ca0 => acl_get: [1] attr description 50258ca0 => acl_mask: access to entry "cn=PersonA,ou=persons,o=test", attr "description" requested 50258ca0 => acl_mask: to value by "cn=persona,ou=persons,o=test", (=0) 50258ca0 <= check a_dn_pat: users 50258ca0 <= acl_mask: [1] applying write(=wrscxd) (stop) 50258ca0 <= acl_mask: [1] mask: write(=wrscxd) 50258ca0 => slap_access_allowed: add access granted by write(=wrscxd) 50258ca0 => access_allowed: add access granted by write(=wrscxd) 50258ca0 => access_allowed: result was in cache (description) 50258ca0 acl: internal mod entryCSN: modify access granted 50258ca0 acl: internal mod modifiersName: modify access granted 50258ca0 acl: internal mod modifyTimestamp: modify access granted 50258ca0 => access_allowed: result not in cache (description) 50258ca0 => access_allowed: delete access to "cn=PersonA,ou=persons,o=test" "description" requested 50258ca0 => dn: [1] ou=persons,o=test 50258ca0 => acl_get: [1] matched 50258ca0 => acl_get: [1] attr description 50258ca0 => acl_mask: access to entry "cn=PersonA,ou=persons,o=test", attr "description" requested 50258ca0 => acl_mask: to value by "cn=persona,ou=persons,o=test", (=0) 50258ca0 <= check a_dn_pat: users 50258ca0 <= acl_mask: [1] applying write(=wrscxd) (stop) 50258ca0 <= acl_mask: [1] mask: write(=wrscxd) 50258ca0 => slap_access_allowed: delete access granted by write(=wrscxd) 50258ca0 => access_allowed: delete access granted by write(=wrscxd) 50258ca0 => access_allowed: result was in cache (description) 50258ca0 acl: internal mod entryCSN: modify access granted 50258ca0 acl: internal mod modifiersName: modify access granted 50258ca0 acl: internal mod modifyTimestamp: modify access granted 50258ca0 => access_allowed: result not in cache (description) 50258ca0 => access_allowed: delete access to "cn=PersonA,ou=persons,o=test" "description" requested 50258ca0 => dn: [1] ou=persons,o=test 50258ca0 => acl_get: [1] matched 50258ca0 => acl_get: [1] attr description 50258ca0 => acl_mask: access to entry "cn=PersonA,ou=persons,o=test", attr "description" requested 50258ca0 => acl_mask: to all values by "cn=persona,ou=persons,o=test", (=0) 50258ca0 <= check a_dn_pat: users 50258ca0 <= acl_mask: [1] applying write(=wrscxd) (stop) 50258ca0 <= acl_mask: [1] mask: write(=wrscxd) 50258ca0 => slap_access_allowed: delete access granted by write(=wrscxd) 50258ca0 => access_allowed: delete access granted by write(=wrscxd) 50258ca0 acl: internal mod entryCSN: modify access granted 50258ca0 acl: internal mod modifiersName: modify access granted 50258ca0 acl: internal mod modifyTimestamp: modify access granted
So far so good, all four modification operations succeeded. That's slapd's known default behavior and completely correct in regard to the above defined acl.
My intention is to let the first three operations (to value(s)) succeed and the last operation (to all values) fail by "Insufficient access (50)".
After studying the documentation, doing some (unstructured, trial and error) testing with various combinations of acl statements, I finally had a closer look into slapd's source: Am I right, that slapd's acl engine currently does not offer a chance to differentiate between these two types of modification?