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/18 23:03:38 UTC

svn commit: r326243 - in /directory/apacheds/trunk/core/src: main/java/org/apache/ldap/server/authz/ main/java/org/apache/ldap/server/partition/ test/org/apache/ldap/server/authz/

Author: akarasulu
Date: Tue Oct 18 14:03:32 2005
New Revision: 326243

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

 o moved collection for safe lookup bypasses into the DPNP so other 
   interceptors can utilize it: this is a common operation/bypass
 o uncommented and modified search tests for authorization rules which
   now seem to work like a champion although I still need more tests 
   like the following:
 
     * test the hiding of attributes 
     * test selective excusion of entries from search results (now we
       are only testing do we get all or not with ACI)
     * test the hiding of specific values of attributes 
     * test the use of both entry ACI and subentry ACI in combination
       with perscriptive ACI
     * test out the effects of denials in concert with grants
     * test out the effects of precidence


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/partition/DirectoryPartitionNexusProxy.java
    directory/apacheds/trunk/core/src/test/org/apache/ldap/server/authz/SearchAuthorizationTest.java

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=326243&r1=326242&r2=326243&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 Tue Oct 18 14:03:32 2005
@@ -144,7 +144,7 @@
         {
             Name parentDn = ( Name ) dn.clone();
             parentDn.remove( dn.size() - 1 );
-            entry = proxy.lookup( parentDn, LOOKUP_BYPASS );
+            entry = proxy.lookup( parentDn, DirectoryPartitionNexusProxy.LOOKUP_BYPASS );
         }
 
         Attribute subentries = entry.get( AC_SUBENTRY_ATTR );
@@ -219,7 +219,7 @@
         // will contain the subentryACI attributes that effect subentries
         Name parentDn = ( Name ) dn.clone();
         parentDn.remove( dn.size() - 1 );
-        Attributes administrativeEntry = proxy.lookup( parentDn, LOOKUP_BYPASS );
+        Attributes administrativeEntry = proxy.lookup( parentDn, DirectoryPartitionNexusProxy.LOOKUP_BYPASS );
         Attribute subentryAci = administrativeEntry.get( SUBENTRYACI_ATTR );
 
         if ( subentryAci == null )
@@ -334,7 +334,7 @@
         // Access the principal requesting the operation, and bypass checks if it is the admin
         Invocation invocation = InvocationStack.getInstance().peek();
         DirectoryPartitionNexusProxy proxy = invocation.getProxy();
-        Attributes entry = proxy.lookup( name, LOOKUP_BYPASS );
+        Attributes entry = proxy.lookup( name, DirectoryPartitionNexusProxy.LOOKUP_BYPASS );
         LdapPrincipal user = ( ( ServerContext ) invocation.getCaller() ).getPrincipal();
         if ( user.getName().equalsIgnoreCase( DirectoryPartitionNexus.ADMIN_PRINCIPAL ) || ! enabled )
         {
@@ -359,27 +359,12 @@
     }
 
 
