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

Problem with break keyword in ACLs



Hi all,

I've got a problem with the 'break' keyword in ACLs in
OpenLDAP 2.1.23. I have reduced the problem to the
following ACLs:

access to *
    by * =csr break

access to dn.children=ou=admin,dc=science,dc=uva,dc=nl
    by * none stop



The following search returns nothing:

% ldapsearch -h server -x -b ou=people,dc=science,dc=uva,dc=nl '(uid=robbert)' givenName

version: 2

#
# filter: (uid=robbert)
# requesting: givenName
#

# search result
search: 2
result: 0 Success

# numResponses: 1



The corresponding slapd logging output (-d 128):

Backend ACL: access to *
        by * =rsc break

Backend ACL: access to dn.children=ou=admin,dc=science,dc=uva,dc=nl
        by * none(=n)

slapd starting
=> access_allowed: search access to "uid=robbert,ou=people,dc=science,dc=uva,dc=nl" "uid" requested
=> acl_get: [1] check attr uid
<= acl_get: [1] acl uid=robbert,ou=people,dc=science,dc=uva,dc=nl attr: uid
=> acl_mask: access to entry "uid=robbert,ou=people,dc=science,dc=uva,dc=nl", attr "uid" requested
=> acl_mask: to value by "", (=n)
<= check a_dn_pat: *
<= acl_mask: [1] applying =rsc (break)
<= acl_mask: [1] mask: =rsc
=> dn: [2] ou=admin,dc=science,dc=uva,dc=nl
<= acl_get: done.
=> access_allowed: no more rules



So I change the ACLs (to something I don't want) by replacing
'break' by 'stop' in the first ACL:

access to *
    by * =csr stop

access to dn.children=ou=admin,dc=science,dc=uva,dc=nl
    by * none stop



The same search now returns one record:

version: 2

#
# filter: (uid=robbert)
# requesting: givenName
#

# robbert, people, science, uva, nl
dn: uid=robbert,ou=people,dc=science,dc=uva,dc=nl
givenName: Robbert

# search result
search: 2
result: 0 Success

# numResponses: 2
# numEntries: 1



Relevant part of the corresponding slapd logging output:

Backend ACL: access to *
        by * =rsc

Backend ACL: access to dn.children=ou=admin,dc=science,dc=uva,dc=nl
        by * none(=n)

slapd starting
=> access_allowed: search access to "uid=robbert,ou=people,dc=science,dc=uva,dc=nl" "uid" requested
=> acl_get: [1] check attr uid
<= acl_get: [1] acl uid=robbert,ou=people,dc=science,dc=uva,dc=nl attr: uid
=> acl_mask: access to entry "uid=robbert,ou=people,dc=science,dc=uva,dc=nl", attr "uid" requested
=> acl_mask: to value by "", (=n)
<= check a_dn_pat: *
<= acl_mask: [1] applying =rsc (stop)
<= acl_mask: [1] mask: =rsc
=> access_allowed: search access granted by =rsc



Going back to the first set of ACLs:

access to *
    by * =csr break

access to dn.children=ou=admin,dc=science,dc=uva,dc=nl
    by * none stop

My interpretation of the 'break' keyword is that it amends the
access bits (=csr in this case) but allows other ACLs to apply
as well. In this case, the access bits set by the first ACL are ignored.
The second ACL doesn't apply in this search.

Looking at the slapd code, I think this happens in servers/slapd/acl.c
at line 339:

        } else if ( control == ACL_BREAK ) {
#ifdef NEW_LOGGING
                LDAP_LOG( ACL, DETAIL1,
                        "access_allowed: conn %lu        no more rules\n", conn->c_connid, 0,0 );
#else
                Debug( LDAP_DEBUG_ACL,
                        "=> access_allowed: no more rules\n", 0, 0, 0);
#endif

                goto done;
        }

This code causes a jump to 'done:' if the last ACL processed returns
ACL_BREAK. The effect is that the line (364)

        ret = ACL_GRANT(mask, access);

is skipped and thus the first ACL is not effective.

According to diff there are no differences between acl.c in OpenLDAP
version 2.1.23 and version 2.1.25.

Is break meant to behave this way?

Kind regards,
Wout