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

Problems resolving multi-valued attributes with acl directives (ITS#3269)



Full_Name: William Edward Woody
Version: 2.2.8
OS: Win32
URL: ftp://ftp.openldap.org/incoming/
Submission from: (NULL) (198.6.50.155)


I encountered a problem with entries with multi-valued attributes, where not all
of the values were being returned in v2.2.8 of OpenLDAP slapd.

When an entry is marked as having read access only to a group, reading the
objectClass attribute with 'cn=root' (full root privileges) will return all
objectClass attribute values. However, if one logs in using the access
privileges of a member in the group, only the first objectClass attribute is
returned.

I narrowed down the problem to the state caching used while resolving ACL
instructions. In servers/slapd/acl.c, the AccessControlState object appears to
store the last resolved ACL item in the slapd.conf block access control list,
and stores nothing with respect to the openLDAPaci attribute. Now we've defined
our access control block to rely on openLDAPaci:

access to *
	by anonymous auth
	by aci write
	by * none

When the founded entry is sent in slap_send_search_entry()
(servers\slapd\result.c), the first pass through the loop to figure out which
attribute/value pairs may be sent succeeds. However, successive passes through
the loop fail.

Now if I were actually smart I'd figure out a way to properly cache the
openLDAPaci ACL instructions in the state record in such a way as to make this
properly work.

I'm not that smart.

The workaround I've devised was to move the call to access_allowed call outside
of the loop creating the attribute return block if SLAPD_ACI_ENABLED is defined,
thus:


(from Perforce's diff tool, context = 10 lines)

@@ -936,38 +936,74 @@
   #endif
   
   				if ( op->o_res_ber == NULL ) ber_free_buf( ber );
   				send_ldap_error( op, rs, LDAP_OTHER, "encoding description error");
   				goto error_return;
   			}
   			finish = 1;
   
   		} else {
   			int first = 1;
-> 
-> 			/*
-> 			 *	Bug fix WEW 5 Aug 04:
-> 			 *
-> 			 *		It appears for efficiency sake we maintain a state
-> 			 *  between calls in order to do ACl control at the attr=value
-> 			 *  level. However, this is screwed up for on-the-fly ACL control.
-> 			 *  So to preserve efficiency if we're using on the fly ACLs, we
-> 			 *  revert to attr level filtering rather than to value level filtering
-> 			 *  in order to skip the filtering bug.
-> 			 *
-> 			 *		What really should be happening is enough intelligence
-> 			 *	at the state level to figure out how to maintain state but
-> 			 *	allow value-level filtering instead.
-> 			 */
-> 
-> #ifdef SLAPD_ACI_ENABLED
-> 				if ( ! access_allowed( op, rs->sr_entry, desc, NULL, ACL_READ, &acl_state
) )
-> 				{
-> #ifdef NEW_LOGGING
-> 					LDAP_LOG( ACL, INFO, 
-> 						"send_search_entry: conn %lu "
-> 						"access to attribute %s not allowed\n",
-> 						op->o_connid, desc->ad_cname.bv_val );
-> #else
-> 					Debug( LDAP_DEBUG_ACL,
-> 						"acl: access to attribute %s not allowed\n",
-> 						desc->ad_cname.bv_val, 0, 0 );
-> #endif
-> 
-> 					continue;
-> 				}
-> #endif
-> 
   			for ( i = 0; a->a_nvals[i].bv_val != NULL; i++ ) {
-> #ifndef SLAPD_ACI_ENABLED
   				if ( ! access_allowed( op, rs->sr_entry,
   					desc, &a->a_nvals[i], ACL_READ, &acl_state ) )
   				{
   #ifdef NEW_LOGGING
   					LDAP_LOG( ACL, INFO, 
   						"send_search_entry: conn %lu "
   						"access to attribute %s, value %d not allowed\n",
   						op->o_connid, desc->ad_cname.bv_val, i );
   #else
   					Debug( LDAP_DEBUG_ACL,
   						"acl: access to attribute %s, "
   						"value %d not allowed\n",
   						desc->ad_cname.bv_val, i, 0 );
   #endif
   
   					continue;
   				}
-> #endif
   
   				if ( op->o_vrFilter && e_flags[j][i] == 0 ){
   					continue;
   				}
   
   				if ( first ) {
   					first = 0;
   					finish = 1;
   					if (( rc = ber_printf( ber, "{O[" /*]}*/ , &desc->ad_cname )) == -1 ) {
   #ifdef NEW_LOGGING