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/19 08:20:36 UTC
svn commit: r326410 - in /directory/apacheds/trunk/core/src:
main/java/org/apache/ldap/server/authz/
main/java/org/apache/ldap/server/jndi/ main/schema/
test/org/apache/ldap/server/authz/
Author: akarasulu
Date: Tue Oct 18 23:20:28 2005
New Revision: 326410
URL: http://svn.apache.org/viewcvs?rev=326410&view=rev
Log:
changes ...
o added more test cases to search tests
o added more abstract test functions for entry and subentry ACI
o fixed bug in schema where entryACI and subentryACI overwrote one another
o fixed bug in processing of entry and subentry ACI
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/jndi/ServerDirContext.java
directory/apacheds/trunk/core/src/main/schema/apache.schema
directory/apacheds/trunk/core/src/test/org/apache/ldap/server/authz/AbstractAuthorizationTest.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=326410&r1=326409&r2=326410&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 23:20:28 2005
@@ -192,7 +192,7 @@
throw new LdapNamingException( msg, ResultCodeEnum.OPERATIONSERROR );
}
- tuples.add( item.toTuples() );
+ tuples.addAll( item.toTuples() );
}
}
@@ -243,7 +243,7 @@
throw new LdapNamingException( msg, ResultCodeEnum.OPERATIONSERROR );
}
- tuples.add( item.toTuples() );
+ tuples.addAll( item.toTuples() );
}
}
@@ -865,11 +865,12 @@
* not allowed are removed from the attribute. If the attribute has no more
* values remaining then the entire attribute is removed.
*/
- NamingEnumeration attributeList = result.getAttributes().getAll();
- while ( attributeList.hasMore() )
+ NamingEnumeration idList = result.getAttributes().getIDs();
+ while ( idList.hasMore() )
{
// if attribute type scope access is not allowed then remove the attribute and continue
- Attribute attr = ( Attribute ) attributeList.next();
+ String id = ( String ) idList.next();
+ Attribute attr = result.getAttributes().get( id );
if ( ! engine.hasPermission( invocation.getProxy(), userGroups, userDn,
ctx.getPrincipal().getAuthenticationLevel(),
normName, attr.getID(), null, SEARCH_ATTRVAL_PERMS, tuples, entry ) )
Modified: directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/jndi/ServerDirContext.java
URL: http://svn.apache.org/viewcvs/directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/jndi/ServerDirContext.java?rev=326410&r1=326409&r2=326410&view=diff
==============================================================================
--- directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/jndi/ServerDirContext.java (original)
+++ directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/jndi/ServerDirContext.java Tue Oct 18 23:20:28 2005
@@ -505,12 +505,9 @@
* Go through the set of attributes using each attribute value pair as
* an attribute value assertion within one big AND filter expression.
*/
- Attribute attr = null;
-
- SimpleNode node = null;
-
+ Attribute attr;
+ SimpleNode node;
BranchNode filter = new BranchNode( BranchNode.AND );
-
NamingEnumeration list = matchingAttributes.getAll();
// Loop through each attribute value pair
@@ -588,7 +585,7 @@
public NamingEnumeration search( Name name, String filter, SearchControls cons )
throws NamingException
{
- ExprNode filterNode = null;
+ ExprNode filterNode;
LdapName target = buildTarget( name );
@@ -695,7 +692,7 @@
NamingListener namingListener )
throws NamingException
{
- ExprNode filter = null;
+ ExprNode filter;
try
{
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=326410&r1=326409&r2=326410&view=diff
==============================================================================
--- directory/apacheds/trunk/core/src/main/schema/apache.schema (original)
+++ directory/apacheds/trunk/core/src/main/schema/apache.schema Tue Oct 18 23:20:28 2005
@@ -118,7 +118,7 @@
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'
+attributetype ( 1.2.6.1.4.1.18060.1.1.1.3.14 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
Modified: directory/apacheds/trunk/core/src/test/org/apache/ldap/server/authz/AbstractAuthorizationTest.java
URL: http://svn.apache.org/viewcvs/directory/apacheds/trunk/core/src/test/org/apache/ldap/server/authz/AbstractAuthorizationTest.java?rev=326410&r1=326409&r2=326410&view=diff
==============================================================================
--- directory/apacheds/trunk/core/src/test/org/apache/ldap/server/authz/AbstractAuthorizationTest.java (original)
+++ directory/apacheds/trunk/core/src/test/org/apache/ldap/server/authz/AbstractAuthorizationTest.java Tue Oct 18 23:20:28 2005
@@ -241,6 +241,21 @@
*/
public void createAccessControlSubentry( String cn, String aciItem ) throws NamingException
{
+ createAccessControlSubentry( cn, "{}", aciItem );
+ }
+
+
+ /**
+ * Creates an access control subentry under ou=system whose subtree covers
+ * the entire naming context.
+ *
+ * @param cn the common name and rdn for the subentry
+ * @param subtree the subtreeSpecification for the subentry
+ * @param aciItem the prescriptive ACI attribute value
+ * @throws NamingException if there is a problem creating the subentry
+ */
+ public void createAccessControlSubentry( String cn, String subtree, String aciItem ) throws NamingException
+ {
DirContext adminCtx = getContextAsAdmin();
// modify ou=system to be an AP for an A/C AA if it is not already
@@ -259,8 +274,42 @@
objectClass.add( "top" );
objectClass.add( "subentry" );
objectClass.add( "accessControlSubentry" );
- subentry.put( "subtreeSpecification", "{}" );
+ subentry.put( "subtreeSpecification", subtree );
subentry.put( "prescriptiveACI", aciItem );
adminCtx.createSubcontext( "cn=" + cn, subentry );
+ }
+
+
+ /**
+ * Adds and entryACI attribute to an entry specified by a relative name
+ * with respect to ou=system
+ *
+ * @param rdn a name relative to ou=system
+ * @param aciItem the entryACI attribute value
+ * @throws NamingException if there is a problem adding the attribute
+ */
+ public void addEntryACI( Name rdn, String aciItem ) throws NamingException
+ {
+ DirContext adminCtx = getContextAsAdmin();
+
+ // modify the entry relative to ou=system to include the aciItem
+ Attributes changes = new BasicAttributes( "entryACI", aciItem, true );
+ adminCtx.modifyAttributes( rdn, DirContext.ADD_ATTRIBUTE, changes );
+ }
+
+
+ /**
+ * Adds and subentryACI attribute to ou=system
+ *
+ * @param aciItem the subentryACI attribute value
+ * @throws NamingException if there is a problem adding the attribute
+ */
+ public void addSubentryACI( String aciItem ) throws NamingException
+ {
+ DirContext adminCtx = getContextAsAdmin();
+
+ // modify the entry relative to ou=system to include the aciItem
+ Attributes changes = new BasicAttributes( "subentryACI", aciItem, true );
+ adminCtx.modifyAttributes( "", DirContext.ADD_ATTRIBUTE, changes );
}
}
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=326410&r1=326409&r2=326410&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 23:20:28 2005
@@ -27,6 +27,9 @@
import javax.naming.Name;
import javax.naming.NamingEnumeration;
import javax.naming.directory.*;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Iterator;
/**
@@ -39,6 +42,13 @@
public class SearchAuthorizationTest extends AbstractAuthorizationTest
{
/**
+ * The search results of tests are added to this map via put (<String, SearchResult>)
+ * the map is also cleared before each search test. This allows further inspections
+ * of the results for more specific test cases.
+ */
+ private Map results = new HashMap();
+
+ /**
* Generates a set of simple organizationalUnit entries where the
* ou of the entry returned is the index of the entry in the array.
*
@@ -55,7 +65,11 @@
oc.add( "top" );
oc.add( "organizationalUnit" );
attributes[ii].put( oc );
- attributes[ii].put( "ou", String.valueOf( count ) );
+ Attribute ou = new LockableAttributeImpl( "ou" );
+ ou.add( String.valueOf( ii ) );
+ ou.add( "testEntry" );
+ attributes[ii].put( ou );
+ attributes[ii].put( "telephoneNumber", String.valueOf( count ) );
}
return attributes;
@@ -203,12 +217,60 @@
Name userDn = new LdapName( "uid="+uid+",ou=users,ou=system" );
try
{
+ results.clear();
DirContext userCtx = getContextAs( userDn, password );
NamingEnumeration list = userCtx.search( base, filter, cons );
int counter = 0;
while ( list.hasMore() )
{
- list.next();
+ SearchResult result = ( SearchResult ) list.next();
+ results.put( result.getName(), result );
+ counter++;
+ }
+ return counter == resultSetSz;
+ }
+ catch ( LdapNoPermissionException e )
+ {
+ return false;
+ }
+ finally
+ {
+ recursivelyDelete( base );
+ }
+ }
+
+
+ /**
+ * Adds an entryACI to specified entry below ou=system and runs a search. Then it
+ * checks to see the result size is correct.
+ *
+ * @param uid the uid RDN attribute value for the user under ou=users,ou=system
+ * @param password the password of the user
+ * @return true if the search succeeds as expected, false otherwise
+ * @throws NamingException if there are problems conducting the search
+ */
+ private boolean checkSearchAsWithEntryACI( String uid, String password, SearchControls cons, Name rdn,
+ String aci, int resultSetSz )
+ throws NamingException
+ {
+ if ( cons == null )
+ {
+ cons = new SearchControls();
+ }
+
+ Name base = addSearchData( new LdapName(), 3, 10 );
+ addEntryACI( rdn, aci );
+ Name userDn = new LdapName( "uid="+uid+",ou=users,ou=system" );
+ try
+ {
+ results.clear();
+ DirContext userCtx = getContextAs( userDn, password );
+ NamingEnumeration list = userCtx.search( base, "(objectClass=*)", cons );
+ int counter = 0;
+ while ( list.hasMore() )
+ {
+ SearchResult result = ( SearchResult ) list.next();
+ results.put( result.getName(), result );
counter++;
}
return counter == resultSetSz;
@@ -250,6 +312,11 @@
}
+ // -----------------------------------------------------------------------
+ // All or nothing search ACI rule tests
+ // -----------------------------------------------------------------------
+
+
/**
* Checks to make sure group membership based userClass works for add operations.
*
@@ -263,10 +330,10 @@
// 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
+ // Gives search perms to all users in the Administrators group for
// entries and all attribute types and values
createAccessControlSubentry( "searchAdmin", "{ " +
- "identificationTag \"addAci\", " +
+ "identificationTag \"searchAci\", " +
"precedence 14, " +
"authenticationLevel none, " +
"itemOrUserFirst userFirst: { " +
@@ -301,8 +368,8 @@
assertFalse( checkCanSearchAs( "billyd", "billyd" ) );
// now add a subentry that enables user billyd to add an entry below ou=system
- createAccessControlSubentry( "billydAdd", "{ " +
- "identificationTag \"addAci\", " +
+ createAccessControlSubentry( "billydSearch", "{ " +
+ "identificationTag \"searchAci\", " +
"precedence 14, " +
"authenticationLevel none, " +
"itemOrUserFirst userFirst: { " +
@@ -330,8 +397,8 @@
assertFalse( checkCanSearchAs( "billyd", "billyd" ) );
// now add a subentry that enables user billyd to add an entry below ou=system
- createAccessControlSubentry( "billyAddBySubtree", "{ " +
- "identificationTag \"addAci\", " +
+ createAccessControlSubentry( "billySearchBySubtree", "{ " +
+ "identificationTag \"searchAci\", " +
"precedence 14, " +
"authenticationLevel none, " +
"itemOrUserFirst userFirst: { " +
@@ -355,12 +422,53 @@
// create the non-admin user
createUser( "billyd", "billyd" );
- // try an add operation which should fail without any ACI
+ // try an search operation which should fail without any ACI
assertFalse( checkCanSearchAs( "billyd", "billyd" ) );
+ // now add a subentry that enables anyone to search an entry below ou=system
+ createAccessControlSubentry( "anybodySearch", "{ " +
+ "identificationTag \"searchAci\", " +
+ "precedence 14, " +
+ "authenticationLevel none, " +
+ "itemOrUserFirst userFirst: { " +
+ "userClasses { allUsers }, " +
+ "userPermissions { { " +
+ "protectedItems {entry, allUserAttributeTypesAndValues}, " +
+ "grantsAndDenials { grantRead, grantReturnDN, grantBrowse } } } } }" );
+
+ // see if we can now search that tree which we could not before
+ // should work now with billyd now that all users are authorized
+ assertTrue( checkCanSearchAs( "billyd", "billyd" ) );
+ }
+
+
+ // -----------------------------------------------------------------------
+ //
+ // -----------------------------------------------------------------------
+
+
+ /**
+ * Checks to make sure search does not return entries not assigned the
+ * perscriptiveACI and that it does not fail with an exception.
+ *
+ * @throws javax.naming.NamingException if the test encounters an error
+ */
+ public void testSelectiveGrantsAllUsers() throws NamingException
+ {
+ // create the non-admin user
+ createUser( "billyd", "billyd" );
+
+ // try an add operation which should fail without any ACI
+ SearchControls cons = new SearchControls();
+ cons.setSearchScope( SearchControls.SUBTREE_SCOPE );
+ assertFalse( checkCanSearchAs( "billyd", "billyd", cons, 4 ) );
+
// now add a subentry that enables anyone to add an entry below ou=system
- createAccessControlSubentry( "anybodyAdd", "{ " +
- "identificationTag \"addAci\", " +
+ // down two more rdns for DNs of a max size of 3
+ createAccessControlSubentry( "anybodySearch",
+ "{ maximum 2 }",
+ "{ " +
+ "identificationTag \"searchAci\", " +
"precedence 14, " +
"authenticationLevel none, " +
"itemOrUserFirst userFirst: { " +
@@ -371,6 +479,224 @@
// 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" ) );
+ assertTrue( checkCanSearchAs( "billyd", "billyd", cons, 4 ) );
+ }
+
+
+ /**
+ * Checks to make sure attributeTypes are not present when permissions are
+ * not given for reading them and their values.
+ *
+ * @throws javax.naming.NamingException if the test encounters an error
+ */
+ public void testHidingAttributes() throws NamingException
+ {
+ // create the non-admin user
+ createUser( "billyd", "billyd" );
+
+ // try an add operation which should fail without any ACI
+ SearchControls cons = new SearchControls();
+ cons.setSearchScope( SearchControls.SUBTREE_SCOPE );
+ assertFalse( checkCanSearchAs( "billyd", "billyd", cons, 4 ) );
+
+ // now add a subentry that enables anyone to search an entry below ou=system
+ // down two more rdns for DNs of a max size of 3. It only grants access to
+ // the ou and objectClass attributes however.
+ createAccessControlSubentry( "excluseTelephoneNumber",
+ "{ maximum 2 }",
+ "{ " +
+ "identificationTag \"searchAci\", " +
+ "precedence 14, " +
+ "authenticationLevel none, " +
+ "itemOrUserFirst userFirst: { " +
+ "userClasses { allUsers }, " +
+ "userPermissions { { " +
+ "protectedItems {entry, allAttributeValues { ou, objectClass } }, " +
+ "grantsAndDenials { grantRead, grantReturnDN, grantBrowse } } } } }" );
+
+ // see if we can now add that search and find 4 entries
+ assertTrue( checkCanSearchAs( "billyd", "billyd", cons, 4 ) );
+
+ // check to make sure the telephoneNumber attribute is not present in results
+ Iterator list = results.values().iterator();
+ while ( list.hasNext() )
+ {
+ SearchResult result = ( SearchResult ) list.next();
+ assertNull( result.getAttributes().get( "telephoneNumber" ) );
+ }
+
+ // delete the subentry to test more general rule's inclusion of telephoneNumber
+ deleteAccessControlSubentry( "excluseTelephoneNumber" );
+
+ // now add a subentry that enables anyone to search an entry below ou=system
+ // down two more rdns for DNs of a max size of 3. This time we should be able
+ // to see the telephoneNumber attribute
+ createAccessControlSubentry( "includeAllAttributeTypesAndValues",
+ "{ maximum 2 }",
+ "{ " +
+ "identificationTag \"searchAci\", " +
+ "precedence 14, " +
+ "authenticationLevel none, " +
+ "itemOrUserFirst userFirst: { " +
+ "userClasses { allUsers }, " +
+ "userPermissions { { " +
+ "protectedItems {entry, allUserAttributeTypesAndValues }, " +
+ "grantsAndDenials { grantRead, grantReturnDN, grantBrowse } } } } }" );
+
+ // again we should find four entries
+ assertTrue( checkCanSearchAs( "billyd", "billyd", cons, 4 ) );
+
+ // check now to make sure the telephoneNumber attribute is present in results
+ list = results.values().iterator();
+ while ( list.hasNext() )
+ {
+ SearchResult result = ( SearchResult ) list.next();
+ assertNotNull( result.getAttributes().get( "telephoneNumber" ) );
+ }
+ }
+
+
+// /**
+// * Checks to make sure specific attribute values are not present when
+// * read permission is denied.
+// *
+// * @throws javax.naming.NamingException if the test encounters an error
+// */
+// public void testHidingAttributeValues() throws NamingException
+// {
+// // create the non-admin user
+// createUser( "billyd", "billyd" );
+//
+// // try an add operation which should fail without any ACI
+// assertFalse( checkCanSearchAs( "billyd", "billyd", 3 ) );
+//
+// // now add a subentry that enables anyone to search an entry below ou=system
+// // down two more rdns for DNs of a max size of 3. It only grants access to
+// // the ou and objectClass attributes however.
+// createAccessControlSubentry( "excluseOUValue",
+// "{ maximum 2 }",
+// "{ " +
+// "identificationTag \"searchAci\", " +
+// "precedence 14, " +
+// "authenticationLevel none, " +
+// "itemOrUserFirst userFirst: { " +
+// "userClasses { allUsers }, " +
+// "userPermissions { { " +
+// "protectedItems {entry, attributeType { ou }, allAttributeValues { objectClass }, attributeValue { ou=0, ou=1, ou=2 } }, " +
+// "grantsAndDenials { grantRead, grantReturnDN, grantBrowse } } } } }" );
+//
+// // see if we can now add that search and find 4 entries
+// assertTrue( checkCanSearchAs( "billyd", "billyd", 3 ) );
+//
+// // check to make sure the ou attribute value "testEntry" is not present in results
+// Iterator list = results.values().iterator();
+// while ( list.hasNext() )
+// {
+// SearchResult result = ( SearchResult ) list.next();
+// assertFalse( result.getAttributes().get( "ou" ).contains( "testEntry" ) );
+// }
+//
+// // delete the subentry to test more general rule's inclusion of all values
+// deleteAccessControlSubentry( "excluseOUValue" );
+//
+// // now add a subentry that enables anyone to search an entry below ou=system
+// // down two more rdns for DNs of a max size of 3. This time we should be able
+// // to see the telephoneNumber attribute
+// createAccessControlSubentry( "includeAllAttributeTypesAndValues",
+// "{ maximum 2 }",
+// "{ " +
+// "identificationTag \"searchAci\", " +
+// "precedence 14, " +
+// "authenticationLevel none, " +
+// "itemOrUserFirst userFirst: { " +
+// "userClasses { allUsers }, " +
+// "userPermissions { { " +
+// "protectedItems {entry, allUserAttributeTypesAndValues }, " +
+// "grantsAndDenials { grantRead, grantReturnDN, grantBrowse } } } } }" );
+//
+// // again we should find four entries
+// assertTrue( checkCanSearchAs( "billyd", "billyd", 3 ) );
+//
+// // check now to make sure the telephoneNumber attribute is present in results
+// list = results.values().iterator();
+// while ( list.hasNext() )
+// {
+// SearchResult result = ( SearchResult ) list.next();
+// assertTrue( result.getAttributes().get( "ou" ).contains( "testEntry" ) );
+// }
+// }
+//
+//
+ /**
+ * Adds a perscriptiveACI to allow search, tests for success, then adds entryACI
+ * to deny read, browse and returnDN to a specific entry and checks to make sure
+ * that entry cannot be accessed via search as a specific user.
+ *
+ * @throws NamingException if the test is broken
+ */
+ public void testPerscriptiveGrantWithEntryDenial() throws NamingException
+ {
+ // create the non-admin user
+ createUser( "billyd", "billyd" );
+
+ // now add an entryACI denies browse, read and returnDN to a specific entry
+ String aci = "{ " +
+ "identificationTag \"denyAci\", " +
+ "precedence 14, " +
+ "authenticationLevel none, " +
+ "itemOrUserFirst userFirst: { " +
+ "userClasses { allUsers }, " +
+ "userPermissions { { " +
+ "protectedItems {entry, allUserAttributeTypesAndValues}, " +
+ "grantsAndDenials { denyRead, denyReturnDN, denyBrowse } } } } }";
+
+ // try a search operation which should fail without any prescriptive ACI
+ SearchControls cons = new SearchControls();
+ cons.setSearchScope( SearchControls.SUBTREE_SCOPE );
+ LdapName rdn = new LdapName( "ou=tests" );
+ assertFalse( checkSearchAsWithEntryACI( "billyd", "billyd", cons, rdn, aci, 9 ) );
+
+ // now add a subentry that enables anyone to search below ou=system
+ createAccessControlSubentry( "anybodySearch", "{ " +
+ "identificationTag \"searchAci\", " +
+ "precedence 14, " +
+ "authenticationLevel none, " +
+ "itemOrUserFirst userFirst: { " +
+ "userClasses { allUsers }, " +
+ "userPermissions { { " +
+ "protectedItems {entry, allUserAttributeTypesAndValues}, " +
+ "grantsAndDenials { grantRead, grantReturnDN, grantBrowse } } } } }" );
+
+ // see if we can now search the tree which we could not before
+ // should work with billyd now that all users are authorized
+ // we should also see the entry we are about to deny access to
+ assertTrue( checkSearchAsWithEntryACI( "billyd", "billyd", cons, rdn, aci, 9 ) );
+ assertNull( results.get( "ou=tests,ou=system" ) );
+
+ // try without the entry ACI .. just perscriptive and see ou=tests,ou=system
+ assertTrue( checkCanSearchAs( "billyd", "billyd", cons, 10 ) );
+ assertNotNull( results.get( "ou=tests,ou=system" ) );
}
+
+
+// public boolean checkSubentryAccessAs( String username, String password, Name rdn )
+//
+//
+// public void testSubentryAccess() throws NamingException
+// {
+// // create the non-admin user
+// createUser( "billyd", "billyd" );
+//
+// // now add a subentry that enables anyone to search below ou=system
+// createAccessControlSubentry( "anybodySearch", "{ " +
+// "identificationTag \"searchAci\", " +
+// "precedence 14, " +
+// "authenticationLevel none, " +
+// "itemOrUserFirst userFirst: { " +
+// "userClasses { allUsers }, " +
+// "userPermissions { { " +
+// "protectedItems {entry, allUserAttributeTypesAndValues}, " +
+// "grantsAndDenials { grantRead, grantReturnDN, grantBrowse } } } } }" );
+//
+// }
}