You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by ak...@apache.org on 2005/10/07 06:18:57 UTC

svn commit: r306997 - in /directory/apacheds/trunk: core/src/main/java/org/apache/ldap/server/authz/ core/src/main/java/org/apache/ldap/server/authz/support/ core/src/main/java/org/apache/ldap/server/configuration/ core/src/main/java/org/apache/ldap/se...

Author: akarasulu
Date: Thu Oct  6 21:18:44 2005
New Revision: 306997

URL: http://svn.apache.org/viewcvs?rev=306997&view=rev
Log:
changes ...

 o added new accessControlEnabled property to the startup configuration
   this property controls whether or not the authorization subsystem is
   enabled or not - by default it is disabled and must be turned on
 o made admin user bypass all permission checks
 o added entryACI and subentryACI to the apache schema
 o implemented and passed tests for authz with add ops .. still need more tests
 o fixed bug in ACDFEngine where on add ops entry lookups in database were 
   failing 
 o fixed bug in SubentryService where we were trying to clone null objects 
   and were getting a NPE
 o added public operation in SubentryService to determine the set of subentry
   operational attributes within an entry that is about to be added ... other
   services like authz cannot figure this out since they do not have access to
   the subtree cache.  This service must be offered to other services that need
   to determine if an entry to be added is included in the collections of 
   subentries.


Modified:
    directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/AuthorizationService.java
    directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/TupleCache.java
    directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/ACDFEngine.java
    directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/configuration/MutableStartupConfiguration.java
    directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/configuration/StartupConfiguration.java
    directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/subtree/SubentryService.java
    directory/apacheds/trunk/core/src/main/schema/apache.schema
    directory/apacheds/trunk/core/src/test/org/apache/ldap/server/authz/AuthorizationServiceAsAdminTest.java
    directory/apacheds/trunk/core/src/test/org/apache/ldap/server/authz/AuthorizationServiceAsNonAdminTest.java
    directory/apacheds/trunk/main/server.xml

Modified: directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/AuthorizationService.java
URL: http://svn.apache.org/viewcvs/directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/AuthorizationService.java?rev=306997&r1=306996&r2=306997&view=diff
==============================================================================
--- directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/AuthorizationService.java (original)
+++ directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/AuthorizationService.java Thu Oct  6 21:18:44 2005
@@ -19,6 +19,7 @@
 
 import org.apache.ldap.server.interceptor.BaseInterceptor;
 import org.apache.ldap.server.interceptor.NextInterceptor;
+import org.apache.ldap.server.interceptor.InterceptorChain;
 import org.apache.ldap.server.jndi.ContextFactoryConfiguration;
 import org.apache.ldap.server.jndi.ServerContext;
 import org.apache.ldap.server.configuration.InterceptorConfiguration;
@@ -26,7 +27,17 @@
 import org.apache.ldap.server.authz.support.ACDFEngine;
 import org.apache.ldap.server.invocation.InvocationStack;
 import org.apache.ldap.server.authn.LdapPrincipal;
+import org.apache.ldap.server.schema.ConcreteNameComponentNormalizer;
+import org.apache.ldap.server.subtree.SubentryService;
 import org.apache.ldap.common.filter.ExprNode;
+import org.apache.ldap.common.aci.MicroOperation;
+import org.apache.ldap.common.aci.ACIItemParser;
+import org.apache.ldap.common.aci.ACIItem;
+import org.apache.ldap.common.exception.LdapNamingException;
+import org.apache.ldap.common.message.ResultCodeEnum;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import javax.naming.Name;
 import javax.naming.NamingException;
@@ -34,8 +45,9 @@
 import javax.naming.directory.Attributes;
 import javax.naming.directory.ModificationItem;
 import javax.naming.directory.SearchControls;
