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/14 07:31:45 UTC
svn commit: r321015 - in /directory/apacheds/trunk/core/src:
main/java/org/apache/ldap/server/authz/ test/org/apache/ldap/server/authz/
Author: akarasulu
Date: Thu Oct 13 22:31:38 2005
New Revision: 321015
URL: http://svn.apache.org/viewcvs?rev=321015&view=rev
Log:
changes ...
o Added guards to hasEntry and lookup operations in Authz interceptor
o With guard on hasEntry requiring browse grants we had to add this
to the ACIItems of all tests - cannot get initial context to ou=system
otherwise.
o With new guards on lookup() and hasEntry() we cannot use the NonAdmin
version of the AbstractTest case. Cannot get initial context as non-admin
user during test setup without ACI addition. So now we derive from the
topmost base class.
o Added some tests for the compare() operation
Added:
directory/apacheds/trunk/core/src/test/org/apache/ldap/server/authz/CompareAuthorizationTest.java (with props)
Modified:
directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/AuthorizationService.java
directory/apacheds/trunk/core/src/test/org/apache/ldap/server/authz/AbstractAuthorizationTest.java
directory/apacheds/trunk/core/src/test/org/apache/ldap/server/authz/AddAuthorizationTest.java
directory/apacheds/trunk/core/src/test/org/apache/ldap/server/authz/DeleteAuthorizationTest.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=321015&r1=321014&r2=321015&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 13 22:31:38 2005
@@ -432,17 +432,23 @@
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 );
+ Attributes entry = nexus.lookup( name );
+ LdapPrincipal user = ( ( ServerContext ) InvocationStack.getInstance().peek().getCaller() ).getPrincipal();
+
+ if ( user.getName().equalsIgnoreCase( DirectoryPartitionNexus.ADMIN_PRINCIPAL ) || ! enabled )
+ {
+ return next.hasEntry( name );
+ }
+
+ Set userGroups = groupCache.getGroups( user.getName() );
+ Collection tuples = new HashSet();
+ addPerscriptiveAciTuples( tuples, name, entry );
+ addEntryAciTuples( tuples, entry );
+ addSubentryAciTuples( tuples, name, entry );
+
+ // check that we have browse access to the entry
+ engine.checkPermission( next, userGroups, user.getJndiName(), user.getAuthenticationLevel(), name, null,
+ null, Collections.singleton( MicroOperation.BROWSE ), tuples, entry );
return next.hasEntry( name );
}
@@ -472,15 +478,79 @@
}
+ /**
+ * Checks if the READ permissions exist to the entry and to each attribute type and
+ * value.
+ *
+ * @todo not sure if we should hide attribute types/values or throw an exception
+ * instead. I think we're going to have to use a filter to restrict the return
+ * of attribute types and values instead of throwing an exception. Lack of read
+ * perms to attributes and their values results in their removal when returning
+ * the entry.
+ *
+ * @param next the next interceptor to call in the chain
+ * @param user the user associated with the call
+ * @param dn the name of the entry being looked up
+ * @param entry the raw entry pulled from the nexus
+ * @throws NamingException
+ */
+ private void checkLookupAccess( NextInterceptor next, LdapPrincipal user, Name dn, Attributes entry )
+ throws NamingException
+ {
+ Set userGroups = groupCache.getGroups( user.getName() );
+ Collection tuples = new HashSet();
+ addPerscriptiveAciTuples( tuples, dn, entry );
+ addEntryAciTuples( tuples, entry );
+ addSubentryAciTuples( tuples, dn, entry );
+
+ // check that we have read access to the entry
+ engine.checkPermission( next, userGroups, user.getJndiName(), user.getAuthenticationLevel(), dn, null,
+ null, Collections.singleton( MicroOperation.READ ), tuples, entry );
+
+ // check that we have read access to every attribute type and value
+ Collection perms = Collections.singleton( MicroOperation.READ );
+ NamingEnumeration attributeList = entry.getAll();
+ while ( attributeList.hasMore() )
+ {
+ Attribute attr = ( Attribute ) attributeList.next();
+ for ( int ii = 0; ii < attr.size(); ii++ )
+ {
+ engine.checkPermission( next, userGroups, user.getJndiName(), user.getAuthenticationLevel(), dn,
+ attr.getID(), attr.get( ii ), perms, tuples, entry );
+ }
+ }
+ }
+
+
public Attributes lookup( NextInterceptor next, Name dn, String[] attrIds ) throws NamingException
{
- return super.lookup( next, dn, attrIds );
+ Attributes entry = nexus.lookup( dn, attrIds );
+ LdapPrincipal user = ( ( ServerContext ) InvocationStack.getInstance().peek().getCaller() ).getPrincipal();
+
+ if ( user.getName().equalsIgnoreCase( DirectoryPartitionNexus.ADMIN_PRINCIPAL ) || ! enabled )
+ {
+ return next.lookup( dn, attrIds );
+ }
+
+ checkLookupAccess( next, user, dn, entry );
+
+ return next.lookup( dn, attrIds );
}
public Attributes lookup( NextInterceptor next, Name name ) throws NamingException
{
- return super.lookup( next, name );
+ Attributes entry = nexus.lookup( name );
+ LdapPrincipal user = ( ( ServerContext ) InvocationStack.getInstance().peek().getCaller() ).getPrincipal();
+
+ if ( user.getName().equalsIgnoreCase( DirectoryPartitionNexus.ADMIN_PRINCIPAL ) || ! enabled )
+ {
+ return next.lookup( name );
+ }
+
+ checkLookupAccess( next, user, name, entry );
+
+ return next.lookup( name );
}
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=321015&r1=321014&r2=321015&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 Thu Oct 13 22:31:38 2005
@@ -17,7 +17,8 @@
package org.apache.ldap.server.authz;
-import org.apache.ldap.server.AbstractNonAdminTestCase;
+import org.apache.ldap.server.AbstractTestCase;
+import org.apache.ldap.server.partition.DirectoryPartitionNexus;
import org.apache.ldap.server.subtree.SubentryService;
import org.apache.ldap.common.name.LdapName;
@@ -29,12 +30,16 @@
/**
* A base class used for authorization tests. It has some extra utility methods
- * added to it which are required by all authorization tests.
+ * added to it which are required by all authorization tests. Note that we use
+ * the admin test case otherwise failures will result without browse permission
+ * when setting up the test case for non-admin users. Anyway we do not use the
+ * context created for the non-admin user since it is anonymous, we get our own
+ * contexts.
*
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
* @version $Rev$
*/
-public abstract class AbstractAuthorizationTest extends AbstractNonAdminTestCase
+public abstract class AbstractAuthorizationTest extends AbstractTestCase
{
/**
* Creates an abstract authorization test case which enables the
@@ -42,7 +47,7 @@
*/
public AbstractAuthorizationTest()
{
- super();
+ super( DirectoryPartitionNexus.ADMIN_PRINCIPAL, "secret" );
super.configuration.setAccessControlEnabled( true );
}
@@ -60,7 +65,7 @@
*/
public DirContext getContextAsAdmin() throws NamingException
{
- return getContextAsAdmin( "ou=system" );
+ return getContextAsAdmin( DirectoryPartitionNexus.SYSTEM_PARTITION_SUFFIX );
}
@@ -78,7 +83,7 @@
Hashtable env = ( Hashtable ) sysRoot.getEnvironment().clone();
env.put( DirContext.PROVIDER_URL, dn );
env.put( DirContext.SECURITY_AUTHENTICATION, "simple" );
- env.put( DirContext.SECURITY_PRINCIPAL, "uid=admin,ou=system" );
+ env.put( DirContext.SECURITY_PRINCIPAL, DirectoryPartitionNexus.ADMIN_PRINCIPAL );
env.put( DirContext.SECURITY_CREDENTIALS, "secret" );
return new InitialDirContext( env );
}
@@ -164,7 +169,7 @@
*/
public DirContext getContextAs( Name user, String password ) throws NamingException
{
- return getContextAs( user, password, "ou=system" );
+ return getContextAs( user, password, DirectoryPartitionNexus.SYSTEM_PARTITION_SUFFIX );
}
Modified: directory/apacheds/trunk/core/src/test/org/apache/ldap/server/authz/AddAuthorizationTest.java
URL: http://svn.apache.org/viewcvs/directory/apacheds/trunk/core/src/test/org/apache/ldap/server/authz/AddAuthorizationTest.java?rev=321015&r1=321014&r2=321015&view=diff
==============================================================================
--- directory/apacheds/trunk/core/src/test/org/apache/ldap/server/authz/AddAuthorizationTest.java (original)
+++ directory/apacheds/trunk/core/src/test/org/apache/ldap/server/authz/AddAuthorizationTest.java Thu Oct 13 22:31:38 2005
@@ -96,7 +96,7 @@
"userClasses { userGroup { \"cn=Administrators,ou=groups,ou=system\" } }, " +
"userPermissions { { " +
"protectedItems {entry, allUserAttributeTypesAndValues}, " +
- "grantsAndDenials { grantAdd } } } } }" );
+ "grantsAndDenials { grantAdd, 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
@@ -132,7 +132,7 @@
"userClasses { name { \"uid=billyd,ou=users,ou=system\" } }, " +
"userPermissions { { " +
"protectedItems {entry, allUserAttributeTypesAndValues}, " +
- "grantsAndDenials { grantAdd } } } } }" );
+ "grantsAndDenials { grantAdd, grantBrowse } } } } }" );
// should work now that billyd is authorized by name
assertTrue( checkCanAddEntryAs( "billyd", "billyd", "ou=testou" ) );
@@ -161,7 +161,7 @@
"userClasses { subtree { { base \"ou=users,ou=system\" } } }, " +
"userPermissions { { " +
"protectedItems {entry, allUserAttributeTypesAndValues}, " +
- "grantsAndDenials { grantAdd } } } } }" );
+ "grantsAndDenials { grantAdd, grantBrowse } } } } }" );
// should work now that billyd is authorized by the subtree userClass
assertTrue( checkCanAddEntryAs( "billyd", "billyd", "ou=testou" ) );
@@ -190,7 +190,7 @@
"userClasses { allUsers }, " +
"userPermissions { { " +
"protectedItems {entry, allUserAttributeTypesAndValues}, " +
- "grantsAndDenials { grantAdd } } } } }" );
+ "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
Added: directory/apacheds/trunk/core/src/test/org/apache/ldap/server/authz/CompareAuthorizationTest.java
URL: http://svn.apache.org/viewcvs/directory/apacheds/trunk/core/src/test/org/apache/ldap/server/authz/CompareAuthorizationTest.java?rev=321015&view=auto
==============================================================================
--- directory/apacheds/trunk/core/src/test/org/apache/ldap/server/authz/CompareAuthorizationTest.java (added)
+++ directory/apacheds/trunk/core/src/test/org/apache/ldap/server/authz/CompareAuthorizationTest.java Thu Oct 13 22:31:38 2005
@@ -0,0 +1,218 @@
+/*
+ * Copyright 2004 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.ldap.server.authz;
+
+
+import org.apache.ldap.common.exception.LdapNoPermissionException;
+import org.apache.ldap.common.name.LdapName;
+import org.apache.ldap.server.jndi.ServerDirContext;
+import org.apache.ldap.server.jndi.ServerLdapContext;
+
+import javax.naming.NamingException;
+import javax.naming.directory.*;
+
+
+/**
+ * Tests whether or not authorization around entry compare operations work properly.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$
+ */
+public class CompareAuthorizationTest extends AbstractAuthorizationTest
+{
+ /**
+ * Checks if an attribute of a simple entry (an organizationalUnit's telephoneNumber)
+ * with an RDN relative to ou=system can be compared by a specific non-admin user.
+ * If a permission exception is encountered it is caught and false is returned,
+ * otherwise true is returned. The entry is deleted after being created just in case
+ * subsequent calls to this method are made in the same test case: the admin account
+ * is used to add and delete this test entry so permissions to add and delete are not
+ * required to test the compare operation by the user.
+ *
+ * @param uid the unique identifier for the user (presumed to exist under ou=users,ou=system)
+ * @param password the password of this user
+ * @param entryRdn the relative DN, relative to ou=system where entry is created
+ * for comparison test
+ * @param number the telephone number to compare to this one
+ * @return true if the entry's telephoneNumber can be compared by the user at the
+ * specified location, false otherwise. A false compare result still returns
+ * true.
+ * @throws javax.naming.NamingException if there are problems conducting the test
+ */
+ public boolean checkCanCompareTelephoneNumberAs( String uid, String password, String entryRdn, String number )
+ throws NamingException
+ {
+ // create the entry with the telephoneNumber attribute to compare
+ Attributes testEntry = new BasicAttributes( "ou", "testou", true );
+ Attribute objectClass = new BasicAttribute( "objectClass" );
+ testEntry.put( objectClass );
+ objectClass.add( "top" );
+ objectClass.add( "organizationalUnit" );
+ testEntry.put( "telephoneNumber", "867-5309" ); // jenny don't change your number
+
+ DirContext adminContext = getContextAsAdmin();
+
+ try
+ {
+ // create the entry as admin
+ LdapName userName = new LdapName( "uid="+uid+",ou=users,ou=system" );
+ adminContext.createSubcontext( entryRdn, testEntry );
+
+ // compare the telephone numbers
+ DirContext userContext = getContextAs( userName, password );
+ ServerLdapContext ctx = ( ServerLdapContext ) userContext.lookup( "" );
+ ctx.compare( new LdapName( entryRdn + ",ou=system" ), "telephoneNumber", number );
+
+ // don't return compare result which can be false but true since op was permitted
+ return true;
+ }
+ catch ( LdapNoPermissionException e )
+ {
+ return false;
+ }
+ finally
+ {
+ // let's clean up
+ adminContext.destroySubcontext( entryRdn );
+ }
+ }
+
+
+ /**
+ * Checks to make sure group membership based userClass works for compare operations.
+ *
+ * @throws javax.naming.NamingException if the test encounters an error
+ */
+ public void testGrantCompareAdministrators() throws NamingException
+ {
+ // create the non-admin user
+ createUser( "billyd", "billyd" );
+
+ // try a compare operation which should fail without any ACI
+ assertFalse( checkCanCompareTelephoneNumberAs( "billyd", "billyd", "ou=testou", "867-5309" ) );
+
+ // Gives grantCompare, and grantRead perm to all users in the Administrators group for
+ // entries and all attribute types and values
+ createAccessControlSubentry( "administratorAdd", "{ " +
+ "identificationTag \"addAci\", " +
+ "precedence 14, " +
+ "authenticationLevel none, " +
+ "itemOrUserFirst userFirst: { " +
+ "userClasses { userGroup { \"cn=Administrators,ou=groups,ou=system\" } }, " +
+ "userPermissions { { " +
+ "protectedItems {entry, allUserAttributeTypesAndValues}, " +
+ "grantsAndDenials { grantCompare, grantRead, 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( checkCanCompareTelephoneNumberAs( "billyd", "billyd", "ou=testou", "867-5309" ) );
+
+ // 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( checkCanCompareTelephoneNumberAs( "billyd", "billyd", "ou=testou", "976-6969" ) );
+ }
+
+
+ /**
+ * Checks to make sure name based userClass works for compare operations.
+ *
+ * @throws javax.naming.NamingException if the test encounters an error
+ */
+ public void testGrantCompareByName() throws NamingException
+ {
+ // create the non-admin user
+ createUser( "billyd", "billyd" );
+
+ // try an compare operation which should fail without any ACI
+ assertFalse( checkCanCompareTelephoneNumberAs( "billyd", "billyd", "ou=testou", "867-5309" ) );
+
+ // now add a subentry that enables user billyd to compare 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 { grantCompare, grantRead, grantBrowse } } } } }" );
+
+ // should work now that billyd is authorized by name
+ assertTrue( checkCanCompareTelephoneNumberAs( "billyd", "billyd", "ou=testou", "867-5309" ) );
+ }
+
+
+ /**
+ * Checks to make sure subtree based userClass works for compare operations.
+ *
+ * @throws javax.naming.NamingException if the test encounters an error
+ */
+ public void testGrantCompareBySubtree() throws NamingException
+ {
+ // create the non-admin user
+ createUser( "billyd", "billyd" );
+
+ // try a compare operation which should fail without any ACI
+ assertFalse( checkCanCompareTelephoneNumberAs( "billyd", "billyd", "ou=testou", "867-5309" ) );
+
+ // now add a subentry that enables user billyd to compare 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 { grantCompare, grantRead, grantBrowse } } } } }" );
+
+ // should work now that billyd is authorized by the subtree userClass
+ assertTrue( checkCanCompareTelephoneNumberAs( "billyd", "billyd", "ou=testou", "867-5309" ) );
+ }
+
+
+ /**
+ * Checks to make sure <b>allUsers</b> userClass works for compare operations.
+ *
+ * @throws javax.naming.NamingException if the test encounters an error
+ */
+ public void testGrantCompareAllUsers() throws NamingException
+ {
+ // create the non-admin user
+ createUser( "billyd", "billyd" );
+
+ // try an add operation which should fail without any ACI
+ assertFalse( checkCanCompareTelephoneNumberAs( "billyd", "billyd", "ou=testou", "867-5309" ) );
+
+ // 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 { grantCompare, grantRead, grantBrowse } } } } }" );
+
+ // see if we can now compare that test entry's number which we could not before
+ // should work with billyd now that all users are authorized
+ assertTrue( checkCanCompareTelephoneNumberAs( "billyd", "billyd", "ou=testou", "867-5309" ) );
+ }
+}
Propchange: directory/apacheds/trunk/core/src/test/org/apache/ldap/server/authz/CompareAuthorizationTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: directory/apacheds/trunk/core/src/test/org/apache/ldap/server/authz/DeleteAuthorizationTest.java
URL: http://svn.apache.org/viewcvs/directory/apacheds/trunk/core/src/test/org/apache/ldap/server/authz/DeleteAuthorizationTest.java?rev=321015&r1=321014&r2=321015&view=diff
==============================================================================
--- directory/apacheds/trunk/core/src/test/org/apache/ldap/server/authz/DeleteAuthorizationTest.java (original)
+++ directory/apacheds/trunk/core/src/test/org/apache/ldap/server/authz/DeleteAuthorizationTest.java Thu Oct 13 22:31:38 2005
@@ -103,7 +103,7 @@
"userClasses { userGroup { \"cn=Administrators,ou=groups,ou=system\" } }, " +
"userPermissions { { " +
"protectedItems {entry}, " +
- "grantsAndDenials { grantRemove } } } } }" );
+ "grantsAndDenials { grantRemove, grantBrowse } } } } }" );
// see if we can now delete that test entry which we could not before
// delete op should still fail since billd is not in the admin group
@@ -139,7 +139,7 @@
"userClasses { name { \"uid=billyd,ou=users,ou=system\" } }, " +
"userPermissions { { " +
"protectedItems {entry}, " +
- "grantsAndDenials { grantRemove } } } } }" );
+ "grantsAndDenials { grantRemove, grantBrowse } } } } }" );
// should work now that billyd is authorized by name
assertTrue( checkCanDeleteEntryAs( "billyd", "billyd", "ou=testou" ) );
@@ -168,7 +168,7 @@
"userClasses { subtree { { base \"ou=users,ou=system\" } } }, " +
"userPermissions { { " +
"protectedItems {entry}, " +
- "grantsAndDenials { grantRemove } } } } }" );
+ "grantsAndDenials { grantRemove, grantBrowse } } } } }" );
// should work now that billyd is authorized by the subtree userClass
assertTrue( checkCanDeleteEntryAs( "billyd", "billyd", "ou=testou" ) );
@@ -197,7 +197,7 @@
"userClasses { allUsers }, " +
"userPermissions { { " +
"protectedItems {entry}, " +
- "grantsAndDenials { grantRemove } } } } }" );
+ "grantsAndDenials { grantRemove, grantBrowse } } } } }" );
// see if we can now delete that test entry which we could not before
// should work now with billyd now that all users are authorized