-    private static final Collection LOOKUP_BYPASS;
-    static
-    {
-            Collection c = new HashSet();
-            c.add( "normalizationService" );
-            c.add( "authenticationService" );
-            c.add( "authorizationService" );
-            c.add( "oldAuthorizationService" );
-            c.add( "schemaService" );
-            c.add( "subentryService" );
-            c.add( "operationalAttributeService" );
-            c.add( "eventService" );
-            LOOKUP_BYPASS = Collections.unmodifiableCollection( c );
-    }
-
     public void modify( NextInterceptor next, Name name, int modOp, Attributes mods ) throws NamingException
     {
         // Access the principal requesting the operation, and bypass checks if it is the admin
         Invocation invocation = InvocationStack.getInstance().peek();
         DirectoryPartitionNexusProxy proxy = invocation.getProxy();
-        Attributes entry = proxy.lookup( name, LOOKUP_BYPASS );
+        Attributes entry = proxy.lookup( name, DirectoryPartitionNexusProxy.LOOKUP_BYPASS );
         LdapPrincipal user = ( ( ServerContext ) invocation.getCaller() ).getPrincipal();
         if ( user.getName().equalsIgnoreCase( DirectoryPartitionNexus.ADMIN_PRINCIPAL ) || ! enabled )
         {
@@ -436,7 +421,7 @@
         // Access the principal requesting the operation, and bypass checks if it is the admin
         Invocation invocation = InvocationStack.getInstance().peek();
         DirectoryPartitionNexusProxy proxy = invocation.getProxy();
-        Attributes entry = proxy.lookup( name, LOOKUP_BYPASS );
+        Attributes entry = proxy.lookup( name, DirectoryPartitionNexusProxy.LOOKUP_BYPASS );
         LdapPrincipal user = ( ( ServerContext ) invocation.getCaller() ).getPrincipal();
         if ( user.getName().equalsIgnoreCase( DirectoryPartitionNexus.ADMIN_PRINCIPAL ) || ! enabled )
         {
@@ -495,7 +480,7 @@
     {
         Invocation invocation = InvocationStack.getInstance().peek();
         DirectoryPartitionNexusProxy proxy = invocation.getProxy();
-        Attributes entry = proxy.lookup( name, LOOKUP_BYPASS );
+        Attributes entry = proxy.lookup( name, DirectoryPartitionNexusProxy.LOOKUP_BYPASS );
         LdapPrincipal user = ( ( ServerContext ) invocation.getCaller() ).getPrincipal();
 
         if ( user.getName().equalsIgnoreCase( DirectoryPartitionNexus.ADMIN_PRINCIPAL ) || ! enabled )
@@ -569,7 +554,7 @@
     {
         Invocation invocation = InvocationStack.getInstance().peek();
         DirectoryPartitionNexusProxy proxy = invocation.getProxy();
-        Attributes entry = proxy.lookup( dn, LOOKUP_BYPASS );
+        Attributes entry = proxy.lookup( dn, DirectoryPartitionNexusProxy.LOOKUP_BYPASS );
         LdapPrincipal user = ( ( ServerContext ) invocation.getCaller() ).getPrincipal();
 
         if ( user.getName().equalsIgnoreCase( DirectoryPartitionNexus.ADMIN_PRINCIPAL ) || ! enabled )
@@ -587,7 +572,7 @@
     {
         Invocation invocation = InvocationStack.getInstance().peek();
         DirectoryPartitionNexusProxy proxy = invocation.getProxy();
-        Attributes entry = proxy.lookup( name, LOOKUP_BYPASS );
+        Attributes entry = proxy.lookup( name, DirectoryPartitionNexusProxy.LOOKUP_BYPASS );
         LdapPrincipal user = ( ( ServerContext ) invocation.getCaller() ).getPrincipal();
 
         if ( user.getName().equalsIgnoreCase( DirectoryPartitionNexus.ADMIN_PRINCIPAL ) || ! enabled )
@@ -606,7 +591,7 @@
         // Access the principal requesting the operation, and bypass checks if it is the admin
         Invocation invocation = InvocationStack.getInstance().peek();
         DirectoryPartitionNexusProxy proxy = invocation.getProxy();
-        Attributes entry = proxy.lookup( name, LOOKUP_BYPASS );
+        Attributes entry = proxy.lookup( name, DirectoryPartitionNexusProxy.LOOKUP_BYPASS );
         LdapPrincipal user = ( ( ServerContext ) invocation.getCaller() ).getPrincipal();
         Name newName = ( Name ) name.clone();
         newName.remove( name.size() - 1 );
@@ -667,7 +652,7 @@
         // Access the principal requesting the operation, and bypass checks if it is the admin
         Invocation invocation = InvocationStack.getInstance().peek();
         DirectoryPartitionNexusProxy proxy = invocation.getProxy();
-        Attributes entry = proxy.lookup( oriChildName, LOOKUP_BYPASS );
+        Attributes entry = proxy.lookup( oriChildName, DirectoryPartitionNexusProxy.LOOKUP_BYPASS );
         LdapPrincipal user = ( ( ServerContext ) invocation.getCaller() ).getPrincipal();
         Name newName = ( Name ) newParentName.clone();
         newName.add( newRn );
@@ -737,7 +722,7 @@
         // Access the principal requesting the operation, and bypass checks if it is the admin
         Invocation invocation = InvocationStack.getInstance().peek();
         DirectoryPartitionNexusProxy proxy = invocation.getProxy();
-        Attributes entry = proxy.lookup( oriChildName, LOOKUP_BYPASS );
+        Attributes entry = proxy.lookup( oriChildName, DirectoryPartitionNexusProxy.LOOKUP_BYPASS );
         Name newName = ( Name ) newParentName.clone();
         newName.add( oriChildName.get( oriChildName.size() - 1 ) );
         LdapPrincipal user = ( ( ServerContext ) invocation.getCaller() ).getPrincipal();
@@ -810,7 +795,7 @@
         // Access the principal requesting the operation, and bypass checks if it is the admin
         Invocation invocation = InvocationStack.getInstance().peek();
         DirectoryPartitionNexusProxy proxy = invocation.getProxy();
-        Attributes entry = proxy.lookup( name, LOOKUP_BYPASS );
+        Attributes entry = proxy.lookup( name, DirectoryPartitionNexusProxy.LOOKUP_BYPASS );
         LdapPrincipal user = ( ( ServerContext ) invocation.getCaller() ).getPrincipal();
         if ( user.getName().equalsIgnoreCase( DirectoryPartitionNexus.ADMIN_PRINCIPAL ) || ! enabled )
         {
@@ -857,7 +842,7 @@
         * tests.  If we hasPermission() returns false we immediately short the
         * process and return false.
         */
-        Attributes entry = invocation.getProxy().lookup( normName, LOOKUP_BYPASS );
+        Attributes entry = invocation.getProxy().lookup( normName, DirectoryPartitionNexusProxy.LOOKUP_BYPASS );
         ServerLdapContext ctx = ( ServerLdapContext ) invocation.getCaller();
         Name userDn = ctx.getPrincipal().getJndiName();
         Set userGroups = groupCache.getGroups( userDn.toString() );
@@ -933,7 +918,8 @@
         }
 
 
-        public boolean accept( Invocation invocation, SearchResult result, SearchControls controls ) throws NamingException
+        public boolean accept( Invocation invocation, SearchResult result, SearchControls controls )
+                throws NamingException
         {
             Name normName = parser.parse( result.getName() );
 

Modified: directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/partition/DirectoryPartitionNexusProxy.java
URL: http://svn.apache.org/viewcvs/directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/partition/DirectoryPartitionNexusProxy.java?rev=326243&r1=326242&r2=326243&view=diff
==============================================================================
--- directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/partition/DirectoryPartitionNexusProxy.java (original)
+++ directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/partition/DirectoryPartitionNexusProxy.java Tue Oct 18 14:03:32 2005
@@ -17,10 +17,7 @@
 package org.apache.ldap.server.partition;
 
 
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Collection;
-import java.util.Collections;
+import java.util.*;
 
 import javax.naming.Context;
 import javax.naming.Name;
@@ -57,6 +54,8 @@
  */
 public class DirectoryPartitionNexusProxy extends DirectoryPartitionNexus
 {
+    /** safe to use set of bypass instructions to lookup raw entries */
+    public static final Collection LOOKUP_BYPASS;
     /** Bypass String to use when ALL interceptors should be skipped */
     public static final String BYPASS_ALL = "*";
     /** Bypass String to use when ALL interceptors should be skipped */
@@ -71,6 +70,22 @@
     private final Context caller;
     private final DirectoryService service;
     private final DirectoryServiceConfiguration configuration;
+
+
+    static
+    {
+        Collection c = new HashSet();
+        c.add( "normalizationService" );
+        c.add( "authenticationService" );
+        c.add( "authorizationService" );
+        c.add( "oldAuthorizationService" );
+        c.add( "schemaService" );
+        c.add( "subentryService" );
+        c.add( "operationalAttributeService" );
+        c.add( "eventService" );
+        LOOKUP_BYPASS = Collections.unmodifiableCollection( c );
+    }
+
 
     /**
      * Creates a new instance.

Modified: directory/apacheds/trunk/core/src/test/org/apache/ldap/server/authz/SearchAuthorizationTest.java
URL: http://svn.apache.org/viewcvs/directory/apacheds/trunk/core/src/test/org/apache/ldap/server/authz/SearchAuthorizationTest.java?rev=326243&r1=326242&r2=326243&view=diff
==============================================================================
--- directory/apacheds/trunk/core/src/test/org/apache/ldap/server/authz/SearchAuthorizationTest.java (original)
+++ directory/apacheds/trunk/core/src/test/org/apache/ldap/server/authz/SearchAuthorizationTest.java Tue Oct 18 14:03:32 2005
@@ -233,144 +233,144 @@
      */
     public void testAddSearchData() throws NamingException
     {
-//        Name base = addSearchData( new LdapName(), 3, 10 );
-//        SearchControls controls = new SearchControls();
-//        controls.setSearchScope( SearchControls.SUBTREE_SCOPE );
-//        NamingEnumeration results = sysRoot.search( base, "(objectClass=*)", controls );
-//        int counter = 0;
-//        while ( results.hasMore() )
-//        {
-//            results.next();
-//            counter++;
-//        }
-//
-//        assertEquals( 10, counter );
-//        recursivelyDelete( base );
-//        try { sysRoot.lookup( base ); fail(); } catch ( LdapNameNotFoundException e ) {}
+        Name base = addSearchData( new LdapName(), 3, 10 );
+        SearchControls controls = new SearchControls();
+        controls.setSearchScope( SearchControls.SUBTREE_SCOPE );
+        NamingEnumeration results = sysRoot.search( base, "(objectClass=*)", controls );
+        int counter = 0;
+        while ( results.hasMore() )
+        {
+            results.next();
+            counter++;
+        }
+
+        assertEquals( 10, counter );
+        recursivelyDelete( base );
+        try { sysRoot.lookup( base ); fail(); } catch ( LdapNameNotFoundException e ) {}
     }
 
 
-//    /**
-//     * Checks to make sure group membership based userClass works for add operations.
-//     *
-//     * @throws javax.naming.NamingException if the test encounters an error
-//     */
-//    public void testGrantAdministrators() throws NamingException
-//    {
-//        // create the non-admin user
-//        createUser( "billyd", "billyd" );
-//
-//        // try an add operation which should fail without any ACI
-//        assertFalse( checkCanSearchAs( "billyd", "billyd" ) );
-//
-//        // Gives grantAdd perm to all users in the Administrators group for
-//        // entries and all attribute types and values
-//        createAccessControlSubentry( "searchAdmin", "{ " +
-//                "identificationTag \"addAci\", " +
-//                "precedence 14, " +
-//                "authenticationLevel none, " +
-//                "itemOrUserFirst userFirst: { " +
-//                "userClasses { userGroup { \"cn=Administrators,ou=groups,ou=system\" } }, " +
-//                "userPermissions { { " +
-//                "protectedItems {entry, allUserAttributeTypesAndValues}, " +
-//                "grantsAndDenials { grantRead, grantReturnDN, grantBrowse } } } } }" );
-//
-//        // see if we can now add that test entry which we could not before
-//        // add op should still fail since billd is not in the admin group
-//        assertFalse( checkCanSearchAs( "billyd", "billyd" ) );
-//
-//        // now add billyd to the Administrator group and try again
-//        addUserToGroup( "billyd", "Administrators" );
-//
-//        // try an add operation which should succeed with ACI and group membership change
-//        assertTrue( checkCanSearchAs( "billyd", "billyd" ) );
-//    }
-//
-//
-//    /**
-//     * Checks to make sure name based userClass works for add operations.
-//     *
-//     * @throws javax.naming.NamingException if the test encounters an error
-//     */
-//    public void testGrantAddByName() throws NamingException
-//    {
-//        // create the non-admin user
-//        createUser( "billyd", "billyd" );
-//
-//        // try an add operation which should fail without any ACI
-//        assertFalse( checkCanSearchAs( "billyd", "billyd" ) );
-//
-//        // now add a subentry that enables user billyd to add an entry below ou=system
-//        createAccessControlSubentry( "billydAdd", "{ " +
-//                "identificationTag \"addAci\", " +
-//                "precedence 14, " +
-//                "authenticationLevel none, " +
-//                "itemOrUserFirst userFirst: { " +
-//                "userClasses { name { \"uid=billyd,ou=users,ou=system\" } }, " +
-//                "userPermissions { { " +
-//                "protectedItems {entry, allUserAttributeTypesAndValues}, " +
-//                "grantsAndDenials { grantAdd, grantBrowse } } } } }" );
-//
-//        // should work now that billyd is authorized by name
-//        assertTrue( checkCanSearchAs( "billyd", "billyd" ) );
-//    }
-//
-//
-//    /**
-//     * Checks to make sure subtree based userClass works for add operations.
-//     *
-//     * @throws javax.naming.NamingException if the test encounters an error
-//     */
-//    public void testGrantAddBySubtree() throws NamingException
-//    {
-//        // create the non-admin user
-//        createUser( "billyd", "billyd" );
-//
-//        // try an add operation which should fail without any ACI
-//        assertFalse( checkCanSearchAs( "billyd", "billyd" ) );
-//
-//        // now add a subentry that enables user billyd to add an entry below ou=system
-//        createAccessControlSubentry( "billyAddBySubtree", "{ " +
-//                "identificationTag \"addAci\", " +
-//                "precedence 14, " +
-//                "authenticationLevel none, " +
-//                "itemOrUserFirst userFirst: { " +
-//                "userClasses { subtree { { base \"ou=users,ou=system\" } } }, " +
-//                "userPermissions { { " +
-//                "protectedItems {entry, allUserAttributeTypesAndValues}, " +
-//                "grantsAndDenials { grantAdd, grantBrowse } } } } }" );
-//
-//        // should work now that billyd is authorized by the subtree userClass
-//        assertTrue( checkCanSearchAs( "billyd", "billyd" ) );
-//    }
-//
-//
-//    /**
-//     * Checks to make sure <b>allUsers</b> userClass works for add operations.
-//     *
-//     * @throws javax.naming.NamingException if the test encounters an error
-//     */
-//    public void testGrantAddAllUsers() throws NamingException
-//    {
-//        // create the non-admin user
-//        createUser( "billyd", "billyd" );
-//
-//        // try an add operation which should fail without any ACI
-//        assertFalse( checkCanSearchAs( "billyd", "billyd" ) );
-//
-//        // now add a subentry that enables anyone to add an entry below ou=system
-//        createAccessControlSubentry( "anybodyAdd", "{ " +
-//                "identificationTag \"addAci\", " +
-//                "precedence 14, " +
-//                "authenticationLevel none, " +
-//                "itemOrUserFirst userFirst: { " +
-//                "userClasses { allUsers }, " +
-//                "userPermissions { { " +
-//                "protectedItems {entry, allUserAttributeTypesAndValues}, " +
-//                "grantsAndDenials { grantAdd, grantBrowse } } } } }" );
-//
-//        // see if we can now add that test entry which we could not before
-//        // should work now with billyd now that all users are authorized
-//        assertTrue( checkCanSearchAs( "billyd", "billyd" ) );
-//    }
+    /**
+     * Checks to make sure group membership based userClass works for add operations.
+     *
+     * @throws javax.naming.NamingException if the test encounters an error
+     */
+    public void testGrantAdministrators() throws NamingException
+    {
+        // create the non-admin user
+        createUser( "billyd", "billyd" );
+
+        // try an add operation which should fail without any ACI
+        assertFalse( checkCanSearchAs( "billyd", "billyd" ) );
+
+        // Gives grantAdd perm to all users in the Administrators group for
+        // entries and all attribute types and values
+        createAccessControlSubentry( "searchAdmin", "{ " +
+                "identificationTag \"addAci\", " +
+                "precedence 14, " +
+                "authenticationLevel none, " +
+                "itemOrUserFirst userFirst: { " +
+                "userClasses { userGroup { \"cn=Administrators,ou=groups,ou=system\" } }, " +
+                "userPermissions { { " +
+                "protectedItems {entry, allUserAttributeTypesAndValues}, " +
+                "grantsAndDenials { grantRead, grantReturnDN, grantBrowse } } } } }" );
+
+        // see if we can now add that test entry which we could not before
+        // add op should still fail since billd is not in the admin group
+        assertFalse( checkCanSearchAs( "billyd", "billyd" ) );
+
+        // now add billyd to the Administrator group and try again
+        addUserToGroup( "billyd", "Administrators" );
+
+        // try an add operation which should succeed with ACI and group membership change
+        assertTrue( checkCanSearchAs( "billyd", "billyd" ) );
+    }
+
+
+    /**
+     * Checks to make sure name based userClass works for search operations.
+     *
+     * @throws javax.naming.NamingException if the test encounters an error
+     */
+    public void testGrantSearchByName() throws NamingException
+    {
+        // create the non-admin user
+        createUser( "billyd", "billyd" );
+
+        // try an add operation which should fail without any ACI
+        assertFalse( checkCanSearchAs( "billyd", "billyd" ) );
+
+        // now add a subentry that enables user billyd to add an entry below ou=system
+        createAccessControlSubentry( "billydAdd", "{ " +
+                "identificationTag \"addAci\", " +
+                "precedence 14, " +
+                "authenticationLevel none, " +
+                "itemOrUserFirst userFirst: { " +
+                "userClasses { name { \"uid=billyd,ou=users,ou=system\" } }, " +
+                "userPermissions { { " +
+                "protectedItems {entry, allUserAttributeTypesAndValues}, " +
+                "grantsAndDenials { grantRead, grantReturnDN, grantBrowse } } } } }" );
+
+        // should work now that billyd is authorized by name
+        assertTrue( checkCanSearchAs( "billyd", "billyd" ) );
+    }
+
+
+    /**
+     * Checks to make sure subtree based userClass works for search operations.
+     *
+     * @throws javax.naming.NamingException if the test encounters an error
+     */
+    public void testGrantSearchBySubtree() throws NamingException
+    {
+        // create the non-admin user
+        createUser( "billyd", "billyd" );
+
+        // try an add operation which should fail without any ACI
+        assertFalse( checkCanSearchAs( "billyd", "billyd" ) );
+
+        // now add a subentry that enables user billyd to add an entry below ou=system
+        createAccessControlSubentry( "billyAddBySubtree", "{ " +
+                "identificationTag \"addAci\", " +
+                "precedence 14, " +
+                "authenticationLevel none, " +
+                "itemOrUserFirst userFirst: { " +
+                "userClasses { subtree { { base \"ou=users,ou=system\" } } }, " +
+                "userPermissions { { " +
+                "protectedItems {entry, allUserAttributeTypesAndValues}, " +
+                "grantsAndDenials {  grantRead, grantReturnDN, grantBrowse } } } } }" );
+
+        // should work now that billyd is authorized by the subtree userClass
+        assertTrue( checkCanSearchAs( "billyd", "billyd" ) );
+    }
+
+
+    /**
+     * Checks to make sure <b>allUsers</b> userClass works for search operations.
+     *
+     * @throws javax.naming.NamingException if the test encounters an error
+     */
+    public void testGrantSearchAllUsers() throws NamingException
+    {
+        // create the non-admin user
+        createUser( "billyd", "billyd" );
+
+        // try an add operation which should fail without any ACI
+        assertFalse( checkCanSearchAs( "billyd", "billyd" ) );
+
+        // now add a subentry that enables anyone to add an entry below ou=system
+        createAccessControlSubentry( "anybodyAdd", "{ " +
+                "identificationTag \"addAci\", " +
+                "precedence 14, " +
+                "authenticationLevel none, " +
+                "itemOrUserFirst userFirst: { " +
+                "userClasses { allUsers }, " +
+                "userPermissions { { " +
+                "protectedItems {entry, allUserAttributeTypesAndValues}, " +
+                "grantsAndDenials { grantRead, grantReturnDN, grantBrowse } } } } }" );
+
+        // see if we can now add that test entry which we could not before
+        // should work now with billyd now that all users are authorized
+        assertTrue( checkCanSearchAs( "billyd", "billyd" ) );
+    }
 }