/*
 *  Licensed to the Apache Software Foundation (ASF) under one
 *  or more contributor license agreements.  See the NOTICE file
 *  distributed with this work for additional information
 *  regarding copyright ownership.  The ASF licenses this file
 *  to you under the Apache License, Version 2.0 (the
 *  "License"); you may not use this file except in compliance
 *  with the License.  You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing,
 *  software distributed under the License is distributed on an
 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 *  KIND, either express or implied.  See the License for the
 *  specific language governing permissions and limitations
 *  under the License.
 *
 */
package org.apache.directory.server.core.authz;


import java.io.IOException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.naming.directory.SearchControls;

import org.apache.directory.api.ldap.aci.ACIItem;
import org.apache.directory.api.ldap.aci.ACIItemParser;
import org.apache.directory.api.ldap.aci.ACITuple;
import org.apache.directory.api.ldap.aci.MicroOperation;
import org.apache.directory.api.ldap.model.constants.Loggers;
import org.apache.directory.api.ldap.model.constants.SchemaConstants;
import org.apache.directory.api.ldap.model.entry.Attribute;
import org.apache.directory.api.ldap.model.entry.Entry;
import org.apache.directory.api.ldap.model.entry.Modification;
import org.apache.directory.api.ldap.model.entry.Value;
import org.apache.directory.api.ldap.model.exception.LdapException;
import org.apache.directory.api.ldap.model.exception.LdapNoPermissionException;
import org.apache.directory.api.ldap.model.exception.LdapOperationErrorException;
import org.apache.directory.api.ldap.model.exception.LdapOperationException;
import org.apache.directory.api.ldap.model.exception.LdapOtherException;
import org.apache.directory.api.ldap.model.filter.EqualityNode;
import org.apache.directory.api.ldap.model.filter.ExprNode;
import org.apache.directory.api.ldap.model.filter.OrNode;
import org.apache.directory.api.ldap.model.message.AliasDerefMode;
import org.apache.directory.api.ldap.model.message.SearchScope;
import org.apache.directory.api.ldap.model.name.Dn;
import org.apache.directory.api.ldap.model.schema.AttributeType;
import org.apache.directory.api.ldap.model.schema.normalizers.ConcreteNameComponentNormalizer;
import org.apache.directory.server.constants.ServerDNConstants;
import org.apache.directory.server.core.api.CoreSession;
import org.apache.directory.server.core.api.DirectoryService;
import org.apache.directory.server.core.api.InterceptorEnum;
import org.apache.directory.server.core.api.LdapPrincipal;
import org.apache.directory.server.core.api.entry.ClonedServerEntry;
import org.apache.directory.server.core.api.entry.ServerEntryUtils;
import org.apache.directory.server.core.api.filtering.EntryFilter;
import org.apache.directory.server.core.api.filtering.EntryFilteringCursor;
import org.apache.directory.server.core.api.interceptor.BaseInterceptor;
import org.apache.directory.server.core.api.interceptor.context.AddOperationContext;
import org.apache.directory.server.core.api.interceptor.context.CompareOperationContext;
import org.apache.directory.server.core.api.interceptor.context.DeleteOperationContext;
import org.apache.directory.server.core.api.interceptor.context.HasEntryOperationContext;
import org.apache.directory.server.core.api.interceptor.context.LookupOperationContext;
import org.apache.directory.server.core.api.interceptor.context.ModifyOperationContext;
import org.apache.directory.server.core.api.interceptor.context.MoveAndRenameOperationContext;
import org.apache.directory.server.core.api.interceptor.context.MoveOperationContext;
import org.apache.directory.server.core.api.interceptor.context.OperationContext;
import org.apache.directory.server.core.api.interceptor.context.RenameOperationContext;
import org.apache.directory.server.core.api.interceptor.context.SearchOperationContext;
import org.apache.directory.server.core.api.partition.Partition;
import org.apache.directory.server.core.api.partition.PartitionNexus;
import org.apache.directory.server.core.api.partition.PartitionTxn;
import org.apache.directory.server.core.api.subtree.SubentryUtils;
import org.apache.directory.server.core.authz.support.ACDFEngine;
import org.apache.directory.server.core.authz.support.AciContext;
import org.apache.directory.server.i18n.I18n;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * An ACI based authorization service.
 *
 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
 */
public class AciAuthorizationInterceptor extends BaseInterceptor
{
    /** the logger for this class */
    private static final Logger LOG = LoggerFactory.getLogger( AciAuthorizationInterceptor.class );

    /** the dedicated logger for ACI */
    private static final Logger ACI_LOG = LoggerFactory.getLogger( Loggers.ACI_LOG.getName() );

    private static final Collection<MicroOperation> ADD_PERMS;
    private static final Collection<MicroOperation> READ_PERMS;
    private static final Collection<MicroOperation> COMPARE_PERMS;
    private static final Collection<MicroOperation> SEARCH_ENTRY_PERMS;
    private static final Collection<MicroOperation> SEARCH_ATTRVAL_PERMS;
    private static final Collection<MicroOperation> REMOVE_PERMS;
    private static final Collection<MicroOperation> BROWSE_PERMS;
    private static final Collection<MicroOperation> LOOKUP_PERMS;
    private static final Collection<MicroOperation> REPLACE_PERMS;
    private static final Collection<MicroOperation> RENAME_PERMS;
    private static final Collection<MicroOperation> EXPORT_PERMS;
    private static final Collection<MicroOperation> IMPORT_PERMS;
    private static final Collection<MicroOperation> MOVERENAME_PERMS;

    static
    {
        Set<MicroOperation> set = new HashSet<>( 2 );
        set.add( MicroOperation.BROWSE );
        set.add( MicroOperation.RETURN_DN );
        SEARCH_ENTRY_PERMS = Collections.unmodifiableCollection( set );

        set = new HashSet<>( 2 );
        set.add( MicroOperation.READ );
        set.add( MicroOperation.BROWSE );
        LOOKUP_PERMS = Collections.unmodifiableCollection( set );

        set = new HashSet<>( 2 );
        set.add( MicroOperation.ADD );
        set.add( MicroOperation.REMOVE );
        REPLACE_PERMS = Collections.unmodifiableCollection( set );

        set = new HashSet<>( 2 );
        set.add( MicroOperation.EXPORT );
        set.add( MicroOperation.RENAME );
        MOVERENAME_PERMS = Collections.unmodifiableCollection( set );

        SEARCH_ATTRVAL_PERMS = Collections.singleton( MicroOperation.READ );
        ADD_PERMS = Collections.singleton( MicroOperation.ADD );
        READ_PERMS = Collections.singleton( MicroOperation.READ );
        COMPARE_PERMS = Collections.singleton( MicroOperation.COMPARE );
        REMOVE_PERMS = Collections.singleton( MicroOperation.REMOVE );
        BROWSE_PERMS = Collections.singleton( MicroOperation.BROWSE );
        RENAME_PERMS = Collections.singleton( MicroOperation.RENAME );
        EXPORT_PERMS = Collections.singleton( MicroOperation.EXPORT );
        IMPORT_PERMS = Collections.singleton( MicroOperation.IMPORT );
    }

