]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/acl.c
ITS#5339
[openldap] / servers / slapd / acl.c
index 0044e6849ecfd40121b5dd8189f48aecf5b9ba27..48f93c81966e13ef2a29442da677e0b231b100d3 100644 (file)
@@ -2,7 +2,7 @@
 /* $OpenLDAP$ */
 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *
- * Copyright 1998-2006 The OpenLDAP Foundation.
+ * Copyright 1998-2008 The OpenLDAP Foundation.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -40,6 +40,9 @@
 #define ACL_BUF_SIZE   1024    /* use most appropriate size */
 
 static const struct berval     acl_bv_ip_eq = BER_BVC( "IP=" );
+#ifdef LDAP_PF_INET6
+static const struct berval     acl_bv_ipv6_eq = BER_BVC( "IP=[" );
+#endif /* LDAP_PF_INET6 */
 #ifdef LDAP_PF_LOCAL
 static const struct berval     acl_bv_path_eq = BER_BVC("PATH=");
 #endif /* LDAP_PF_LOCAL */
@@ -134,7 +137,6 @@ slap_access_allowed(
        slap_access_t                   access_level;
        const char                      *attr;
        regmatch_t                      matches[MAXREMATCHES];
-       int                             st_same_attr = 0;
 
        assert( op != NULL );
        assert( e != NULL );
@@ -198,24 +200,17 @@ slap_access_allowed(
        ret = 0;
        control = ACL_BREAK;
 
-       if ( st_same_attr ) {
-               assert( state->as_vd_acl != NULL );
-
+       if ( state && state->as_vd_ad == desc ) {
                a = state->as_vd_acl;
                count = state->as_vd_acl_count;
-               if ( !ACL_IS_INVALID( state->as_vd_acl_mask ) ) {
-                       mask = state->as_vd_acl_mask;
-                       AC_MEMCPY( matches, state->as_vd_acl_matches, sizeof(matches) );
-                       goto vd_access;
-               }
 
        } else {
                if ( state ) state->as_vi_acl = NULL;
                a = NULL;
-               ACL_PRIV_ASSIGN( mask, *maskp );
                count = 0;
-               memset( matches, '\0', sizeof( matches ) );
        }
+       ACL_PRIV_ASSIGN( mask, *maskp );
+       memset( matches, '\0', sizeof( matches ) );
 
        while ( ( a = slap_acl_get( a, &count, op, e, desc, val,
                MAXREMATCHES, matches, state ) ) != NULL )
@@ -239,18 +234,17 @@ slap_access_allowed(
                                ( state->as_recorded & ACL_STATE_RECORDED_NV ) )
                        {
                                Debug( LDAP_DEBUG_ACL,
-                                       "=> slap_access_allowed: result from state (%s)\n",
+                                       "=> slap_access_allowed: result was in cache (%s)\n",
                                        attr, 0, 0 );
                                ret = state->as_result;
                                goto done;
                        } else {
                                Debug( LDAP_DEBUG_ACL,
-                                       "=> slap_access_allowed: no res from state (%s)\n",
+                                       "=> slap_access_allowed: result not in cache (%s)\n",
                                        attr, 0, 0 );
                        }
                }
 
-vd_access:
                control = slap_acl_mask( a, &mask, op,
                        e, desc, val, MAXREMATCHES, matches, count, state );
 
@@ -310,7 +304,7 @@ fe_access_allowed(
        be_orig = op->o_bd;
 
        if ( op->o_bd == NULL ) {
-               op->o_bd = select_backend( &op->o_req_ndn, 0, 0 );
+               op->o_bd = select_backend( &op->o_req_ndn, 0 );
                if ( op->o_bd == NULL )
                        op->o_bd = frontendDB;
        }
@@ -340,7 +334,6 @@ access_allowed_mask(
        slap_mask_t                     mask;
        slap_access_t                   access_level;
        const char                      *attr;
-       int                             st_same_attr = 0;
        static AccessControlState       state_init = ACL_STATE_INIT;
 
        assert( e != NULL );
@@ -358,12 +351,15 @@ access_allowed_mask(
        assert( attr != NULL );
 
        if ( op ) {
-               if ( op->o_is_auth_check &&
+               if ( op->o_acl_priv != ACL_NONE ) {
+                       access = op->o_acl_priv;
+
+               } else if ( op->o_is_auth_check &&
                        ( access_level == ACL_SEARCH || access_level == ACL_READ ) )
                {
                        access = ACL_AUTH;
 
-               } else if ( get_manageDIT( op ) && access_level == ACL_WRITE &&
+               } else if ( get_relax( op ) && access_level == ACL_WRITE &&
                        desc == slap_schema.si_ad_entry )
                {
                        access = ACL_MANAGE;
@@ -377,17 +373,10 @@ access_allowed_mask(
                        {
                                return state->as_result;
 
-                       } else if ( ( state->as_recorded & ACL_STATE_RECORDED_VD ) &&
-                               val != NULL && state->as_vd_acl == NULL )
-                       {
-                               return state->as_result;
                        }
-                       st_same_attr = 1;
                } else {
                        *state = state_init;
                }
-
-               state->as_vd_ad = desc;
        }
 
        Debug( LDAP_DEBUG_ACL,
@@ -403,14 +392,12 @@ access_allowed_mask(
                op->o_bd = LDAP_STAILQ_FIRST( &backendDB );
                be_null = 1;
 
-#ifdef LDAP_DEVEL
-               /*
-                * FIXME: experimental; use first backend rules
-                * iff there is no global_acl (ITS#3100) */
+               /* FIXME: experimental; use first backend rules
+                * iff there is no global_acl (ITS#3100)
+                */
                if ( frontendDB->be_acl != NULL ) {
                        op->o_bd = frontendDB;
                }
-#endif /* LDAP_DEVEL */
        }
        assert( op->o_bd != NULL );
 
@@ -455,6 +442,7 @@ done:
                        state->as_result = ret;
                }
                state->as_recorded |= ACL_STATE_RECORDED;
+               state->as_vd_ad = desc;
        }
        if ( be_null ) op->o_bd = NULL;
        if ( maskp ) ACL_PRIV_ASSIGN( *maskp, mask );
@@ -509,7 +497,7 @@ slap_acl_get(
 
        dnlen = e->e_nname.bv_len;
 
-       for ( ; a != NULL; a = a->acl_next ) {
+       for ( ; a != NULL; prev = a, a = a->acl_next ) {
                (*count) ++;
 
                if ( a->acl_dn_pat.bv_len || ( a->acl_dn_style != ACL_STYLE_REGEX )) {
@@ -580,11 +568,8 @@ slap_acl_get(
 
                        if( state && !( state->as_recorded & ACL_STATE_RECORDED_VD )) {
                                state->as_recorded |= ACL_STATE_RECORDED_VD;
-                               state->as_vd_acl = a;
-                               state->as_vd_acl_count = *count;
-                               state->as_vd_access = a->acl_access;
-                               state->as_vd_access_count = 1;
-                               ACL_INVALIDATE( state->as_vd_acl_mask );
+                               state->as_vd_acl = prev;
+                               state->as_vd_acl_count = *count - 1;
                        }
 
                        if ( a->acl_attrval_style == ACL_STYLE_REGEX ) {
@@ -667,6 +652,17 @@ slap_acl_get(
        return( NULL );
 }
 
+/*
+ * Record value-dependent access control state
+ */
+#define ACL_RECORD_VALUE_STATE do { \
+               if( state && !( state->as_recorded & ACL_STATE_RECORDED_VD )) { \
+                       state->as_recorded |= ACL_STATE_RECORDED_VD; \
+                       state->as_vd_acl = a; \
+                       state->as_vd_acl_count = count; \
+               } \
+       } while( 0 )
+
 static int
 acl_mask_dn(
        Operation               *op,
@@ -676,7 +672,7 @@ acl_mask_dn(
        AccessControl           *a,
        int                     nmatch,
        regmatch_t              *matches,
-       slap_dn_access          *b,
+       slap_dn_access          *bdn,
        struct berval           *opndn )
 {
        /*
@@ -688,40 +684,20 @@ acl_mask_dn(
         * NOTE: styles "anonymous", "users" and "self" 
         * have been moved to enum slap_style_t, whose 
         * value is set in a_dn_style; however, the string
-        * is maintaned in a_dn_pat.
+        * is maintained in a_dn_pat.
         */
-       if ( b->a_style == ACL_STYLE_ANONYMOUS ) {
+
+       if ( bdn->a_style == ACL_STYLE_ANONYMOUS ) {
                if ( !BER_BVISEMPTY( opndn ) ) {
                        return 1;
                }
 
-       } else if ( b->a_style == ACL_STYLE_USERS ) {
+       } else if ( bdn->a_style == ACL_STYLE_USERS ) {
                if ( BER_BVISEMPTY( opndn ) ) {
                        return 1;
                }
 
-               if ( b->a_self ) {
-                       const char *dummy;
-                       int rc, match = 0;
-
-                       /* must have DN syntax */
-                       if ( desc->ad_type->sat_syntax != slap_schema.si_syn_distinguishedName ) return 1;
-
-                       /* check if the target is an attribute. */
-                       if ( val == NULL ) return 1;
-
-                       /* target is attribute, check if the attribute value
-                        * is the op dn.
-                        */
-                       rc = value_match( &match, desc,
-                               desc->ad_type->sat_equality, 0,
-                               val, opndn, &dummy );
-                       /* on match error or no match, fail the ACL clause */
-                       if ( rc != LDAP_SUCCESS || match != 0 )
-                               return 1;
-               }
-
-       } else if ( b->a_style == ACL_STYLE_SELF ) {
+       } else if ( bdn->a_style == ACL_STYLE_SELF ) {
                struct berval   ndn, selfndn;
                int             level;
 
@@ -729,7 +705,7 @@ acl_mask_dn(
                        return 1;
                }
 
-               level = b->a_self_level;
+               level = bdn->a_self_level;
                if ( level < 0 ) {
                        selfndn = *opndn;
                        ndn = e->e_nname;
@@ -752,8 +728,8 @@ acl_mask_dn(
                        return 1;
                }
 
-       } else if ( b->a_style == ACL_STYLE_REGEX ) {
-               if ( !ber_bvccmp( &b->a_pat, '*' ) ) {
+       } else if ( bdn->a_style == ACL_STYLE_REGEX ) {
+               if ( !ber_bvccmp( &bdn->a_pat, '*' ) ) {
                        int             tmp_nmatch;
                        regmatch_t      tmp_matches[2],
                                        *tmp_matchesp = tmp_matches;
@@ -795,7 +771,7 @@ acl_mask_dn(
                                return 1;
                        }
 
-                       if ( !regex_matches( &b->a_pat, opndn->bv_val,
+                       if ( !regex_matches( &bdn->a_pat, opndn->bv_val,
                                e->e_ndn, tmp_nmatch, tmp_matchesp ) )
                        {
                                return 1;
@@ -810,7 +786,7 @@ acl_mask_dn(
                if ( e->e_dn == NULL )
                        return 1;
 
-               if ( b->a_expand ) {
+               if ( bdn->a_expand ) {
                        struct berval   bv;
                        char            buf[ACL_BUF_SIZE];
                        
@@ -858,7 +834,7 @@ acl_mask_dn(
                                return 1;
                        }
 
-                       if ( acl_string_expand( &bv, &b->a_pat, 
+                       if ( acl_string_expand( &bv, &bdn->a_pat, 
                                        e->e_nname.bv_val,
                                        tmp_nmatch, tmp_matchesp ) )
                        {
@@ -874,7 +850,7 @@ acl_mask_dn(
                        }
 
                } else {
-                       pat = b->a_pat;
+                       pat = bdn->a_pat;
                }
 
                patlen = pat.bv_len;
@@ -884,13 +860,13 @@ acl_mask_dn(
 
                }
 
-               if ( b->a_style == ACL_STYLE_BASE ) {
+               if ( bdn->a_style == ACL_STYLE_BASE ) {
                        /* base dn -- entire object DN must match */
                        if ( odnlen != patlen ) {
                                goto dn_match_cleanup;
                        }
 
-               } else if ( b->a_style == ACL_STYLE_ONE ) {
+               } else if ( bdn->a_style == ACL_STYLE_ONE ) {
                        ber_len_t       rdnlen = 0;
 
                        if ( odnlen <= patlen ) {
@@ -906,12 +882,12 @@ acl_mask_dn(
                                goto dn_match_cleanup;
                        }
 
-               } else if ( b->a_style == ACL_STYLE_SUBTREE ) {
+               } else if ( bdn->a_style == ACL_STYLE_SUBTREE ) {
                        if ( odnlen > patlen && !DN_SEPARATOR( opndn->bv_val[odnlen - patlen - 1] ) ) {
                                goto dn_match_cleanup;
                        }
 
-               } else if ( b->a_style == ACL_STYLE_CHILDREN ) {
+               } else if ( bdn->a_style == ACL_STYLE_CHILDREN ) {
                        if ( odnlen <= patlen ) {
                                goto dn_match_cleanup;
                        }
@@ -920,8 +896,8 @@ acl_mask_dn(
                                goto dn_match_cleanup;
                        }
 
-               } else if ( b->a_style == ACL_STYLE_LEVEL ) {
-                       int             level = b->a_level;
+               } else if ( bdn->a_style == ACL_STYLE_LEVEL ) {
+                       int             level = bdn->a_level;
                        struct berval   ndn;
 
                        if ( odnlen <= patlen ) {
@@ -952,7 +928,7 @@ acl_mask_dn(
                got_match = !strcmp( pat.bv_val, &opndn->bv_val[ odnlen - patlen ] );
 
 dn_match_cleanup:;
-               if ( pat.bv_val != b->a_pat.bv_val ) {
+               if ( pat.bv_val != bdn->a_pat.bv_val ) {
                        slap_sl_free( pat.bv_val, op->o_tmpmemctx );
                }
 
@@ -964,21 +940,6 @@ dn_match_cleanup:;
        return 0;
 }
 
-/*
- * Record value-dependent access control state
- */
-#define ACL_RECORD_VALUE_STATE do { \
-               if( state && !( state->as_recorded & ACL_STATE_RECORDED_VD )) { \
-                       state->as_recorded |= ACL_STATE_RECORDED_VD; \
-                       state->as_vd_acl = a; \
-                       AC_MEMCPY( state->as_vd_acl_matches, matches, \
-                               sizeof( state->as_vd_acl_matches )) ; \
-                       state->as_vd_acl_count = count; \
-                       state->as_vd_access = b; \
-                       state->as_vd_access_count = i; \
-               } \
-       } while( 0 )
-
 static int
 acl_mask_dnattr(
        Operation               *op,
@@ -1013,11 +974,10 @@ acl_mask_dnattr(
                at != NULL;
                at = attrs_find( at->a_next, bdn->a_at ) )
        {
-               if ( value_find_ex( bdn->a_at,
+               if ( attr_valfind( at,
                        SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
                                SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
-                       at->a_nvals,
-                       &bv, op->o_tmpmemctx ) == 0 )
+                       &bv, NULL, op->o_tmpmemctx ) == 0 )
                {
                        /* found it */
                        match = 1;
@@ -1050,7 +1010,7 @@ acl_mask_dnattr(
                        return 1;
 
                ACL_RECORD_VALUE_STATE;
-               
+
                /* this is a self clause, check if the target is an
                 * attribute.
                 */
@@ -1122,16 +1082,8 @@ slap_acl_mask(
                accessmask2str( *mask, accessmaskbuf, 1 ) );
 
 
-       if( state && ( state->as_recorded & ACL_STATE_RECORDED_VD )
-               && state->as_vd_acl == a )
-       {
-               b = state->as_vd_access;
-               i = state->as_vd_access_count;
-
-       } else {
-               b = a->acl_access;
-               i = 1;
-       }
+       b = a->acl_access;
+       i = 1;
 
        for ( ; b != NULL; b = b->a_next, i++ ) {
                slap_mask_t oldmask, modmask;
@@ -1151,7 +1103,7 @@ slap_acl_mask(
                         * NOTE: styles "anonymous", "users" and "self" 
                         * have been moved to enum slap_style_t, whose 
                         * value is set in a_dn_style; however, the string
-                        * is maintaned in a_dn_pat.
+                        * is maintained in a_dn_pat.
                         */
 
                        if ( acl_mask_dn( op, e, desc, val, a, nmatch, matches,
@@ -1175,7 +1127,7 @@ slap_acl_mask(
                         * NOTE: styles "anonymous", "users" and "self" 
                         * have been moved to enum slap_style_t, whose 
                         * value is set in a_dn_style; however, the string
-                        * is maintaned in a_dn_pat.
+                        * is maintained in a_dn_pat.
                         */
 
                        if ( op->o_conn && !BER_BVISNULL( &op->o_conn->c_ndn ) )
@@ -1328,7 +1280,7 @@ slap_acl_mask(
                                        /* extract IP and try exact match */
                                        } else if ( b->a_peername_style == ACL_STYLE_IP ) {
                                                char            *port;
-                                               char            buf[] = "255.255.255.255";
+                                               char            buf[STRLENOF("255.255.255.255") + 1];
                                                struct berval   ip;
                                                unsigned long   addr;
                                                int             port_number = -1;
@@ -1369,6 +1321,50 @@ slap_acl_mask(
                                                if ( (addr & b->a_peername_mask) != b->a_peername_addr )
                                                        continue;
 
+#ifdef LDAP_PF_INET6
+                                       /* extract IPv6 and try exact match */
+                                       } else if ( b->a_peername_style == ACL_STYLE_IPV6 ) {
+                                               char            *port;
+                                               char            buf[STRLENOF("FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF") + 1];
+                                               struct berval   ip;
+                                               struct in6_addr addr;
+                                               int             port_number = -1;
+                                               
+                                               if ( strncasecmp( op->o_conn->c_peer_name.bv_val, 
+                                                                       acl_bv_ipv6_eq.bv_val,
+                                                                       acl_bv_ipv6_eq.bv_len ) != 0 ) 
+                                                       continue;
+
+                                               ip.bv_val = op->o_conn->c_peer_name.bv_val + acl_bv_ipv6_eq.bv_len;
+                                               ip.bv_len = op->o_conn->c_peer_name.bv_len - acl_bv_ipv6_eq.bv_len;
+
+                                               port = strrchr( ip.bv_val, ']' );
+                                               if ( port ) {
+                                                       ip.bv_len = port - ip.bv_val;
+                                                       ++port;
+                                                       if ( port[0] == ':' && lutil_atoi( &port_number, ++port ) != 0 )
+                                                               continue;
+                                               }
+                                               
+                                               /* the port check can be anticipated here */
+                                               if ( b->a_peername_port != -1 && port_number != b->a_peername_port )
+                                                       continue;
+                                               
+                                               /* address longer than expected? */
+                                               if ( ip.bv_len >= sizeof(buf) )
+                                                       continue;
+
+                                               AC_MEMCPY( buf, ip.bv_val, ip.bv_len );
+                                               buf[ ip.bv_len ] = '\0';
+
+                                               if ( inet_pton( AF_INET6, buf, &addr ) != 1 )
+                                                       continue;
+
+                                               /* check mask */
+                                               if ( !slap_addr6_mask( &addr, &b->a_peername_mask6, &b->a_peername_addr6 ) )
+                                                       continue;
+#endif /* LDAP_PF_INET6 */
+
 #ifdef LDAP_PF_LOCAL
                                        /* extract path and try exact match */
                                        } else if ( b->a_peername_style == ACL_STYLE_PATH ) {
@@ -1661,6 +1657,36 @@ slap_acl_mask(
                        }
                }
 
+               /* check for the "self" modifier in the <access> field */
+               if ( b->a_dn.a_self ) {
+                       const char *dummy;
+                       int rc, match = 0;
+
+                       ACL_RECORD_VALUE_STATE;
+
+                       /* must have DN syntax */
+                       if ( desc->ad_type->sat_syntax != slap_schema.si_syn_distinguishedName &&
+                               !is_at_syntax( desc->ad_type, SLAPD_NAMEUID_SYNTAX )) continue;
+
+                       /* check if the target is an attribute. */
+                       if ( val == NULL ) continue;
+
+                       /* a DN must be present */
+                       if ( BER_BVISEMPTY( &op->o_ndn ) ) {
+                               continue;
+                       }
+
+                       /* target is attribute, check if the attribute value
+                        * is the op dn.
+                        */
+                       rc = value_match( &match, desc,
+                               desc->ad_type->sat_equality, 0,
+                               val, &op->o_ndn, &dummy );
+                       /* on match error or no match, fail the ACL clause */
+                       if ( rc != LDAP_SUCCESS || match != 0 )
+                               continue;
+               }
+
 #ifdef SLAP_DYNACL
                if ( b->a_dynacl ) {
                        slap_dynacl_t   *da;
@@ -1694,7 +1720,8 @@ slap_acl_mask(
                                Debug( LDAP_DEBUG_ACL, "    <= check a_dynacl: %s\n",
                                        da->da_name, 0, 0 );
 
-                               (void)( *da->da_mask )( da->da_private, op, e, desc, val, nmatch, matches, &grant, &deny );
+                               (void)da->da_mask( da->da_private, op, e, desc,
+                                       val, nmatch, matches, &grant, &deny );
 
                                tgrant |= grant;
                                tdeny |= deny;
@@ -2004,6 +2031,10 @@ acl_set_cb_gather( Operation *op, SlapReply *rs )
 
                for ( j = 0; !BER_BVISNULL( &rs->sr_attrs[ j ].an_name ); j++ ) {
                        AttributeDescription    *desc = rs->sr_attrs[ j ].an_desc;
+
+                       if ( desc == NULL ) {
+                               continue;
+                       }
                        
                        if ( desc == slap_schema.si_ad_entryDN ) {
                                bvalsp = bvals;
@@ -2015,17 +2046,12 @@ acl_set_cb_gather( Operation *op, SlapReply *rs )
 
                                a = attr_find( rs->sr_entry->e_attrs, desc );
                                if ( a != NULL ) {
-                                       int     i;
-
-                                       for ( i = 0; !BER_BVISNULL( &a->a_nvals[ i ] ); i++ )
-                                               ;
-
                                        bvalsp = a->a_nvals;
                                }
                        }
                }
 
-               if ( bvals ) {
+               if ( bvalsp ) {
                        p->bvals = slap_set_join( p->cookie, p->bvals,
                                        ( '|' | SLAP_SET_RREF ), bvalsp );
                }
@@ -2049,8 +2075,6 @@ acl_set_gather( SetCookie *cookie, struct berval *name, AttributeDescription *de
        int                     nattrs = 0;
        slap_callback           cb = { NULL, acl_set_cb_gather, NULL, NULL };
        acl_set_gather_t        p = { 0 };
-       const char              *text = NULL;
-       static struct berval    defaultFilter_bv = BER_BVC( "(objectClass=*)" );
 
        /* this routine needs to return the bervals instead of
         * plain strings, since syntax is not known.  It should
@@ -2062,6 +2086,10 @@ acl_set_gather( SetCookie *cookie, struct berval *name, AttributeDescription *de
 
        rc = ldap_url_parse( name->bv_val, &ludp );
        if ( rc != LDAP_URL_SUCCESS ) {
+               Debug( LDAP_DEBUG_TRACE,
+                       "%s acl_set_gather: unable to parse URL=\"%s\"\n",
+                       cp->asc_op->o_log_prefix, name->bv_val, 0 );
+
                rc = LDAP_PROTOCOL_ERROR;
                goto url_done;
        }
@@ -2070,6 +2098,10 @@ acl_set_gather( SetCookie *cookie, struct berval *name, AttributeDescription *de
        {
                /* host part must be empty */
                /* extensions parts must be empty */
+               Debug( LDAP_DEBUG_TRACE,
+                       "%s acl_set_gather: host/exts must be absent in URL=\"%s\"\n",
+                       cp->asc_op->o_log_prefix, name->bv_val, 0 );
+
                rc = LDAP_PROTOCOL_ERROR;
                goto url_done;
        }
@@ -2080,11 +2112,19 @@ acl_set_gather( SetCookie *cookie, struct berval *name, AttributeDescription *de
                        &op2.o_req_ndn, cp->asc_op->o_tmpmemctx );
        BER_BVZERO( &op2.o_req_dn );
        if ( rc != LDAP_SUCCESS ) {
+               Debug( LDAP_DEBUG_TRACE,
+                       "%s acl_set_gather: DN=\"%s\" normalize failed\n",
+                       cp->asc_op->o_log_prefix, op2.o_req_dn.bv_val, 0 );
+
                goto url_done;
        }
 
-       op2.o_bd = select_backend( &op2.o_req_ndn, 0, 1 );
+       op2.o_bd = select_backend( &op2.o_req_ndn, 1 );
        if ( ( op2.o_bd == NULL ) || ( op2.o_bd->be_search == NULL ) ) {
+               Debug( LDAP_DEBUG_TRACE,
+                       "%s acl_set_gather: no database could be selected for DN=\"%s\"\n",
+                       cp->asc_op->o_log_prefix, op2.o_req_ndn.bv_val, 0 );
+
                rc = LDAP_NO_SUCH_OBJECT;
                goto url_done;
        }
@@ -2093,35 +2133,46 @@ acl_set_gather( SetCookie *cookie, struct berval *name, AttributeDescription *de
        if ( ludp->lud_filter ) {
                ber_str2bv_x( ludp->lud_filter, 0, 0, &op2.ors_filterstr,
                                cp->asc_op->o_tmpmemctx );
+               op2.ors_filter = str2filter_x( cp->asc_op, op2.ors_filterstr.bv_val );
+               if ( op2.ors_filter == NULL ) {
+                       Debug( LDAP_DEBUG_TRACE,
+                               "%s acl_set_gather: unable to parse filter=\"%s\"\n",
+                               cp->asc_op->o_log_prefix, op2.ors_filterstr.bv_val, 0 );
+
+                       rc = LDAP_PROTOCOL_ERROR;
+                       goto url_done;
+               }
                
        } else {
-               op2.ors_filterstr = defaultFilter_bv;
+               op2.ors_filterstr = *slap_filterstr_objectClass_pres;
+               op2.ors_filter = (Filter *)slap_filter_objectClass_pres;
        }
 
-       op2.ors_filter = str2filter_x( cp->asc_op, op2.ors_filterstr.bv_val );
-       if ( op2.ors_filter == NULL ) {
-               rc = LDAP_PROTOCOL_ERROR;
-               goto url_done;
-       }
 
        /* Grab the scope */
        op2.ors_scope = ludp->lud_scope;
 
        /* Grap the attributes */
        if ( ludp->lud_attrs ) {
+               int i;
+
                for ( ; ludp->lud_attrs[ nattrs ]; nattrs++ )
                        ;
 
-               anlistp = slap_sl_malloc( sizeof( AttributeName ) * ( nattrs + 2 ),
+               anlistp = slap_sl_calloc( sizeof( AttributeName ), nattrs + 2,
                                cp->asc_op->o_tmpmemctx );
 
-               for ( ; ludp->lud_attrs[ nattrs ]; nattrs++ ) {
-                       ber_str2bv( ludp->lud_attrs[ nattrs ], 0, 0, &anlistp[ nattrs ].an_name );
-                       anlistp[ nattrs ].an_desc = NULL;
-                       rc = slap_bv2ad( &anlistp[ nattrs ].an_name,
-                                       &anlistp[ nattrs ].an_desc, &text );
-                       if ( rc != LDAP_SUCCESS ) {
-                               goto url_done;
+               for ( i = 0, nattrs = 0; ludp->lud_attrs[ i ]; i++ ) {
+                       struct berval           name;
+                       AttributeDescription    *desc = NULL;
+                       const char              *text = NULL;
+
+                       ber_str2bv( ludp->lud_attrs[ i ], 0, 0, &name );
+                       rc = slap_bv2ad( &name, &desc, &text );
+                       if ( rc == LDAP_SUCCESS ) {
+                               anlistp[ nattrs ].an_name = name;
+                               anlistp[ nattrs ].an_desc = desc;
+                               nattrs++;
                        }
                }
 
@@ -2158,7 +2209,7 @@ acl_set_gather( SetCookie *cookie, struct berval *name, AttributeDescription *de
        }
 
 url_done:;
-       if ( op2.ors_filter ) {
+       if ( op2.ors_filter && op2.ors_filter != slap_filter_objectClass_pres ) {
                filter_free_x( cp->asc_op, op2.ors_filter );
        }
        if ( !BER_BVISNULL( &op2.o_req_ndn ) ) {
@@ -2228,7 +2279,7 @@ acl_match_set (
        } else {
                struct berval           subjdn, ndn = BER_BVNULL;
                struct berval           setat;
-               BerVarray               bvals;
+               BerVarray               bvals = NULL;
                const char              *text;
                AttributeDescription    *desc = NULL;