const char                      *attr;
        int                             st_same_attr = 0;
        static AccessControlState       state_init = ACL_STATE_INIT;
+       BackendDB                       *be_orig;
 
        assert( e != NULL );
        assert( desc != NULL );
                ret = op->o_bd->bd_info->bi_access_allowed( op, e, desc, val, access, state, &mask );
 
        } else {
-               /* use default */
-               ret = slap_access_allowed( op, e, desc, val, access, state, &mask );
+               /* use default (but pass through frontend for global ACL overlays) */
+               be_orig = op->o_bd;
+
+               op->o_bd = frontendDB;
+               ret = frontendDB->bd_info->bi_access_allowed( op, e, desc, val, access, state, &mask );
+               op->o_bd = be_orig;
        }
 
        if ( !ret ) {
 
 }
 
 int 
-backend_group(
+fe_acl_group(
        Operation *op,
        Entry   *target,
        struct berval *gr_ndn,
        GroupAssertion *g;
        Backend *be = op->o_bd;
 
-       if ( op->o_abandon ) return SLAPD_ABANDON;
-
        op->o_bd = select_backend( gr_ndn, 0, 0 );
 
        for ( g = op->o_groups; g; g = g->ga_next ) {
 }
 
 int 
-backend_attribute(
+backend_group(
+       Operation *op,
+       Entry   *target,
+       struct berval *gr_ndn,
+       struct berval *op_ndn,
+       ObjectClass *group_oc,
+       AttributeDescription *group_at )
+{
+       int                     rc;
+       BackendDB               *be_orig;
+
+       if ( op->o_abandon ) {
+               return SLAPD_ABANDON;
+       }
+
+       be_orig = op->o_bd;
+       op->o_bd = frontendDB;
+       rc = frontendDB->be_group( op, target, gr_ndn,
+               op_ndn, group_oc, group_at );
+       op->o_bd = be_orig;
+
+       return rc;
+}
+
+int 
+fe_acl_attribute(
        Operation *op,
        Entry   *target,
        struct berval   *edn,
        return rc;
 }
 
+int 
+backend_attribute(
+       Operation *op,
+       Entry   *target,
+       struct berval   *edn,
+       AttributeDescription *entry_at,
+       BerVarray *vals,
+       slap_access_t access )
+{
+       int                     rc;
+       BackendDB               *be_orig;
+
+       be_orig = op->o_bd;
+       op->o_bd = frontendDB;
+       rc = frontendDB->be_attribute( op, target, edn,
+               entry_at, vals, access );
+       op->o_bd = be_orig;
+
+       return rc;
+}
+
 int 
 backend_access(
        Operation               *op,
        Operation *op,
        SlapReply *rs )
 {
-       Attribute       **ap;
-       int             rc = 0;
-       BackendDB       *be_orig;
+       Attribute               **ap;
+       int                     rc = 0;
+       BackendDB               *be_orig;
 
        for ( ap = &rs->sr_operational_attrs; *ap; ap = &(*ap)->a_next )
                /* just count them */ ;
 
        frontendDB->bd_info->bi_op_search = fe_op_search;
        frontendDB->bd_info->bi_extended = fe_extended;
        frontendDB->bd_info->bi_operational = fe_aux_operational;
+#if 0
+       frontendDB->bd_info->bi_entry_get_rw = fe_entry_get_rw;
+       frontendDB->bd_info->bi_entry_release_rw = fe_entry_release_rw;
+#endif
+#ifdef SLAP_OVERLAY_ACCESS
+       frontendDB->bd_info->bi_access_allowed = slap_access_allowed;
+       frontendDB->bd_info->bi_acl_group = fe_acl_group;
+       frontendDB->bd_info->bi_acl_attribute = fe_acl_attribute;
+#endif /* SLAP_OVERLAY_ACCESS */
 
 #if 0
        /* FIXME: is this too early? */
 
 LDAP_SLAPD_F (int) fe_op_unbind LDAP_P((Operation *op, SlapReply *rs));
 #endif
 LDAP_SLAPD_F (int) fe_extended LDAP_P((Operation *op, SlapReply *rs));
+LDAP_SLAPD_F (int) fe_acl_group LDAP_P((
+       Operation *op,
+       Entry   *target,
+       struct berval *gr_ndn,
+       struct berval *op_ndn,
+       ObjectClass *group_oc,
+       AttributeDescription *group_at ));
+LDAP_SLAPD_F (int) fe_acl_attribute LDAP_P((
+       Operation *op,
+       Entry   *target,
+       struct berval   *edn,
+       AttributeDescription *entry_at,
+       BerVarray *vals,
+       slap_access_t access ));
 
 /* NOTE: this macro assumes that bv has been allocated
  * by ber_* malloc functions or is { 0L, NULL } */
 
        Slapi_Entry             *e;
        int                     rc;
        Slapi_PBlock            *pb = op->o_pb;
+       BackendDB               *be = NULL;
+       BackendDB               *be_orig = op->o_bd;
 
        if ( pb == NULL ) {
                return SLAP_CB_CONTINUE;
        }
 
-       rc = be_entry_get_rw( op, gr_ndn, group_oc, group_at, 0, &e );
-       if ( e == NULL ) {
+       if ( target != NULL && dn_match( &target->e_nname, gr_ndn ) ) {
+               e = target;
+               rc = 0;
+       } else {
+               be = select_backend( gr_ndn, 0, 0 );
+               if ( be == NULL ) {
+                       rc = LDAP_NO_SUCH_OBJECT;
+               } else {
+                       op->o_bd = be;
+                       rc = be_entry_get_rw( op, gr_ndn, group_oc, group_at, 0, &e );
+                       op->o_bd = be_orig;
+               }
+       }
+
+       if ( rc ) {
                return SLAP_CB_CONTINUE;
        }
 
        slapi_pblock_set( pb, SLAPI_X_GROUP_ATTRIBUTE,     NULL );
        slapi_pblock_set( pb, SLAPI_X_GROUP_TARGET_ENTRY,  NULL );
 
-       if ( e != target )
+       if ( e != target ) {
+               op->o_bd = be;
                be_entry_release_r( op, e );
+               op->o_bd = be_orig;
+       }
 
        /*
         * XXX don't call POST_GROUP_FN, I have no idea what the point of
        return rc;
 }
 
-#if 0
-static int
-slapi_over_compute_output_attr_access(computed_attr_context *c, Slapi_Attr *a, Slapi_Entry *e)
-{
-       struct berval   *nval = (struct berval *)c->cac_private;
-
-       return access_allowed( c->cac_op, e, a->a_desc, nval, ACL_AUTH, NULL ) == 0;
-}
-
-static int
-slapi_over_acl_attribute(
-       Operation               *op,
-       Entry                   *target,
-       struct berval           *entry_ndn,
-       AttributeDescription    *entry_at,
-       BerVarray               *vals,
-       slap_access_t           access )
-{
-       computed_attr_context   ctx;
-
-       ctx.cac_pb = op->o_pb;
-       ctx.cac_op = op;
-       ctx.cac_acl_state = NULL;
-       ctx.cac_private = nval;
-}
-#endif
-
 int
 slapi_int_overlay_init()
 {
        slapi.on_bi.bi_extended = slapi_over_extended;
        slapi.on_bi.bi_access_allowed = slapi_over_access_allowed;
        slapi.on_bi.bi_operational = slapi_over_aux_operational;
+       slapi.on_bi.bi_acl_group = slapi_over_acl_group;
 
        return overlay_register( &slapi );
 }