    /** a tupleCache that responds to add, delete, and modify attempts */
    private TupleCache tupleCache;

    /** a groupCache that responds to add, delete, and modify attempts */
    private GroupCache groupCache;

    /** a normalizing ACIItem parser */
    private ACIItemParser aciParser;

    /** use and instance of the ACDF engine */
    private ACDFEngine engine;

    /** the system wide subschemaSubentryDn */
    private Dn subschemaSubentryDn;

    /** A reference to the nexus for direct backend operations */
    private PartitionNexus nexus;

    public static final SearchControls DEFAULT_SEARCH_CONTROLS = new SearchControls();

    /** The SubentryUtils instance */
    private static SubentryUtils subentryUtils;


    /**
     * Create a AciAuthorizationInterceptor instance
     */
    public AciAuthorizationInterceptor()
    {
        super( InterceptorEnum.ACI_AUTHORIZATION_INTERCEPTOR );
    }


    /**
     * Load the Tuples into the cache
     */
    private void initTupleCache() throws LdapException
    {
        // Load all the prescriptiveACI : they are stored in AccessControlSubentry entries
        SearchControls controls = new SearchControls();
        controls.setSearchScope( SearchControls.SUBTREE_SCOPE );
        controls.setReturningAttributes( new String[]
            { SchemaConstants.PRESCRIPTIVE_ACI_AT } );

        AttributeType ocAt = directoryService.getAtProvider().getObjectClass();
        ExprNode filter = new EqualityNode<String>( ocAt, 
            new Value( ocAt, SchemaConstants.ACCESS_CONTROL_SUBENTRY_OC ) );

        CoreSession adminSession = directoryService.getAdminSession();

        SearchOperationContext searchOperationContext = new SearchOperationContext( adminSession, Dn.ROOT_DSE, filter, controls );

        searchOperationContext.setAliasDerefMode( AliasDerefMode.NEVER_DEREF_ALIASES );
        Partition partition = nexus.getPartition( Dn.ROOT_DSE );
        searchOperationContext.setPartition( partition );
        
        try ( PartitionTxn partitionTxn = partition.beginReadTransaction() )
        {
            searchOperationContext.setTransaction( partitionTxn );

            EntryFilteringCursor results = nexus.search( searchOperationContext );
    
            try
            {
                while ( results.next() )
                {
                    Entry entry = results.get();
    
                    tupleCache.subentryAdded( entry.getDn(), entry );
                }
    
                results.close();
            }
            catch ( Exception e )
            {
                throw new LdapOperationException( e.getMessage(), e );
            }
        }
        catch ( IOException ioe )
        {
            throw new LdapOtherException( ioe.getMessage(), ioe );
        }
    }


    /**
     * Load the Groups into the cache
     */
    private void initGroupCache() throws LdapException
    {
        // Load all the member/uniqueMember : they are stored in groupOfNames/groupOfUniqueName
        SearchControls controls = new SearchControls();
        controls.setSearchScope( SearchControls.SUBTREE_SCOPE );
        controls.setReturningAttributes( new String[]
            { SchemaConstants.MEMBER_AT, SchemaConstants.UNIQUE_MEMBER_AT } );
        AttributeType ocAt = directoryService.getAtProvider().getObjectClass();

        ExprNode filter =
            new OrNode(
                new EqualityNode<String>( ocAt, new Value( ocAt, SchemaConstants.GROUP_OF_NAMES_OC ) ),
                new EqualityNode<String>( ocAt, new Value( ocAt, SchemaConstants.GROUP_OF_UNIQUE_NAMES_OC ) ) );

        CoreSession adminSession = directoryService.getAdminSession();
        
        SearchOperationContext searchOperationContext = new SearchOperationContext( adminSession, Dn.ROOT_DSE, filter,
            controls );

        searchOperationContext.setAliasDerefMode( AliasDerefMode.NEVER_DEREF_ALIASES );

        EntryFilteringCursor results = nexus.search( searchOperationContext );

        try
        {
            while ( results.next() )
            {
                Entry entry = results.get();

                groupCache.groupAdded( entry.getDn().getNormName(), entry );
            }

            results.close();
        }
        catch ( Exception e )
        {
            throw new LdapOperationException( e.getMessage(), e );
        }
    }


    /**
     * Initializes this interceptor based service by getting a handle on the nexus, setting up
     * the tuple and group membership caches, the ACIItem parser and the ACDF engine.
     *
     * @param directoryService the directory service core
     * @throws LdapException if there are problems during initialization
     */
    @Override
    public void init( DirectoryService directoryService ) throws LdapException
    {
        LOG.debug( "Initializing the AciAuthorizationInterceptor" );

        super.init( directoryService );

        nexus = directoryService.getPartitionNexus();

        CoreSession adminSession = directoryService.getAdminSession();

        // Create the caches
        tupleCache = new TupleCache( adminSession );
        groupCache = new GroupCache( directoryService );

        // Iitialize the ACI PARSER and ACDF engine
        aciParser = new ACIItemParser( new ConcreteNameComponentNormalizer( schemaManager ), schemaManager );
        engine = new ACDFEngine( schemaManager );

        // stuff for dealing with subentries (garbage for now)
        Value subschemaSubentry = directoryService.getPartitionNexus().getRootDseValue(
            directoryService.getAtProvider().getSubschemaSubentry() );
        subschemaSubentryDn = dnFactory.create( subschemaSubentry.getString() );

        // Init the caches now
        initTupleCache();
        initGroupCache();

        // Init the SubentryUtils instance
        subentryUtils = new SubentryUtils( directoryService );
    }


    private void protectCriticalEntries( OperationContext opCtx, Dn dn ) throws LdapException
    {
        Dn principalDn = getPrincipal( opCtx ).getDn();

        if ( dn.isEmpty() )
        {
            String msg = I18n.err( I18n.ERR_8 );
            LOG.error( msg );
            throw new LdapNoPermissionException( msg );
        }

        if ( isTheAdministrator( dn ) )
        {
            String msg = I18n.err( I18n.ERR_9, principalDn.getName(), dn.getName() );
            LOG.error( msg );
            throw new LdapNoPermissionException( msg );
        }
    }