-import java.util.Iterator;
-import java.util.Map;
+import javax.naming.directory.Attribute;
+import java.util.*;
+import java.text.ParseException;
 
 
 /**
@@ -46,16 +58,85 @@
  */
 public class AuthorizationService extends BaseInterceptor
 {
+    /** the logger for this class */
+    private static final Logger log = LoggerFactory.getLogger( AuthorizationService.class );
+
+    private static final String ENTRYACI_ATTR = "entryACI";
+    private static final String SUBENTRYACI_ATTR = "subentryACI";
+    private static final String AC_SUBENTRY_ATTR = "accessControlSubentries";
+
+    /** collection of MicroOperations for the add operation */
+    private static final Collection ADD_OPS;
+    /** collection of MicroOperations for the delete operation */
+    private static final Collection DELETE_OPS;
+    /** collection of MicroOperations for the compare operation */
+    private static final Collection COMPARE_OPS;
+    /** collection of MicroOperations for the search operation */
+    private static final Collection SEARCH_OPS;
+    /** collection of MicroOperations for the modify operation */
+    private static final Collection MODIFY_OPS;
+    /** collection of MicroOperations for the modifyRdn operation */
+    private static final Collection MODIFYRDN_OPS;
+    /** collection of MicroOperations for the browsing */
+    private static final Collection BROWSE_OPS;
+
+    static
+    {
+        Set ops = new HashSet();
+        ops.add( MicroOperation.ADD );
+        ADD_OPS = Collections.unmodifiableCollection( ops );
+
+        ops = new HashSet();
+        ops.add( MicroOperation.REMOVE );
+        DELETE_OPS = Collections.unmodifiableCollection( ops );
+
+        ops = new HashSet();
+        ops.add( MicroOperation.COMPARE );
+        COMPARE_OPS = Collections.unmodifiableCollection( ops );
+
+        ops = new HashSet();
+        ops.add( MicroOperation.RETURN_DN );
+        ops.add( MicroOperation.FILTER_MATCH );
+        ops.add( MicroOperation.READ );
+        SEARCH_OPS = Collections.unmodifiableCollection( ops );
+
+        ops = new HashSet();
+        ops.add( MicroOperation.MODIFY );
+        MODIFY_OPS = Collections.unmodifiableCollection( ops );
+
+        ops = new HashSet();
+        ops.add( MicroOperation.RENAME );
+        MODIFYRDN_OPS = Collections.unmodifiableCollection( ops );
+
+        ops = new HashSet();
+        ops.add( MicroOperation.BROWSE );
+        BROWSE_OPS = Collections.unmodifiableCollection( ops );
+    }
+
     /** the partition nexus */
     private ContextPartitionNexus nexus;
     /** 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;
+    /** interceptor chain */
+    private InterceptorChain chain;
+    /** whether or not this interceptor is activated */
+    private boolean enabled = false;
 
 
+    /**
+     * Initializes this interceptor based service by getting a handle on the nexus, setting up
+     * the tupe and group membership caches and the ACIItem parser and the ACDF engine.
+     *
+     * @param factoryCfg the ContextFactory configuration for the server
+     * @param cfg the interceptor configuration
+     * @throws NamingException if there are problems during initialization
+     */
     public void init( ContextFactoryConfiguration factoryCfg, InterceptorConfiguration cfg ) throws NamingException
     {
         super.init( factoryCfg, cfg );
@@ -63,44 +144,204 @@
         nexus = factoryCfg.getPartitionNexus();
         tupleCache = new TupleCache( factoryCfg );
         groupCache = new GroupCache( factoryCfg );
+        aciParser = new ACIItemParser( new ConcreteNameComponentNormalizer(
+                factoryCfg.getGlobalRegistries().getAttributeTypeRegistry() ) );
         engine = new ACDFEngine( factoryCfg.getGlobalRegistries().getOidRegistry(),
                 factoryCfg.getGlobalRegistries().getAttributeTypeRegistry() );
+        chain = factoryCfg.getInterceptorChain();
+        enabled = factoryCfg.getStartupConfiguration().isAccessControlEnabled();
+    }
+
+
+    /**
+     * 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 that access to is being controled
+     * @throws NamingException if there are problems accessing attribute values
+     */
+    private void addPerscriptiveAciTuples( Collection tuples, Name dn, Attributes entry ) throws NamingException
+    {
+        /*
+         * 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 ( entry.get( "objectClass" ).contains( "subentry" ) )
+        {
+            Name parentDn = ( Name ) dn.clone();
+            parentDn.remove( dn.size() - 1 );
+            entry = nexus.lookup( parentDn );
+        }
+
+        Attribute subentries = entry.get( AC_SUBENTRY_ATTR );
+        if ( subentries == null ) return;
+        for ( int ii = 0; ii < subentries.size(); ii++ )
+        {
+            String subentryDn = ( String ) subentries.get( ii );
+            tuples.addAll( tupleCache.getACITuples( subentryDn ) );
+        }
+    }
+
+
+    /**
+     * 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 NamingException if there are problems accessing attribute values
+     */
+    private void addEntryAciTuples( Collection tuples, Attributes entry ) throws NamingException
+    {
+        Attribute entryAci = entry.get( ENTRYACI_ATTR );
+        if ( entryAci == null ) return;
+
+        for ( int ii = 0; ii < entryAci.size(); ii++ )
+        {
+            String aciString = ( String ) entryAci.get( ii );
+            ACIItem item;
+
+            try
+            {
+                item = aciParser.parse( aciString );
+            }
+            catch ( ParseException e )
+            {
+                String msg = "failed to parse entryACI: " + aciString ;
+                log.error( msg, e );
+                throw new LdapNamingException( msg, ResultCodeEnum.OPERATIONSERROR );
+            }
+
+            tuples.add( 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 NamingException if there are problems accessing attribute values
+     */
+    private void addSubentryAciTuples( Collection tuples, Name dn, Attributes entry ) throws NamingException
+    {
+        // only perform this for subentries
+        if ( ! entry.get( "objectClass" ).contains( "subentry" ) ) return;
+
+        // get the parent or administrative entry for this subentry since it
+        // will contain the subentryACI attributes that effect subentries
+        Name parentDn = ( Name ) dn.clone();
+        parentDn.remove( dn.size() - 1 );
+        Attributes administrativeEntry = nexus.lookup( parentDn );
+        Attribute subentryAci = administrativeEntry.get( SUBENTRYACI_ATTR );
+
+        if ( subentryAci == null ) return;
+
+        for ( int ii = 0; ii < subentryAci.size(); ii++ )
+        {
+            String aciString = ( String ) subentryAci.get( ii );
+            ACIItem item;
+
+            try
+            {
+                item = aciParser.parse( aciString );
+            }
+            catch ( ParseException e )
+            {
+                String msg = "failed to parse subentryACI: " + aciString ;
+                log.error( msg, e );
+                throw new LdapNamingException( msg, ResultCodeEnum.OPERATIONSERROR );
+            }
+
+            tuples.add( 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.  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.
+     * 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.
      *
      * The union of ACITuples are fed into the engine along with other parameters
      * to decide where permission is granted or rejected for the specific operation.
+     * -------------------------------------------------------------------------------
      */
 
     public void add( NextInterceptor next, String upName, Name normName, Attributes entry ) throws NamingException
     {
+        // Access the principal requesting the operation, and bypass checks if it is the admin
+        LdapPrincipal user = ( ( ServerContext ) InvocationStack.getInstance().peek().getCaller() ).getPrincipal();
+        if ( user.getName().equalsIgnoreCase( ContextPartitionNexus.ADMIN_PRINCIPAL ) || ! enabled )
+        {
+            next.add( upName, normName, entry );
+            tupleCache.subentryAdded( upName, normName, entry );
+            groupCache.groupAdded( upName, normName, entry );
+            return;
+        }
+
+        // perform checks below here
+        SubentryService subentryService = ( SubentryService ) chain.get( "subentryService" );
+        Attributes subentryAttrs = subentryService.getSubentryAttributes( normName, entry );
+        NamingEnumeration attrList = entry.getAll();
+        while( attrList.hasMore() )
+        {
+            subentryAttrs.put( ( Attribute ) attrList.next() );
+        }
+
+        // Assemble all the information required to make an access control decision
+        Set userGroups = groupCache.getGroups( user.getName() );
+        Collection tuples = new HashSet();
+
+        // note that entryACI should not be considered in adds (it's a security breach)
+        addPerscriptiveAciTuples( tuples, normName, subentryAttrs );
+        addSubentryAciTuples( tuples, normName, subentryAttrs );
+        engine.checkPermission( next, userGroups, user.getJndiName(), user.getAuthenticationLevel(), normName, null,
+            null, ADD_OPS, tuples, subentryAttrs );
+
+        // if we've gotten this far then access is granted
         next.add( upName, normName, entry );
         tupleCache.subentryAdded( upName, normName, entry );
         groupCache.groupAdded( upName, normName, entry );
-
-        ServerContext ctx = ( ServerContext ) InvocationStack.getInstance().peek().getCaller();
-        LdapPrincipal user = ctx.getPrincipal();
-        Name userGroupName = null;
-
-//        engine.checkPermission( next, userGroupName, user.getName(), user.getAuthenticationLevel(), normName, null,
-//                null, ADD_OPS, aciTuples );
     }
 
 
     public void delete( NextInterceptor next, Name name ) throws NamingException
     {
         Attributes entry = nexus.lookup( name );
+//        ServerContext ctx = ( ServerContext ) InvocationStack.getInstance().peek().getCaller();
+//        LdapPrincipal user = ctx.getPrincipal();
+//        Set userGroups = groupCache.getGroups( user.getName() );
+//        Collection tuples = new HashSet();
+//        addPerscriptiveAciTuples( tuples, entry );
+//        addEntryAciTuples( tuples, entry );
+//        addSubentryAciTuples( tuples, entry );
+//
+//        engine.checkPermission( next, userGroups, user.getJndiName(), user.getAuthenticationLevel(), name, null,
+//                null, DELETE_OPS, tuples );
+
         next.delete( name );
         tupleCache.subentryDeleted( name, entry );
         groupCache.groupDeleted( name, entry );
@@ -110,6 +351,17 @@
     public void modify( NextInterceptor next, Name name, int modOp, Attributes mods ) throws NamingException
     {
         Attributes entry = nexus.lookup( name );
+//        ServerContext ctx = ( ServerContext ) InvocationStack.getInstance().peek().getCaller();
+//        LdapPrincipal user = ctx.getPrincipal();
+//        Set userGroups = groupCache.getGroups( user.getName() );
+//        Collection tuples = new HashSet();
+//        addPerscriptiveAciTuples( tuples, entry );
+//        addEntryAciTuples( tuples, entry );
+//        addSubentryAciTuples( tuples, entry );
+//
+//        engine.checkPermission( next, userGroups, user.getJndiName(), user.getAuthenticationLevel(), name, null,
+//                null, MODIFY_OPS, tuples );
+
         next.modify( name, modOp, mods );
         tupleCache.subentryModified( name, modOp, mods, entry );
         groupCache.groupModified( name, modOp, mods, entry );
@@ -119,6 +371,17 @@
     public void modify( NextInterceptor next, Name name, ModificationItem[] mods ) throws NamingException
     {
         Attributes entry = nexus.lookup( name );
+//        ServerContext ctx = ( ServerContext ) InvocationStack.getInstance().peek().getCaller();
+//        LdapPrincipal user = ctx.getPrincipal();
+//        Set userGroups = groupCache.getGroups( user.getName() );
+//        Collection tuples = new HashSet();
+//        addPerscriptiveAciTuples( tuples, entry );
+//        addEntryAciTuples( tuples, entry );
+//        addSubentryAciTuples( tuples, entry );
+//
+//        engine.checkPermission( next, userGroups, user.getJndiName(), user.getAuthenticationLevel(), name, null,
+//                null, MODIFY_OPS, tuples );
+
         next.modify( name, mods );
         tupleCache.subentryModified( name, mods, entry );
         groupCache.groupModified( name, mods, entry );
@@ -127,18 +390,54 @@
 
     public Attributes getRootDSE( NextInterceptor next ) throws NamingException
     {
-        return super.getRootDSE( next );
+        Attributes entry = super.getRootDSE( next );
+//        ServerContext ctx = ( ServerContext ) InvocationStack.getInstance().peek().getCaller();
+//        LdapPrincipal user = ctx.getPrincipal();
+//        Set userGroups = groupCache.getGroups( user.getName() );
+//        Collection tuples = new HashSet();
+//        addPerscriptiveAciTuples( tuples, entry );
+//        addEntryAciTuples( tuples, entry );
+//        addSubentryAciTuples( tuples, entry );
+//
+//        engine.checkPermission( next, userGroups, user.getJndiName(), user.getAuthenticationLevel(),
+//                new LdapName(), null, null, SEARCH_OPS, tuples );
+
+        return entry;
     }
 
 
     public boolean hasEntry( NextInterceptor next, Name name ) throws NamingException
     {
+//        Attributes entry = nexus.lookup( name );
+//        ServerContext ctx = ( ServerContext ) InvocationStack.getInstance().peek().getCaller();
+//        LdapPrincipal user = ctx.getPrincipal();
+//        Set userGroups = groupCache.getGroups( user.getName() );
+//        Collection tuples = new HashSet();
+//        addPerscriptiveAciTuples( tuples, entry );
+//        addEntryAciTuples( tuples, entry );
+//        addSubentryAciTuples( tuples, entry );
+//
+//        engine.checkPermission( next, userGroups, user.getJndiName(), user.getAuthenticationLevel(), name, null,
+//                null, BROWSE_OPS, tuples );
+
         return next.hasEntry( name );
     }
 
 
     public NamingEnumeration list( NextInterceptor next, Name base ) throws NamingException
     {
+//        Attributes entry = nexus.lookup( base );
+//        ServerContext ctx = ( ServerContext ) InvocationStack.getInstance().peek().getCaller();
+//        LdapPrincipal user = ctx.getPrincipal();
+//        Set userGroups = groupCache.getGroups( user.getName() );
+//        Collection tuples = new HashSet();
+//        addPerscriptiveAciTuples( tuples, entry );
+//        addEntryAciTuples( tuples, entry );
+//        addSubentryAciTuples( tuples, entry );
+//
+//        engine.checkPermission( next, userGroups, user.getJndiName(), user.getAuthenticationLevel(), base, null,
+//                null, SEARCH_OPS, tuples );
+
         return super.list( next, base );
     }
 
@@ -163,6 +462,18 @@
 
     public void modifyRn( NextInterceptor next, Name name, String newRn, boolean deleteOldRn ) throws NamingException
     {
+//        Attributes entry = nexus.lookup( name );
+//        ServerContext ctx = ( ServerContext ) InvocationStack.getInstance().peek().getCaller();
+//        LdapPrincipal user = ctx.getPrincipal();
+//        Set userGroups = groupCache.getGroups( user.getName() );
+//        Collection tuples = new HashSet();
+//        addPerscriptiveAciTuples( tuples, entry );
+//        addEntryAciTuples( tuples, entry );
+//        addSubentryAciTuples( tuples, entry );
+//
+//        engine.checkPermission( next, userGroups, user.getJndiName(), user.getAuthenticationLevel(), name, null,
+//                null, MODIFYRDN_OPS, tuples );
+
         super.modifyRn( next, name, newRn, deleteOldRn );
     }
 
@@ -170,12 +481,36 @@
     public void move( NextInterceptor next, Name oriChildName, Name newParentName, String newRn, boolean deleteOldRn )
             throws NamingException
     {
+//        Attributes entry = nexus.lookup( oriChildName );
+//        ServerContext ctx = ( ServerContext ) InvocationStack.getInstance().peek().getCaller();
+//        LdapPrincipal user = ctx.getPrincipal();
+//        Set userGroups = groupCache.getGroups( user.getName() );
+//        Collection tuples = new HashSet();
+//        addPerscriptiveAciTuples( tuples, entry );
+//        addEntryAciTuples( tuples, entry );
+//        addSubentryAciTuples( tuples, entry );
+//
+//        engine.checkPermission( next, userGroups, user.getJndiName(), user.getAuthenticationLevel(), oriChildName, null,
+//                null, MODIFYRDN_OPS, tuples );
+
         super.move( next, oriChildName, newParentName, newRn, deleteOldRn );
     }
 
 
     public void move( NextInterceptor next, Name oriChildName, Name newParentName ) throws NamingException
     {
+//        Attributes entry = nexus.lookup( oriChildName );
+//        ServerContext ctx = ( ServerContext ) InvocationStack.getInstance().peek().getCaller();
+//        LdapPrincipal user = ctx.getPrincipal();
+//        Set userGroups = groupCache.getGroups( user.getName() );
+//        Collection tuples = new HashSet();
+//        addPerscriptiveAciTuples( tuples, entry );
+//        addEntryAciTuples( tuples, entry );
+//        addSubentryAciTuples( tuples, entry );
+//
+//        engine.checkPermission( next, userGroups, user.getJndiName(), user.getAuthenticationLevel(), oriChildName, null,
+//                null, MODIFYRDN_OPS, tuples );
+//
         super.move( next, oriChildName, newParentName );
     }
 
@@ -183,6 +518,36 @@
     public NamingEnumeration search( NextInterceptor next, Name base, Map env, ExprNode filter,
                                      SearchControls searchCtls ) throws NamingException
     {
+//        Attributes entry = nexus.lookup( base );
+//        ServerContext ctx = ( ServerContext ) InvocationStack.getInstance().peek().getCaller();
+//        LdapPrincipal user = ctx.getPrincipal();
+//        Set userGroups = groupCache.getGroups( user.getName() );
+//        Collection tuples = new HashSet();
+//        addPerscriptiveAciTuples( tuples, entry );
+//        addEntryAciTuples( tuples, entry );
+//        addSubentryAciTuples( tuples, entry );
+//
+//        engine.checkPermission( next, userGroups, user.getJndiName(), user.getAuthenticationLevel(), base, null,
+//                null, SEARCH_OPS, tuples );
+
         return super.search( next, base, env, filter, searchCtls );
+    }
+
+
+    public boolean compare( NextInterceptor next, Name name, String oid, Object value ) throws NamingException
+    {
+//        Attributes entry = nexus.lookup( name );
+//        ServerContext ctx = ( ServerContext ) InvocationStack.getInstance().peek().getCaller();
+//        LdapPrincipal user = ctx.getPrincipal();
+//        Set userGroups = groupCache.getGroups( user.getName() );
+//        Collection tuples = new HashSet();
+//        addPerscriptiveAciTuples( tuples, entry );
+//        addEntryAciTuples( tuples, entry );
+//        addSubentryAciTuples( tuples, entry );
+//
+//        engine.checkPermission( next, userGroups, user.getJndiName(), user.getAuthenticationLevel(), name, null,
+//                null, COMPARE_OPS, tuples );
+
+        return super.compare(next, name, oid, value);
     }
 }

Modified: directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/TupleCache.java
URL: http://svn.apache.org/viewcvs/directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/TupleCache.java?rev=306997&r1=306996&r2=306997&view=diff
==============================================================================
--- directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/TupleCache.java (original)
+++ directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/TupleCache.java Thu Oct  6 21:18:44 2005
@@ -172,7 +172,7 @@
 
 
     public void subentryDeleted( Name normName, Attributes entry ) throws NamingException
-    {
+    {                                                                                      
         if ( ! hasPrescriptiveACI( entry ) )
         {
             return;

Modified: directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/ACDFEngine.java
URL: http://svn.apache.org/viewcvs/directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/ACDFEngine.java?rev=306997&r1=306996&r2=306997&view=diff
==============================================================================
--- directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/ACDFEngine.java (original)
+++ directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/ACDFEngine.java Thu Oct  6 21:18:44 2005
@@ -116,13 +116,13 @@
             NextInterceptor next,
             Collection userGroupNames, Name username, AuthenticationLevel authenticationLevel,
             Name entryName, String attrId, Object attrValue,
-            Collection microOperations, Collection aciTuples ) throws NamingException 
+            Collection microOperations, Collection aciTuples, Attributes entry ) throws NamingException
     {
         if( !hasPermission(
                 next,
                 userGroupNames, username, authenticationLevel,
                 entryName, attrId, attrValue,
-                microOperations, aciTuples ) )
+                microOperations, aciTuples, entry ) )
         {
             throw new LdapNoPermissionException();
         }
@@ -148,7 +148,7 @@
             NextInterceptor next, 
             Collection userGroupNames, Name userName, AuthenticationLevel authenticationLevel,
             Name entryName, String attrId, Object attrValue,
-            Collection microOperations, Collection aciTuples ) throws NamingException
+            Collection microOperations, Collection aciTuples, Attributes entry ) throws NamingException
     {
         if( entryName == null )
         {
@@ -156,8 +156,7 @@
         }
         
         Attributes userEntry = next.lookup( userName );
-        Attributes entry = next.lookup( entryName );
-        
+
         // Determine the scope of the requested operation.
         OperationScope scope;
         if( attrId == null )

Modified: directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/configuration/MutableStartupConfiguration.java
URL: http://svn.apache.org/viewcvs/directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/configuration/MutableStartupConfiguration.java?rev=306997&r1=306996&r2=306997&view=diff
==============================================================================
--- directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/configuration/MutableStartupConfiguration.java (original)
+++ directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/configuration/MutableStartupConfiguration.java Thu Oct  6 21:18:44 2005
@@ -70,6 +70,11 @@
         super.setContextPartitionConfigurations( contextParitionConfigurations );
     }
 
+    public void setAccessControlEnabled( boolean isAccessControlEnabled )
+    {
+        super.setAccessControlEnabled( isAccessControlEnabled );
+    }
+
     public void setAllowAnonymousAccess( boolean enableAnonymousAccess )
     {
         super.setAllowAnonymousAccess( enableAnonymousAccess );

Modified: directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/configuration/StartupConfiguration.java
URL: http://svn.apache.org/viewcvs/directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/configuration/StartupConfiguration.java?rev=306997&r1=306996&r2=306997&view=diff
==============================================================================
--- directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/configuration/StartupConfiguration.java (original)
+++ directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/configuration/StartupConfiguration.java Thu Oct  6 21:18:44 2005
@@ -54,6 +54,7 @@
 
     private File workingDirectory = new File( "server-work" );
     private boolean allowAnonymousAccess = true; // allow by default
+    private boolean accessControlEnabled = false; // turn off by default
     private Set authenticatorConfigurations; // Set<AuthenticatorConfiguration>
     private List interceptorConfigurations; // Set<InterceptorConfiguration>
     
@@ -266,6 +267,22 @@
         }
         
         this.contextPartitionConfigurations = newSet;
+    }
+
+    /**
+     * Returns <tt>true</tt> if access control checks are enbaled.
+     */
+    public boolean isAccessControlEnabled()
+    {
+        return accessControlEnabled;
+    }
+
+    /**
+     * Sets whether to enable basic access control checks or not
+     */
+    protected void setAccessControlEnabled( boolean isAccessControlEnabled )
+    {
+        this.accessControlEnabled = isAccessControlEnabled;
     }
 
     /**

Modified: directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/subtree/SubentryService.java
URL: http://svn.apache.org/viewcvs/directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/subtree/SubentryService.java?rev=306997&r1=306996&r2=306997&view=diff
==============================================================================
--- directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/subtree/SubentryService.java (original)
+++ directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/subtree/SubentryService.java Thu Oct  6 21:18:44 2005
@@ -102,11 +102,7 @@
                 return true;
             }
 
-            if ( objectClasses.contains( SUBENTRY_OBJECTCLASS ) || objectClasses.contains( SUBENTRY_OBJECTCLASS_OID ) )
-            {
-                return false;
-            }
-            return true;
+            return !( objectClasses.contains(SUBENTRY_OBJECTCLASS) || objectClasses.contains(SUBENTRY_OBJECTCLASS_OID) );
         }
     };
 
@@ -150,7 +146,7 @@
                 Attributes subentry = result.getAttributes();
                 String dn = result.getName();
                 String subtree = ( String ) subentry.get( "subtreeSpecification" ).get();
-                SubtreeSpecification ss = null;
+                SubtreeSpecification ss;
 
                 try
                 {
@@ -219,7 +215,7 @@
      */
     private boolean isSubentryVisible( LdapContext ctx ) throws NamingException
     {
-        Control[] reqControls = ( Control[] ) ctx.getRequestControls();
+        Control[] reqControls = ctx.getRequestControls();
 
         if ( reqControls == null || reqControls.length <= 0 )
         {
@@ -246,6 +242,93 @@
     // -----------------------------------------------------------------------
 
 
+    /**
+     * Evaluates the set of subentry subtrees upon an entry and returns the
+     * operational subentry attributes that will be added to the entry if
+     * added at the dn specified.
+     *
+     * @param dn the normalized distinguished name of the entry
+     * @param entryAttrs the entry attributes are generated for
+     * @return the set of subentry op attrs for an entry
+     * @throws NamingException if there are problems accessing entry information
+     */
+    public Attributes getSubentryAttributes( Name dn, Attributes entryAttrs ) throws NamingException
+    {
+        Attributes subentryAttrs = new LockableAttributesImpl();
+        Attribute objectClasses = entryAttrs.get( "objectClass" );
+        Iterator list = subtrees.keySet().iterator();
+        while ( list.hasNext() )
+        {
+            String subentryDnStr = ( String ) list.next();
+            Name subentryDn = new LdapName( subentryDnStr );
+            Name apDn = ( Name ) subentryDn.clone();
+            apDn.remove( apDn.size() - 1 );
+            SubtreeSpecification ss = ( SubtreeSpecification ) subtrees.get( subentryDn );
+
+            if ( evaluator.evaluate( ss, apDn, dn, objectClasses ) )
+            {
+                Attribute administrativeRole = nexus.lookup( apDn ).get( "administrativeRole" );
+                NamingEnumeration roles = administrativeRole.getAll();
+                while ( roles.hasMore() )
+                {
+                    Attribute operational;
+                    String role = ( String ) roles.next();
+
+                    if ( role.equalsIgnoreCase( AUTONOUMOUS_AREA ) )
+                    {
+                        operational = subentryAttrs.get( AUTONOUMOUS_AREA_SUBENTRY );
+                        if ( operational == null )
+                        {
+                            operational = new LockableAttributeImpl( AUTONOUMOUS_AREA_SUBENTRY );
+                            subentryAttrs.put( operational );
+                        }
+                    }
+                    else if ( role.equalsIgnoreCase( AC_AREA ) || role.equalsIgnoreCase( AC_INNERAREA ) )
+                    {
+                        operational = subentryAttrs.get( AC_SUBENTRY );
+                        if ( operational == null )
+                        {
+                            operational = new LockableAttributeImpl( AC_SUBENTRY );
+                            subentryAttrs.put( operational );
+                        }
+                    }
+                    else if ( role.equalsIgnoreCase( SCHEMA_AREA ) )
+                    {
+                        operational = subentryAttrs.get( SCHEMA_AREA_SUBENTRY );
+                        if ( operational == null )
+                        {
+                            operational = new LockableAttributeImpl( SCHEMA_AREA_SUBENTRY );
+                            subentryAttrs.put( operational );
+                        }
+                    }
+                    else if ( role.equalsIgnoreCase( COLLECTIVE_AREA ) ||
+                              role.equalsIgnoreCase( COLLECTIVE_INNERAREA ) )
+                    {
+                        operational = subentryAttrs.get( COLLECTIVE_ATTRIBUTE_SUBENTRIES );
+                        if ( operational == null )
+                        {
+                            operational = new LockableAttributeImpl( COLLECTIVE_ATTRIBUTE_SUBENTRIES );
+                            subentryAttrs.put( operational );
+                        }
+                    }
+                    else
+                    {
+                        throw new LdapInvalidAttributeValueException( "Encountered invalid administrativeRole '"
+                                + role + "' in administrative point of subentry " + subentryDnStr + ". The values of this attribute"
+                                + " are constrained to autonomousArea, accessControlSpecificArea, accessControlInnerArea,"
+                                + " subschemaAdminSpecificArea, collectiveAttributeSpecificArea, and"
+                                + " collectiveAttributeInnerArea.", ResultCodeEnum.CONSTRAINTVIOLATION );
+                    }
+
+                    operational.add( subentryDn.toString() );
+                }
+            }
+        }
+
+        return subentryAttrs;
+    }
+
+
     public void add( NextInterceptor next, String upName, Name normName, Attributes entry ) throws NamingException
     {
         Attribute objectClasses = entry.get( "objectClass" );
@@ -285,7 +368,7 @@
              * ----------------------------------------------------------------
              */
             String subtree = ( String ) entry.get( "subtreeSpecification" ).get();
-            SubtreeSpecification ss = null;
+            SubtreeSpecification ss;
             try
             {
                 ss = ssParser.parse( subtree );
@@ -345,7 +428,7 @@
                     NamingEnumeration roles = administrativeRole.getAll();
                     while ( roles.hasMore() )
                     {
-                        Attribute operational = null;
+                        Attribute operational;
                         String role = ( String ) roles.next();
 
                         if ( role.equalsIgnoreCase( AUTONOUMOUS_AREA ) )
@@ -359,7 +442,7 @@
                         }
                         else if ( role.equalsIgnoreCase( AC_AREA ) || role.equalsIgnoreCase( AC_INNERAREA ) )
                         {
-                            operational = ( Attribute ) entry.get( AC_SUBENTRY ).clone();
+                            operational = ( Attribute ) entry.get( AC_SUBENTRY );
                             if ( operational == null )
                             {
                                 operational = new LockableAttributeImpl( AC_SUBENTRY );
@@ -368,7 +451,7 @@
                         }
                         else if ( role.equalsIgnoreCase( SCHEMA_AREA ) )
                         {
-                            operational = ( Attribute ) entry.get( SCHEMA_AREA_SUBENTRY ).clone();
+                            operational = ( Attribute ) entry.get( SCHEMA_AREA_SUBENTRY );
                             if ( operational == null )
                             {
                                 operational = new LockableAttributeImpl( SCHEMA_AREA_SUBENTRY );
@@ -378,7 +461,7 @@
                         else if ( role.equalsIgnoreCase( COLLECTIVE_AREA ) ||
                                   role.equalsIgnoreCase( COLLECTIVE_INNERAREA ) )
                         {
-                            operational = ( Attribute ) entry.get( COLLECTIVE_ATTRIBUTE_SUBENTRIES ).clone();
+                            operational = ( Attribute ) entry.get( COLLECTIVE_ATTRIBUTE_SUBENTRIES );
                             if ( operational == null )
                             {
                                 operational = new LockableAttributeImpl( COLLECTIVE_ATTRIBUTE_SUBENTRIES );
@@ -777,7 +860,7 @@
         if ( objectClasses.contains( "subentry" ) && mods.get( "subtreeSpecification" ) != null )
         {
             SubtreeSpecification ssOld = ( SubtreeSpecification ) subtrees.remove( name.toString() );
-            SubtreeSpecification ssNew = null;
+            SubtreeSpecification ssNew;
 
             try
             {
@@ -850,7 +933,7 @@
 
         for ( int ii = 0; ii < mods.length; ii++ )
         {
-            if ( ( ( String ) mods[ii].getAttribute().getID() ).equalsIgnoreCase( "subtreeSpecification" ) )
+            if ( "subtreeSpecification".equalsIgnoreCase( mods[ii].getAttribute().getID() ) )
             {
                 isSubtreeSpecificationModification = true;
                 subtreeMod = mods[ii];
@@ -860,7 +943,7 @@
         if ( objectClasses.contains( "subentry" ) && isSubtreeSpecificationModification )
         {
             SubtreeSpecification ssOld = ( SubtreeSpecification ) subtrees.remove( name.toString() );
-            SubtreeSpecification ssNew = null;
+            SubtreeSpecification ssNew;
 
             try
             {
@@ -936,7 +1019,7 @@
         NamingEnumeration roles = administrativeRole.getAll();
         while ( roles.hasMore() )
         {
-            Attribute operational = null;
+            Attribute operational;
             String role = ( String ) roles.next();
 
             if ( role.equalsIgnoreCase( AUTONOUMOUS_AREA ) )

Modified: directory/apacheds/trunk/core/src/main/schema/apache.schema
URL: http://svn.apache.org/viewcvs/directory/apacheds/trunk/core/src/main/schema/apache.schema?rev=306997&r1=306996&r2=306997&view=diff
==============================================================================
--- directory/apacheds/trunk/core/src/main/schema/apache.schema (original)
+++ directory/apacheds/trunk/core/src/main/schema/apache.schema Thu Oct  6 21:18:44 2005
@@ -112,6 +112,18 @@
   SYNTAX 1.3.6.1.4.1.1466.115.121.1.1
   USAGE directoryOperation )
 
+attributetype ( 1.2.6.1.4.1.18060.1.1.1.3.13 NAME 'entryACI'
+  DESC 'Access control information that applies to a single entry'
+  EQUALITY directoryStringFirstComponentMatch
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.1
+  USAGE directoryOperation )
+
+attributetype ( 1.2.6.1.4.1.18060.1.1.1.3.13 NAME 'subentryACI'
+  DESC 'Access control information that applies to a single subentry'
+  EQUALITY directoryStringFirstComponentMatch
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.1
+  USAGE directoryOperation )
+
 objectclass ( 1.2.6.1.4.1.18060.1.1.1.4.2
     NAME 'accessControlSubentry'
     AUXILIARY 

Modified: directory/apacheds/trunk/core/src/test/org/apache/ldap/server/authz/AuthorizationServiceAsAdminTest.java
URL: http://svn.apache.org/viewcvs/directory/apacheds/trunk/core/src/test/org/apache/ldap/server/authz/AuthorizationServiceAsAdminTest.java?rev=306997&r1=306996&r2=306997&view=diff
==============================================================================
--- directory/apacheds/trunk/core/src/test/org/apache/ldap/server/authz/AuthorizationServiceAsAdminTest.java (original)
+++ directory/apacheds/trunk/core/src/test/org/apache/ldap/server/authz/AuthorizationServiceAsAdminTest.java Thu Oct  6 21:18:44 2005
@@ -21,14 +21,12 @@
 
 import javax.naming.NamingEnumeration;
 import javax.naming.NamingException;
-import javax.naming.directory.Attributes;
-import javax.naming.directory.DirContext;
-import javax.naming.directory.SearchControls;
-import javax.naming.directory.SearchResult;
+import javax.naming.directory.*;
 
 import org.apache.ldap.common.exception.LdapNoPermissionException;
 import org.apache.ldap.common.message.LockableAttributesImpl;
 import org.apache.ldap.server.AbstractAdminTestCase;
+import org.apache.ldap.server.subtree.SubentryService;
 
 
 /**
@@ -101,28 +99,20 @@
     public void testSearchSubtreeByAdmin() throws NamingException
     {
         SearchControls controls = new SearchControls();
-
         controls.setSearchScope( SearchControls.SUBTREE_SCOPE );
-
         HashSet set = new HashSet();
-
         NamingEnumeration list = sysRoot.search( "", "(objectClass=*)", controls );
 
         while ( list.hasMore() )
         {
             SearchResult result = ( SearchResult ) list.next();
-
             set.add( result.getName() );
         }
 
         assertTrue( set.contains( "ou=system" ) );
-
         assertTrue( set.contains( "ou=groups,ou=system" ) );
-
         assertTrue( set.contains( "ou=users,ou=system" ) );
-
         assertTrue( set.contains( "uid=akarasulu,ou=users,ou=system" ) );
-
         assertTrue( set.contains( "uid=admin,ou=system" ) );
     }
 }

Modified: directory/apacheds/trunk/core/src/test/org/apache/ldap/server/authz/AuthorizationServiceAsNonAdminTest.java
URL: http://svn.apache.org/viewcvs/directory/apacheds/trunk/core/src/test/org/apache/ldap/server/authz/AuthorizationServiceAsNonAdminTest.java?rev=306997&r1=306996&r2=306997&view=diff
==============================================================================
--- directory/apacheds/trunk/core/src/test/org/apache/ldap/server/authz/AuthorizationServiceAsNonAdminTest.java (original)
+++ directory/apacheds/trunk/core/src/test/org/apache/ldap/server/authz/AuthorizationServiceAsNonAdminTest.java Thu Oct  6 21:18:44 2005
@@ -18,17 +18,16 @@
 
 
 import java.util.HashSet;
+import java.util.Hashtable;
 
 import javax.naming.NamingEnumeration;
 import javax.naming.NamingException;
-import javax.naming.directory.Attributes;
-import javax.naming.directory.DirContext;
-import javax.naming.directory.SearchControls;
-import javax.naming.directory.SearchResult;
+import javax.naming.directory.*;
 
 import org.apache.ldap.common.exception.LdapNoPermissionException;
 import org.apache.ldap.common.message.LockableAttributesImpl;
 import org.apache.ldap.server.AbstractNonAdminTestCase;
+import org.apache.ldap.server.subtree.SubentryService;
 
 
 /**
@@ -40,6 +39,13 @@
  */
 public class AuthorizationServiceAsNonAdminTest extends AbstractNonAdminTestCase
 {
+    public AuthorizationServiceAsNonAdminTest()
+    {
+        super();
+        super.configuration.setAccessControlEnabled( true );
+    }
+
+
     /**
      * Makes sure a non-admin user cannot delete the admin account.
      *
@@ -106,8 +112,7 @@
         controls.setSearchScope( SearchControls.SUBTREE_SCOPE );
 
         HashSet set = new HashSet();
-        NamingEnumeration list = sysRoot.search( "",
-                "(objectClass=*)", controls );
+        NamingEnumeration list = sysRoot.search( "", "(objectClass=*)", controls );
         while ( list.hasMore() )
         {
             SearchResult result = ( SearchResult ) list.next();
@@ -120,5 +125,67 @@
         assertTrue( set.contains( "ou=users,ou=system" ) );
         assertFalse( set.contains( "uid=akarasulu,ou=users,ou=system" ) );
         assertFalse( set.contains( "uid=admin,ou=system" ) );
+    }
+
+
+    private DirContext getAdminContext() throws NamingException
+    {
+        Hashtable env = ( Hashtable ) ( ( Hashtable ) sysRoot.getEnvironment() ).clone();
+        env.put( DirContext.PROVIDER_URL, "ou=system" );
+        env.put( DirContext.SECURITY_AUTHENTICATION, "simple" );
+        env.put( DirContext.SECURITY_PRINCIPAL, "uid=admin,ou=system" );
+        env.put( DirContext.SECURITY_CREDENTIALS, "secret" );
+        return new InitialDirContext( env );
+    }
+
+
+    public void testGrantAddAllUsers() throws NamingException
+    {
+        DirContext adminCtx = getAdminContext();
+
+        // modify ou=system to be an AP for an A/C AA
+        Attributes changes = new BasicAttributes( "administrativeRole", SubentryService.AC_AREA, true );
+        adminCtx.modifyAttributes( "", DirContext.ADD_ATTRIBUTE, changes );
+
+        // try an add operation which should fail without any ACI
+        Attributes testEntry = new BasicAttributes( "ou", "testou", true );
+        Attribute objectClass = new BasicAttribute( "objectClass" );
+        testEntry.put( objectClass );
+        objectClass.add( "top" );
+        objectClass.add( "organizationalUnit" );
+
+        try
+        {
+            sysRoot.createSubcontext( "ou=testou", testEntry );
+            fail( "should never get here due to a permission exception" );
+        }
+        catch ( LdapNoPermissionException e ) {}
+
+        // now add a subentry that enables anyone to add an entry below ou=system
+        Attributes subentry = new BasicAttributes( "cn", "anybodyAdd", true );
+        objectClass = new BasicAttribute( "objectClass" );
+        subentry.put( objectClass );
+        objectClass.add( "top" );
+        objectClass.add( "subentry" );
+        objectClass.add( "accessControlSubentry" );
+        subentry.put( "subtreeSpecification", "{}" );
+        subentry.put( "prescriptiveACI", "{ " +
+                "identificationTag \"addAci\", " +
+                "precedence 14, " +
+                "authenticationLevel none, " +
+                "itemOrUserFirst userFirst: { " +
+                "userClasses { allUsers }, " +
+                "userPermissions { { " +
+                "protectedItems {entry}, " +
+                "grantsAndDenials { grantAdd } } } } }" );
+        adminCtx.createSubcontext( "cn=anybodyAdd", subentry );
+
+        // see if we can now add that test entry which we could not before
+        testEntry = new BasicAttributes( "ou", "testou", true );
+        objectClass = new BasicAttribute( "objectClass" );
+        testEntry.put( objectClass );
+        objectClass.add( "top" );
+        objectClass.add( "organizationalUnit" );
+        sysRoot.createSubcontext( "ou=testou", testEntry );
     }
 }

Modified: directory/apacheds/trunk/main/server.xml
URL: http://svn.apache.org/viewcvs/directory/apacheds/trunk/main/server.xml?rev=306997&r1=306996&r2=306997&view=diff
==============================================================================
--- directory/apacheds/trunk/main/server.xml (original)
+++ directory/apacheds/trunk/main/server.xml Thu Oct  6 21:18:44 2005
@@ -20,6 +20,7 @@
   <bean id="configuration" class="org.apache.ldap.server.configuration.MutableServerStartupConfiguration">
     <property name="workingDirectory"><value>apache.org</value></property>
     <property name="allowAnonymousAccess"><value>false</value></property>
+    <property name="accessControlEnabled"><value>false</value></property>
     <property name="ldapPort"><value>10389</value></property>
     <property name="contextPartitionConfigurations">
       <set>