    /**
     * Adds perscriptiveACI tuples to a collection of tuples by accessing the
     * tupleCache.  The tuple cache is accessed for each A/C subentry
     * associated with the protected entry.  Note that subentries are handled
     * differently: their parent, the administrative entry is accessed to
     * determine the perscriptiveACIs effecting the AP and hence the subentry
     * which is considered to be in the same context.
     *
     * @param tuples the collection of tuples to add to
     * @param dn the normalized distinguished name of the protected entry
     * @param entry the target entry whose access is being controlled
     * @throws Exception if there are problems accessing attribute values
     * @param proxy the partition nexus proxy object
     */
    private void addPerscriptiveAciTuples( OperationContext opContext, Collection<ACITuple> tuples, Dn dn, Entry entry )
        throws LdapException
    {
        Entry originalEntry;

        if ( entry instanceof ClonedServerEntry )
        {
            originalEntry = ( ( ClonedServerEntry ) entry ).getOriginalEntry();
        }
        else
        {
            originalEntry = entry;
        }

        Attribute oc = originalEntry.get( directoryService.getAtProvider().getObjectClass() );

        /*
         * If the protected entry is a subentry, then the entry being evaluated
         * for perscriptiveACIs is in fact the administrative entry.  By
         * substituting the administrative entry for the actual subentry the
         * code below this "if" statement correctly evaluates the effects of
         * perscriptiveACI on the subentry.  Basically subentries are considered
         * to be in the same naming context as their access point so the subentries
         * effecting their parent entry applies to them as well.
         */
        if ( oc.contains( SchemaConstants.SUBENTRY_OC ) )
        {
            Dn parentDn = dn.getParent();
            CoreSession session = opContext.getSession();
            LookupOperationContext lookupContext = new LookupOperationContext( session, parentDn,
                SchemaConstants.ALL_ATTRIBUTES_ARRAY );
            lookupContext.setPartition( opContext.getPartition() );
            lookupContext.setTransaction( opContext.getTransaction() );

            originalEntry = directoryService.getPartitionNexus().lookup( lookupContext );
        }

        Attribute subentries = originalEntry.get( directoryService.getAtProvider().getAccessControlSubentries() );

        if ( subentries == null )
        {
            return;
        }

        for ( Value value : subentries )
        {
            String subentryDnStr = value.getString();
            Dn subentryDn = dnFactory.create( subentryDnStr );
            tuples.addAll( tupleCache.getACITuples( subentryDn.getNormName() ) );
        }
    }


    /**
     * Adds the set of entryACI tuples to a collection of tuples.  The entryACI
     * is parsed and tuples are generated on they fly then added to the collection.
     *
     * @param tuples the collection of tuples to add to
     * @param entry the target entry that access to is being regulated
     * @throws Exception if there are problems accessing attribute values
     */
    private void addEntryAciTuples( Collection<ACITuple> tuples, Entry entry ) throws LdapException
    {
        Attribute entryAci = entry.get( directoryService.getAtProvider().getEntryACI() );

        if ( entryAci == null )
        {
            return;
        }

        for ( Value value : entryAci )
        {
            String aciString = value.getString();
            ACIItem item;

            try
            {
                item = aciParser.parse( aciString );
            }
            catch ( ParseException e )
            {
                String msg = I18n.err( I18n.ERR_10, aciString );
                LOG.error( msg, e );
                throw new LdapOperationErrorException( msg );
            }

            tuples.addAll( item.toTuples() );
        }
    }


    /**
     * Adds the set of subentryACI tuples to a collection of tuples.  The subentryACI
     * is parsed and tuples are generated on the fly then added to the collection.
     *
     * @param tuples the collection of tuples to add to
     * @param dn the normalized distinguished name of the protected entry
     * @param entry the target entry that access to is being regulated
     * @throws Exception if there are problems accessing attribute values
     * @param proxy the partition nexus proxy object
     */
    private void addSubentryAciTuples( OperationContext opContext, Collection<ACITuple> tuples, Dn dn, Entry entry )
        throws LdapException
    {
        // only perform this for subentries
        if ( !entry.contains( SchemaConstants.OBJECT_CLASS_AT, SchemaConstants.SUBENTRY_OC ) )
        {
            return;
        }

        // get the parent or administrative entry for this subentry since it
        // will contain the subentryACI attributes that effect subentries
        Dn parentDn = dn.getParent();

        CoreSession session = opContext.getSession();
        LookupOperationContext lookupContext = new LookupOperationContext( session, parentDn,
            SchemaConstants.ALL_ATTRIBUTES_ARRAY );
        lookupContext.setPartition( opContext.getPartition() );
        lookupContext.setTransaction( opContext.getTransaction() );

        Entry administrativeEntry = ( ( ClonedServerEntry ) directoryService.getPartitionNexus().lookup( lookupContext ) )
            .getOriginalEntry();

        Attribute subentryAci = administrativeEntry.get( directoryService.getAtProvider().getSubentryACI() );

        if ( subentryAci == null )
        {
            return;
        }

        for ( Value value : subentryAci )
        {
            String aciString = value.getString();
            ACIItem item;

            try
            {
                item = aciParser.parse( aciString );
            }
            catch ( ParseException e )
            {
                String msg = I18n.err( I18n.ERR_11, aciString );
                LOG.error( msg, e );
                throw new LdapOperationErrorException( msg );
            }

            tuples.addAll( item.toTuples() );
        }
    }


    /* -------------------------------------------------------------------------------
     * Within every access controled interceptor method we must retrieve the ACITuple
     * set for all the perscriptiveACIs that apply to the candidate, the target entry
     * operated upon.  This ACITuple set is gotten from the TupleCache by looking up
     * the subentries referenced by the accessControlSubentries operational attribute
     * within the target entry.
     *
     * Then the entry is inspected for an entryACI.  This is not done for the add op
     * since it could introduce a security breech.  So for non-add ops if present a
     * set of ACITuples are generated for all the entryACIs within the entry.  This
     * set is combined with the ACITuples cached for the perscriptiveACI affecting
     * the target entry.  If the entry is a subentry the ACIs are also processed for
     * the subentry to generate more ACITuples.  This subentry TupleACI set is joined
     * with the entry and perscriptive ACI.
     *
     * The union of ACITuples are fed into the engine along with other parameters
     * to decide whether a permission is granted or rejected for the specific
     * operation.
     * -------------------------------------------------------------------------------
     */
    /**
     * {@inheritDoc}
     */
    @Override
    public void add( AddOperationContext addContext ) throws LdapException
    {
        // bypass authz code if it was disabled
        if ( !directoryService.isAccessControlEnabled() )
        {
            ACI_LOG.debug( "ACI interceptor disabled" );
            next( addContext );
            return;
        }

        ACI_LOG.debug( "Adding the entry {}", addContext.getEntry() );

        // Access the principal requesting the operation, and bypass checks if it is the admin
        LdapPrincipal principal = addContext.getSession().getEffectivePrincipal();
        Dn principalDn = principal.getDn();

        Entry serverEntry = addContext.getEntry();

        Dn dn = addContext.getDn();

        // bypass authz code but manage caches if operation is performed by the admin
        if ( isPrincipalAnAdministrator( principalDn ) )
        {
            ACI_LOG.debug( "Addition done by the administartor : no check" );

            next( addContext );
            tupleCache.subentryAdded( dn, serverEntry );
            groupCache.groupAdded( dn.getNormName(), serverEntry );
            return;
        }

        // perform checks below here for all non-admin users
        Entry subentry = subentryUtils.getSubentryAttributes( dn, serverEntry );

        for ( Attribute attribute : serverEntry )
        {
            subentry.put( attribute );
        }

        // Assemble all the information required to make an access control decision
        Set<String> userGroups = groupCache.getGroups( principalDn.getNormName() );
        Collection<ACITuple> tuples = new HashSet<>();

        // Build the total collection of tuples to be considered for add rights
        // NOTE: entryACI are NOT considered in adds (it would be a security breech)
        addPerscriptiveAciTuples( addContext, tuples, dn, subentry );
        addSubentryAciTuples( addContext, tuples, dn, subentry );

        // check if entry scope permission is granted
        AciContext entryAciCtx = new AciContext( schemaManager, addContext );
        entryAciCtx.setUserGroupNames( userGroups );
        entryAciCtx.setUserDn( principalDn );
        entryAciCtx.setAuthenticationLevel( principal.getAuthenticationLevel() );
        entryAciCtx.setEntryDn( dn );
        entryAciCtx.setMicroOperations( ADD_PERMS );
        entryAciCtx.setAciTuples( tuples );
        entryAciCtx.setEntry( subentry );

        engine.checkPermission( entryAciCtx );

        // now we must check if attribute type and value scope permission is granted
        for ( Attribute attribute : serverEntry )
        {
            for ( Value value : attribute )
            {
                AciContext attrAciContext = new AciContext( schemaManager, addContext );
                attrAciContext.setUserGroupNames( userGroups );
                attrAciContext.setUserDn( principalDn );
                attrAciContext.setAuthenticationLevel( principal.getAuthenticationLevel() );
                attrAciContext.setEntryDn( dn );
                attrAciContext.setAttributeType( attribute.getAttributeType() );
                attrAciContext.setAttrValue( value );
                attrAciContext.setMicroOperations( ADD_PERMS );
                attrAciContext.setAciTuples( tuples );
                attrAciContext.setEntry( serverEntry );

                engine.checkPermission( attrAciContext );
            }
        }

        // if we've gotten this far then access has been granted
        next( addContext );

        // if the entry added is a subentry or a groupOf[Unique]Names we must
        // update the ACITuple cache and the groups cache to keep them in sync
        tupleCache.subentryAdded( dn, serverEntry );
        groupCache.groupAdded( dn.getNormName(), serverEntry );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public boolean compare( CompareOperationContext compareContext ) throws LdapException
    {
        CoreSession session = compareContext.getSession();
        Dn dn = compareContext.getDn();
        String oid = compareContext.getOid();

        Entry entry = compareContext.getOriginalEntry();

        LdapPrincipal principal = session.getEffectivePrincipal();
        Dn principalDn = principal.getDn();

        if ( isPrincipalAnAdministrator( principalDn ) || !directoryService.isAccessControlEnabled() )
        {
            return next( compareContext );
        }

        Set<String> userGroups = groupCache.getGroups( principalDn.getNormName() );
        Collection<ACITuple> tuples = new HashSet<>();
        addPerscriptiveAciTuples( compareContext, tuples, dn, entry );
        addEntryAciTuples( tuples, entry );
        addSubentryAciTuples( compareContext, tuples, dn, entry );

        AciContext aciContext = new AciContext( schemaManager, compareContext );
        aciContext.setUserGroupNames( userGroups );
        aciContext.setUserDn( principalDn );
        aciContext.setAuthenticationLevel( principal.getAuthenticationLevel() );
        aciContext.setEntryDn( dn );
        aciContext.setMicroOperations( READ_PERMS );
        aciContext.setAciTuples( tuples );
        aciContext.setEntry( entry );

        engine.checkPermission( aciContext );

        AttributeType attributeType = schemaManager.lookupAttributeTypeRegistry( oid );

        aciContext = new AciContext( schemaManager, compareContext );
        aciContext.setUserGroupNames( userGroups );
        aciContext.setUserDn( principalDn );
        aciContext.setAuthenticationLevel( principal.getAuthenticationLevel() );
        aciContext.setEntryDn( dn );
        aciContext.setAttributeType( attributeType );
        aciContext.setMicroOperations( COMPARE_PERMS );
        aciContext.setAciTuples( tuples );
        aciContext.setEntry( entry );

        engine.checkPermission( aciContext );

        return next( compareContext );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public void delete( DeleteOperationContext deleteContext ) throws LdapException
    {
        CoreSession session = deleteContext.getSession();

        // bypass authz code if we are disabled
        if ( !directoryService.isAccessControlEnabled() )
        {
            next( deleteContext );
            return;
        }

        Dn dn = deleteContext.getDn();
        LdapPrincipal principal = session.getEffectivePrincipal();
        Dn principalDn = principal.getDn();

        Entry entry = deleteContext.getEntry();

        protectCriticalEntries( deleteContext, dn );

        // bypass authz code but manage caches if operation is performed by the admin
        if ( isPrincipalAnAdministrator( principalDn ) )
        {
            next( deleteContext );

            tupleCache.subentryDeleted( dn, entry );
            groupCache.groupDeleted( dn, entry );

            return;
        }

        Set<String> userGroups = groupCache.getGroups( principalDn.getNormName() );
        Collection<ACITuple> tuples = new HashSet<>();
        addPerscriptiveAciTuples( deleteContext, tuples, dn, entry );
        addEntryAciTuples( tuples, entry );
        addSubentryAciTuples( deleteContext, tuples, dn, entry );

        AciContext aciContext = new AciContext( schemaManager, deleteContext );
        aciContext.setUserGroupNames( userGroups );
        aciContext.setUserDn( principalDn );
        aciContext.setAuthenticationLevel( principal.getAuthenticationLevel() );
        aciContext.setEntryDn( dn );
        aciContext.setMicroOperations( REMOVE_PERMS );
        aciContext.setAciTuples( tuples );
        aciContext.setEntry( entry );

        engine.checkPermission( aciContext );

        next( deleteContext );

        tupleCache.subentryDeleted( dn, entry );
        groupCache.groupDeleted( dn, entry );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public boolean hasEntry( HasEntryOperationContext hasEntryContext ) throws LdapException
    {
        Dn dn = hasEntryContext.getDn();

        if ( !directoryService.isAccessControlEnabled() )
        {
            return dn.isRootDse() || next( hasEntryContext );
        }

        boolean answer = next( hasEntryContext );

        // no checks on the RootDSE
        if ( dn.isRootDse() )
        {
            // No need to go down to the stack, if the dn is empty
            // It's the rootDSE, and it exists !
            return answer;
        }

        CoreSession session = hasEntryContext.getSession();

        // TODO - eventually replace this with a check on session.isAnAdministrator()
        LdapPrincipal principal = session.getEffectivePrincipal();
        Dn principalDn = principal.getDn();

        if ( isPrincipalAnAdministrator( principalDn ) )
        {
            return answer;
        }

        LookupOperationContext lookupContext = new LookupOperationContext( session, dn,
            SchemaConstants.ALL_ATTRIBUTES_ARRAY );
        lookupContext.setPartition( hasEntryContext.getPartition() );
        lookupContext.setTransaction( hasEntryContext.getTransaction() );

        Entry entry = directoryService.getPartitionNexus().lookup( lookupContext );

        Set<String> userGroups = groupCache.getGroups( principalDn.getNormName() );
        Collection<ACITuple> tuples = new HashSet<>();
        addPerscriptiveAciTuples( hasEntryContext, tuples, dn, entry );
        addEntryAciTuples( tuples, ( ( ClonedServerEntry ) entry ).getOriginalEntry() );
        addSubentryAciTuples( hasEntryContext, tuples, dn, ( ( ClonedServerEntry ) entry ).getOriginalEntry() );

        // check that we have browse access to the entry
        AciContext aciContext = new AciContext( schemaManager, hasEntryContext );
        aciContext.setUserGroupNames( userGroups );
        aciContext.setUserDn( principalDn );
        aciContext.setAuthenticationLevel( principal.getAuthenticationLevel() );
        aciContext.setEntryDn( dn );
        aciContext.setMicroOperations( BROWSE_PERMS );
        aciContext.setAciTuples( tuples );
        aciContext.setEntry( ( ( ClonedServerEntry ) entry ).getOriginalEntry() );

        engine.checkPermission( aciContext );

        return next( hasEntryContext );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public Entry lookup( LookupOperationContext lookupContext ) throws LdapException
    {
        CoreSession session = lookupContext.getSession();

        Entry entry = next( lookupContext );

        LdapPrincipal principal = session.getEffectivePrincipal();
        Dn principalDn = principal.getDn();
        
        if ( !principalDn.isSchemaAware() )
        {
            principalDn = new Dn( schemaManager, principalDn );
        }

        // Bypass this interceptor if we disabled the AC subsystem or if the principal is the admin
        if ( isPrincipalAnAdministrator( principalDn ) || !directoryService.isAccessControlEnabled() )
        {
            return entry;
        }

        checkLookupAccess( lookupContext, entry );

        return entry;
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public void modify( ModifyOperationContext modifyContext ) throws LdapException
    {
        Dn dn = modifyContext.getDn();

        // Access the principal requesting the operation, and bypass checks if it is the admin
        Entry entry = modifyContext.getEntry();

        LdapPrincipal principal = modifyContext.getSession().getEffectivePrincipal();
        Dn principalDn = principal.getDn();

        // bypass authz code if we are disabled
        if ( !directoryService.isAccessControlEnabled() )
        {
            next( modifyContext );
            return;
        }

        List<Modification> mods = modifyContext.getModItems();

        // bypass authz code but manage caches if operation is performed by the admin
        if ( isPrincipalAnAdministrator( principalDn ) )
        {
            next( modifyContext );

            Entry modifiedEntry = modifyContext.getAlteredEntry();
            tupleCache.subentryModified( dn, mods, modifiedEntry );
            groupCache.groupModified( dn, mods, entry, schemaManager );

            return;
        }

        Set<String> userGroups = groupCache.getGroups( principalDn.getNormName() );
        Collection<ACITuple> tuples = new HashSet<>();
        addPerscriptiveAciTuples( modifyContext, tuples, dn, entry );
        addEntryAciTuples( tuples, entry );
        addSubentryAciTuples( modifyContext, tuples, dn, entry );

        AciContext entryAciContext = new AciContext( schemaManager, modifyContext );
        entryAciContext.setUserGroupNames( userGroups );
        entryAciContext.setUserDn( principalDn );
        entryAciContext.setAuthenticationLevel( principal.getAuthenticationLevel() );
        entryAciContext.setEntryDn( dn );
        entryAciContext.setMicroOperations( Collections.singleton( MicroOperation.MODIFY ) );
        entryAciContext.setAciTuples( tuples );
        entryAciContext.setEntry( entry );

        engine.checkPermission( entryAciContext );

        Collection<MicroOperation> perms;
        Entry entryView = entry.clone();

        for ( Modification mod : mods )
        {
            Attribute attr = mod.getAttribute();

            switch ( mod.getOperation() )
            {
                case ADD_ATTRIBUTE:
                    perms = ADD_PERMS;

                    // If the attribute is being created with an initial value ...
                    if ( entry.get( attr.getId() ) == null )
                    {
                        AciContext attrAciContext = new AciContext( schemaManager, modifyContext );
                        attrAciContext.setUserGroupNames( userGroups );
                        attrAciContext.setUserDn( principalDn );
                        attrAciContext.setAuthenticationLevel( principal.getAuthenticationLevel() );
                        attrAciContext.setEntryDn( dn );
                        attrAciContext.setAttributeType( attr.getAttributeType() );
                        attrAciContext.setMicroOperations( perms );
                        attrAciContext.setAciTuples( tuples );
                        attrAciContext.setEntry( entry );

                        // ... we also need to check if adding the attribute is permitted
                        engine.checkPermission( attrAciContext );
                    }

                    break;

                case REMOVE_ATTRIBUTE:
                    perms = REMOVE_PERMS;
                    Attribute entryAttr = entry.get( attr.getId() );

                    if ( ( entryAttr != null ) && ( entryAttr.size() == 1 ) )
                    {
                        // If there is only one value remaining in the attribute ...
                        // ... we also need to check if removing the attribute at all is permitted
                        AciContext aciContext = new AciContext( schemaManager, modifyContext );
                        aciContext.setUserGroupNames( userGroups );
                        aciContext.setUserDn( principalDn );
                        aciContext.setAuthenticationLevel( principal.getAuthenticationLevel() );
                        aciContext.setEntryDn( dn );
                        aciContext.setAttributeType( attr.getAttributeType() );
                        aciContext.setMicroOperations( perms );
                        aciContext.setAciTuples( tuples );
                        aciContext.setEntry( entry );

                        engine.checkPermission( aciContext );
                    }

                    break;

                case REPLACE_ATTRIBUTE:
                    perms = REPLACE_PERMS;
                    break;

                default:
                    throw new IllegalArgumentException( "Unexpected modify operation " + mod.getOperation() );
            }

            /**
             * Update the entry view as the current modification is applied to the original entry.
             * This is especially required for handling the MaxValueCount protected item. Number of
             * values for an attribute after a modification should be known in advance in order to
             * check permissions for MaxValueCount protected item. So during addition of the first
             * value of an attribute it can be rejected if the permission denied due the the
             * MaxValueCount protected item. This is not the perfect implementation as required by
             * the specification because the system should reject the addition exactly on the right
             * value of the attribute. However as we do not have that much granularity in our
             * implementation (we consider an Attribute Addition itself a Micro Operation,
             * not the individual Value Additions) we just handle this when the first value of an
             * attribute is being checked for relevant permissions below.
             */
            entryView = ServerEntryUtils.getTargetEntry( mod, entryView, schemaManager );

            for ( Value value : attr )
            {
                AciContext aciContext = new AciContext( schemaManager, modifyContext );
                aciContext.setUserGroupNames( userGroups );
                aciContext.setUserDn( principalDn );
                aciContext.setAuthenticationLevel( principal.getAuthenticationLevel() );
                aciContext.setEntryDn( dn );
                aciContext.setAttributeType( attr.getAttributeType() );
                aciContext.setAttrValue( value );
                aciContext.setMicroOperations( perms );
                aciContext.setAciTuples( tuples );
                aciContext.setEntry( entry );
                aciContext.setEntryView( entryView );

                engine.checkPermission( aciContext );
            }
        }

        next( modifyContext );

        Entry modifiedEntry = modifyContext.getAlteredEntry();
        tupleCache.subentryModified( dn, mods, modifiedEntry );
        groupCache.groupModified( dn, mods, entry, schemaManager );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public void move( MoveOperationContext moveContext ) throws LdapException
    {
        Dn oriChildName = moveContext.getDn();

        // Access the principal requesting the operation, and bypass checks if it is the admin
        Entry entry = moveContext.getOriginalEntry();
        CoreSession session = moveContext.getSession();

        Dn newDn = moveContext.getNewDn();

        LdapPrincipal principal = session.getEffectivePrincipal();
        Dn principalDn = principal.getDn();

        // bypass authz code if we are disabled
        if ( !directoryService.isAccessControlEnabled() )
        {
            next( moveContext );
            return;
        }

        protectCriticalEntries( moveContext, oriChildName );

        // bypass authz code but manage caches if operation is performed by the admin
        if ( isPrincipalAnAdministrator( principalDn ) )
        {
            next( moveContext );
            tupleCache.subentryRenamed( oriChildName, newDn );
            groupCache.groupRenamed( oriChildName, newDn );
            return;
        }

        Set<String> userGroups = groupCache.getGroups( principalDn.getNormName() );
        Collection<ACITuple> tuples = new HashSet<>();
        addPerscriptiveAciTuples( moveContext, tuples, oriChildName, entry );
        addEntryAciTuples( tuples, entry );
        addSubentryAciTuples( moveContext, tuples, oriChildName, entry );

        AciContext aciContext = new AciContext( schemaManager, moveContext );
        aciContext.setUserGroupNames( userGroups );
        aciContext.setUserDn( principalDn );
        aciContext.setAuthenticationLevel( principal.getAuthenticationLevel() );
        aciContext.setEntryDn( oriChildName );
        aciContext.setMicroOperations( EXPORT_PERMS );
        aciContext.setAciTuples( tuples );
        aciContext.setEntry( entry );

        engine.checkPermission( aciContext );

        // Get the entry again without operational attributes
        // because access control subentry operational attributes
        // will not be valid at the new location.
        // This will certainly be fixed by the SubentryInterceptor,
        // but after this service.
        LookupOperationContext lookupContext = new LookupOperationContext( session, oriChildName,
            SchemaConstants.ALL_USER_ATTRIBUTES_ARRAY );
        lookupContext.setPartition( moveContext.getPartition() );
        lookupContext.setTransaction( moveContext.getTransaction() );

        Entry importedEntry = directoryService.getPartitionNexus().lookup( lookupContext );

        // As the target entry does not exist yet and so
        // its subentry operational attributes are not there,
        // we need to construct an entry to represent it
        // at least with minimal requirements which are object class
        // and access control subentry operational attributes.
        Entry subentryAttrs = subentryUtils.getSubentryAttributes( newDn, importedEntry );

        for ( Attribute attribute : importedEntry )
        {
            subentryAttrs.put( attribute );
        }

        Collection<ACITuple> destTuples = new HashSet<>();
        // Import permission is only valid for prescriptive ACIs
        addPerscriptiveAciTuples( moveContext, destTuples, newDn, subentryAttrs );

        // Evaluate the target context to see whether it
        // allows an entry named newName to be imported as a subordinate.
        aciContext = new AciContext( schemaManager, moveContext );
        aciContext.setUserGroupNames( userGroups );
        aciContext.setUserDn( principalDn );
        aciContext.setAuthenticationLevel( principal.getAuthenticationLevel() );
        aciContext.setEntryDn( newDn );
        aciContext.setMicroOperations( IMPORT_PERMS );
        aciContext.setAciTuples( destTuples );
        aciContext.setEntry( subentryAttrs );

        engine.checkPermission( aciContext );

        next( moveContext );
        tupleCache.subentryRenamed( oriChildName, newDn );
        groupCache.groupRenamed( oriChildName, newDn );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public void moveAndRename( MoveAndRenameOperationContext moveAndRenameContext ) throws LdapException
    {
        Dn oldDn = moveAndRenameContext.getDn();
        CoreSession session = moveAndRenameContext.getSession();

        Entry entry = moveAndRenameContext.getOriginalEntry();

        LdapPrincipal principal = session.getEffectivePrincipal();
        Dn principalDn = principal.getDn();
        Dn newDn = moveAndRenameContext.getNewDn();

        // bypass authz code if we are disabled
        if ( !directoryService.isAccessControlEnabled() )
        {
            next( moveAndRenameContext );

            return;
        }

        protectCriticalEntries( moveAndRenameContext, oldDn );

        // bypass authz code but manage caches if operation is performed by the admin
        if ( isPrincipalAnAdministrator( principalDn ) )
        {
            next( moveAndRenameContext );
            tupleCache.subentryRenamed( oldDn, newDn );
            groupCache.groupRenamed( oldDn, newDn );

            return;
        }

        Set<String> userGroups = groupCache.getGroups( principalDn.getNormName() );
        Collection<ACITuple> tuples = new HashSet<>();
        addPerscriptiveAciTuples( moveAndRenameContext, tuples, oldDn, entry );
        addEntryAciTuples( tuples, entry );
        addSubentryAciTuples( moveAndRenameContext, tuples, oldDn, entry );

        AciContext aciContext = new AciContext( schemaManager, moveAndRenameContext );
        aciContext.setUserGroupNames( userGroups );
        aciContext.setUserDn( principalDn );
        aciContext.setAuthenticationLevel( principal.getAuthenticationLevel() );
        aciContext.setEntryDn( oldDn );
        aciContext.setMicroOperations( MOVERENAME_PERMS );
        aciContext.setAciTuples( tuples );
        aciContext.setEntry( entry );

        engine.checkPermission( aciContext );

        // Get the entry again without operational attributes
        // because access control subentry operational attributes
        // will not be valid at the new location.
        // This will certainly be fixed by the SubentryInterceptor,
        // but after this service.

        LookupOperationContext lookupContext = new LookupOperationContext( session, oldDn,
            SchemaConstants.ALL_USER_ATTRIBUTES_ARRAY );
        lookupContext.setPartition( moveAndRenameContext.getPartition() );
        lookupContext.setTransaction( moveAndRenameContext.getTransaction() );

        Entry importedEntry = directoryService.getPartitionNexus().lookup( lookupContext );

        // As the target entry does not exist yet and so
        // its subentry operational attributes are not there,
        // we need to construct an entry to represent it
        // at least with minimal requirements which are object class
        // and access control subentry operational attributes.
        Entry subentryAttrs = subentryUtils.getSubentryAttributes( newDn, importedEntry );

        for ( Attribute attribute : importedEntry )
        {
            subentryAttrs.put( attribute );
        }

        Collection<ACITuple> destTuples = new HashSet<>();
        // Import permission is only valid for prescriptive ACIs
        addPerscriptiveAciTuples( moveAndRenameContext, destTuples, newDn, subentryAttrs );

        // Evaluate the target context to see whether it
        // allows an entry named newName to be imported as a subordinate.
        aciContext = new AciContext( schemaManager, moveAndRenameContext );
        aciContext.setUserGroupNames( userGroups );
        aciContext.setUserDn( principalDn );
        aciContext.setAuthenticationLevel( principal.getAuthenticationLevel() );
        aciContext.setEntryDn( newDn );
        aciContext.setMicroOperations( IMPORT_PERMS );
        aciContext.setAciTuples( destTuples );
        aciContext.setEntry( subentryAttrs );

        engine.checkPermission( aciContext );

        next( moveAndRenameContext );
        tupleCache.subentryRenamed( oldDn, newDn );
        groupCache.groupRenamed( oldDn, newDn );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public void rename( RenameOperationContext renameContext ) throws LdapException
    {
        Dn oldName = renameContext.getDn();
        Entry originalEntry = renameContext.getOriginalEntry();

        if ( renameContext.getEntry() != null )
        {
            originalEntry = ( ( ClonedServerEntry ) renameContext.getEntry() ).getOriginalEntry();
        }

        LdapPrincipal principal = renameContext.getSession().getEffectivePrincipal();
        Dn principalDn = principal.getDn();
        Dn newName = renameContext.getNewDn();

        // bypass authz code if we are disabled
        if ( !directoryService.isAccessControlEnabled() )
        {
            next( renameContext );
            return;
        }

        protectCriticalEntries( renameContext, oldName );

        // bypass authz code but manage caches if operation is performed by the admin
        if ( isPrincipalAnAdministrator( principalDn ) )
        {
            next( renameContext );
            tupleCache.subentryRenamed( oldName, newName );

            // TODO : this method returns a boolean : what should we do with the result ?
            groupCache.groupRenamed( oldName, newName );

            return;
        }

        Set<String> userGroups = groupCache.getGroups( principalDn.getNormName() );
        Collection<ACITuple> tuples = new HashSet<>();
        addPerscriptiveAciTuples( renameContext, tuples, oldName, originalEntry );
        addEntryAciTuples( tuples, originalEntry );
        addSubentryAciTuples( renameContext, tuples, oldName, originalEntry );

        AciContext aciContext = new AciContext( schemaManager, renameContext );
        aciContext.setUserGroupNames( userGroups );
        aciContext.setUserDn( principalDn );
        aciContext.setAuthenticationLevel( principal.getAuthenticationLevel() );
        aciContext.setEntryDn( oldName );
        aciContext.setMicroOperations( RENAME_PERMS );
        aciContext.setAciTuples( tuples );
        aciContext.setEntry( originalEntry );

        engine.checkPermission( aciContext );

        next( renameContext );
        tupleCache.subentryRenamed( oldName, newName );
        groupCache.groupRenamed( oldName, newName );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public EntryFilteringCursor search( SearchOperationContext searchContext ) throws LdapException
    {
        LdapPrincipal user = searchContext.getSession().getEffectivePrincipal();
        Dn principalDn = user.getDn();
        EntryFilteringCursor cursor = next( searchContext );

        boolean isSubschemaSubentryLookup = subschemaSubentryDn.equals( searchContext.getDn() );

        boolean isRootDseLookup = ( searchContext.getDn().size() == 0 )
            && ( searchContext.getScope() == SearchScope.OBJECT );

        if ( isPrincipalAnAdministrator( principalDn )
            || !directoryService.isAccessControlEnabled() || isRootDseLookup
            || isSubschemaSubentryLookup )
        {
            return cursor;
        }

        cursor.addEntryFilter( new AuthorizationFilter() );
        return cursor;
    }


    /**
     * Checks if the READ permissions exist to the entry and to each attribute type and
     * value.
     *
     * @todo not sure if we should hide attribute types/values or throw an exception
     * instead.  I think we're going to have to use a filter to restrict the return
     * of attribute types and values instead of throwing an exception.  Lack of read
     * perms to attributes and their values results in their removal when returning
     * the entry.
     *
     * @param principal the user associated with the call
     * @param dn the name of the entry being looked up
     * @param entry the raw entry pulled from the nexus
     * @throws Exception if undlying access to the DIT fails
     */
    private void checkLookupAccess( LookupOperationContext lookupContext, Entry entry ) throws LdapException
    {
        Dn dn = lookupContext.getDn();

        // no permissions checks on the RootDSE
        if ( dn.isRootDse() )
        {
            return;
        }

        LdapPrincipal principal = lookupContext.getSession().getEffectivePrincipal();
        Dn userName = principal.getDn();
        Set<String> userGroups = groupCache.getGroups( userName.getNormName() );
        Collection<ACITuple> tuples = new HashSet<>();
        addPerscriptiveAciTuples( lookupContext, tuples, dn, entry );
        addEntryAciTuples( tuples, entry );
        addSubentryAciTuples( lookupContext, tuples, dn, entry );

        // check that we have read access to the entry
        AciContext aciContext = new AciContext( schemaManager, lookupContext );
        aciContext.setUserGroupNames( userGroups );
        aciContext.setUserDn( userName );
        aciContext.setAuthenticationLevel( principal.getAuthenticationLevel() );
        aciContext.setEntryDn( dn );
        aciContext.setMicroOperations( LOOKUP_PERMS );
        aciContext.setAciTuples( tuples );
        aciContext.setEntry( entry );

        engine.checkPermission( aciContext );

        // check that we have read access to every attribute type and value
        for ( Attribute attribute : entry )
        {

            for ( Value value : attribute )
            {
                AciContext valueAciContext = new AciContext( schemaManager, lookupContext );
                valueAciContext.setUserGroupNames( userGroups );
                valueAciContext.setUserDn( userName );
                valueAciContext.setAuthenticationLevel( principal.getAuthenticationLevel() );
                valueAciContext.setEntryDn( dn );
                valueAciContext.setAttributeType( attribute.getAttributeType() );
                valueAciContext.setAttrValue( value );
                valueAciContext.setMicroOperations( READ_PERMS );
                valueAciContext.setAciTuples( tuples );
                valueAciContext.setEntry( entry );

                engine.checkPermission( valueAciContext );
            }
        }
    }


    public final boolean isPrincipalAnAdministrator( Dn principalDn )
    {
        return groupCache.isPrincipalAnAdministrator( principalDn.getNormName() );
    }


    public void cacheNewGroup( String name, Entry entry ) throws LdapException
    {
        groupCache.groupAdded( name, entry );
    }


    private boolean filter( OperationContext opContext, Dn normName, Entry clonedEntry ) throws LdapException
    {
        /*
         * First call hasPermission() for entry level "Browse" and "ReturnDN" perm
         * tests.  If we hasPermission() returns false we immediately short the
         * process and return false.
         */

        LdapPrincipal principal = opContext.getSession().getEffectivePrincipal();
        Dn userDn = principal.getDn();
        Set<String> userGroups = groupCache.getGroups( userDn.getNormName() );
        Collection<ACITuple> tuples = new HashSet<>();
        addPerscriptiveAciTuples( opContext, tuples, normName, clonedEntry );
        addEntryAciTuples( tuples, ( ( ClonedServerEntry ) clonedEntry ).getOriginalEntry() );
        addSubentryAciTuples( opContext, tuples, normName, ( ( ClonedServerEntry ) clonedEntry ).getOriginalEntry() );

        AciContext aciContext = new AciContext( schemaManager, opContext );
        aciContext.setUserGroupNames( userGroups );
        aciContext.setUserDn( userDn );
        aciContext.setAuthenticationLevel( principal.getAuthenticationLevel() );
        aciContext.setEntryDn( normName );
        aciContext.setMicroOperations( SEARCH_ENTRY_PERMS );
        aciContext.setAciTuples( tuples );
        aciContext.setEntry( ( ( ClonedServerEntry ) clonedEntry ).getOriginalEntry() );

        if ( !engine.hasPermission( aciContext ) )
        {
            return false;
        }

        /*
         * For each attribute type we check if access is allowed to the type.  If not
         * the attribute is yanked out of the entry to be returned.  If permission is
         * allowed we move on to check if the values are allowed.  Values that are
         * not allowed are removed from the attribute.  If the attribute has no more
         * values remaining then the entire attribute is removed.
         */
        List<AttributeType> attributeToRemove = new ArrayList<>();

        for ( Attribute attribute : clonedEntry.getAttributes() )
        {
            // if attribute type scope access is not allowed then remove the attribute and continue
            AttributeType attributeType = attribute.getAttributeType();
            Attribute attr = clonedEntry.get( attributeType );

            aciContext = new AciContext( schemaManager, opContext );
            aciContext.setUserGroupNames( userGroups );
            aciContext.setUserDn( userDn );
            aciContext.setAuthenticationLevel( principal.getAuthenticationLevel() );
            aciContext.setEntryDn( normName );
            aciContext.setAttributeType( attributeType );
            aciContext.setMicroOperations( SEARCH_ATTRVAL_PERMS );
            aciContext.setAciTuples( tuples );
            aciContext.setEntry( clonedEntry );

            if ( !engine.hasPermission( aciContext ) )
            {
                attributeToRemove.add( attributeType );

                continue;
            }

            List<Value> valueToRemove = new ArrayList<>();

            // attribute type scope is ok now let's determine value level scope
            for ( Value value : attr )
            {
                aciContext = new AciContext( schemaManager, opContext );
                aciContext.setUserGroupNames( userGroups );
                aciContext.setUserDn( userDn );
                aciContext.setAuthenticationLevel( principal.getAuthenticationLevel() );
                aciContext.setEntryDn( normName );
                aciContext.setAttributeType( attr.getAttributeType() );
                aciContext.setAttrValue( value );
                aciContext.setMicroOperations( SEARCH_ATTRVAL_PERMS );
                aciContext.setAciTuples( tuples );
                aciContext.setEntry( clonedEntry );

                if ( !engine.hasPermission( aciContext ) )
                {
                    valueToRemove.add( value );
                }
            }

            for ( Value value : valueToRemove )
            {
                attr.remove( value );
            }

            if ( attr.size() == 0 )
            {
                attributeToRemove.add( attributeType );
            }
        }

        for ( AttributeType attributeType : attributeToRemove )
        {
            clonedEntry.removeAttributes( attributeType );
        }

        return true;
    }

    /**
     * WARNING: create one of these filters fresh every time for each new search.
     */
    private class AuthorizationFilter implements EntryFilter
    {
        /**
         * {@inheritDoc}
         */
        @Override
        public boolean accept( SearchOperationContext searchContext, Entry entry ) throws LdapException
        {
            if ( !entry.getDn().isSchemaAware() )
            {
                entry.setDn(  new Dn( schemaManager, entry.getDn() ) );
            }

            return filter( searchContext, entry.getDn(), entry );
        }


        /**
         * {@inheritDoc}
         */
        @Override
        public String toString( String tabs )
        {
            return tabs + "AuthorizationFilter";
        }
    }


    private boolean isTheAdministrator( Dn normalizedDn )
    {
        return normalizedDn.equals( ServerDNConstants.ADMIN_SYSTEM_DN_NORMALIZED );
    }
}
