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/08 09:07:58 UTC
svn commit: r307270 - in /directory/apacheds/trunk/core/src:
main/java/org/apache/ldap/server/ main/java/org/apache/ldap/server/authz/
main/java/org/apache/ldap/server/exception/
test/org/apache/ldap/server/authz/
Author: akarasulu
Date: Sat Oct 8 00:07:47 2005
New Revision: 307270
URL: http://svn.apache.org/viewcvs?rev=307270&view=rev
Log:
changes ...
o added a bunch of test cases for the ADD operation using different userClasses
o added new rename methods for the Tuple and GroupCache to support modifyRn and
move operations within the server
o implemented interceptor methods for delete, compare, modify, modifyRn, & move
o added better error reporting on LdapNameAlreadyBoundException
o made sure the right normalized name for the Administrators group is used
Modified:
directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/DefaultDirectoryService.java
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/GroupCache.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/exception/ExceptionService.java
directory/apacheds/trunk/core/src/test/org/apache/ldap/server/authz/AuthorizationServiceAsNonAdminTest.java
Modified: directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/DefaultDirectoryService.java
URL: http://svn.apache.org/viewcvs/directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/DefaultDirectoryService.java?rev=307270&r1=307269&r2=307270&view=diff
==============================================================================
--- directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/DefaultDirectoryService.java (original)
+++ directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/DefaultDirectoryService.java Sat Oct 8 00:07:47 2005
@@ -460,7 +460,7 @@
// -------------------------------------------------------------------
String upName = "cn=Administrators,ou=groups,ou=system";
- Name normName = new LdapName( upName );
+ Name normName = new LdapName( "cn=administrators,ou=groups,ou=system" );
if ( !partitionNexus.hasEntry( normName ) )
{
firstStart = true;
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=307270&r1=307269&r2=307270&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 Sat Oct 8 00:07:47 2005
@@ -35,6 +35,7 @@
import org.apache.ldap.common.aci.ACIItem;
import org.apache.ldap.common.exception.LdapNamingException;
import org.apache.ldap.common.message.ResultCodeEnum;
+import org.apache.ldap.common.util.NamespaceTools;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -42,10 +43,7 @@
import javax.naming.Name;
import javax.naming.NamingException;
import javax.naming.NamingEnumeration;
-import javax.naming.directory.Attributes;
-import javax.naming.directory.ModificationItem;
-import javax.naming.directory.SearchControls;
-import javax.naming.directory.Attribute;
+import javax.naming.directory.*;
import java.util.*;
import java.text.ParseException;
@@ -65,54 +63,6 @@
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 DirectoryPartitionNexus nexus;
/** a tupleCache that responds to add, delete, and modify attempts */
@@ -318,8 +268,19 @@
// note that entryACI should not be considered in adds (it's a security breach)
addPerscriptiveAciTuples( tuples, normName, subentryAttrs );
addSubentryAciTuples( tuples, normName, subentryAttrs );
+ Collection perms = Collections.singleton( MicroOperation.ADD );
engine.checkPermission( next, userGroups, user.getJndiName(), user.getAuthenticationLevel(), normName, null,
- null, ADD_OPS, tuples, subentryAttrs );
+ null, perms, tuples, subentryAttrs );
+ 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(), normName,
+ attr.getID(), attr.get( ii ), perms, tuples, entry );
+ }
+ }
// if we've gotten this far then access is granted
next.add( upName, normName, entry );
@@ -330,17 +291,25 @@
public void delete( NextInterceptor next, Name name ) throws NamingException
{
+ // Access the principal requesting the operation, and bypass checks if it is the admin
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 );
+ LdapPrincipal user = ( ( ServerContext ) InvocationStack.getInstance().peek().getCaller() ).getPrincipal();
+ if ( user.getName().equalsIgnoreCase( DirectoryPartitionNexus.ADMIN_PRINCIPAL ) || ! enabled )
+ {
+ next.delete( name );
+ tupleCache.subentryDeleted( name, entry );
+ groupCache.groupDeleted( name, entry );
+ return;
+ }
+
+ Set userGroups = groupCache.getGroups( user.getName() );
+ Collection tuples = new HashSet();
+ addPerscriptiveAciTuples( tuples, name, entry );
+ addEntryAciTuples( tuples, entry );
+ addSubentryAciTuples( tuples, name, entry );
+
+ engine.checkPermission( next, userGroups, user.getJndiName(), user.getAuthenticationLevel(), name, null,
+ null, Collections.singleton( MicroOperation.REMOVE ), tuples, entry );
next.delete( name );
tupleCache.subentryDeleted( name, entry );
@@ -350,17 +319,52 @@
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
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 );
+ LdapPrincipal user = ( ( ServerContext ) InvocationStack.getInstance().peek().getCaller() ).getPrincipal();
+ if ( user.getName().equalsIgnoreCase( DirectoryPartitionNexus.ADMIN_PRINCIPAL ) || ! enabled )
+ {
+ next.modify( name, modOp, mods );
+ tupleCache.subentryModified( name, modOp, mods, entry );
+ groupCache.groupModified( name, modOp, mods, entry );
+ return;
+ }
+
+ Set userGroups = groupCache.getGroups( user.getName() );
+ Collection tuples = new HashSet();
+ addPerscriptiveAciTuples( tuples, name, entry );
+ addEntryAciTuples( tuples, entry );
+ addSubentryAciTuples( tuples, name, entry );
+
+ engine.checkPermission( next, userGroups, user.getJndiName(), user.getAuthenticationLevel(), name, null,
+ null, Collections.singleton( MicroOperation.MODIFY ), tuples, entry );
+
+ NamingEnumeration attrList = mods.getAll();
+ Collection perms = null;
+ switch( modOp )
+ {
+ case( DirContext.ADD_ATTRIBUTE ):
+ perms = Collections.singleton( MicroOperation.ADD );
+ break;
+ case( DirContext.REMOVE_ATTRIBUTE ):
+ perms = Collections.singleton( MicroOperation.REMOVE );
+ break;
+ case( DirContext.REPLACE_ATTRIBUTE ):
+ perms = new HashSet();
+ perms.add( MicroOperation.ADD );
+ perms.add( MicroOperation.REMOVE );
+ break;
+ }
+
+ while( attrList.hasMore() )
+ {
+ Attribute attr = ( Attribute ) attrList.next();
+ for ( int ii = 0; ii < attr.size(); ii++ )
+ {
+ engine.checkPermission( next, userGroups, user.getJndiName(), user.getAuthenticationLevel(),
+ name, attr.getID(), attr.get( ii ), perms, tuples, entry );
+ }
+ }
next.modify( name, modOp, mods );
tupleCache.subentryModified( name, modOp, mods, entry );
@@ -370,39 +374,59 @@
public void modify( NextInterceptor next, Name name, ModificationItem[] mods ) throws NamingException
{
+ // Access the principal requesting the operation, and bypass checks if it is the admin
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 );
+ LdapPrincipal user = ( ( ServerContext ) InvocationStack.getInstance().peek().getCaller() ).getPrincipal();
+ if ( user.getName().equalsIgnoreCase( DirectoryPartitionNexus.ADMIN_PRINCIPAL ) || ! enabled )
+ {
+ next.modify( name, mods );
+ tupleCache.subentryModified( name, mods, entry );
+ groupCache.groupModified( name, mods, entry );
+ return;
+ }
- next.modify( name, mods );
- tupleCache.subentryModified( name, mods, entry );
- groupCache.groupModified( name, mods, entry );
- }
+ Set userGroups = groupCache.getGroups( user.getName() );
+ Collection tuples = new HashSet();
+ addPerscriptiveAciTuples( tuples, name, entry );
+ addEntryAciTuples( tuples, entry );
+ addSubentryAciTuples( tuples, name, entry );
+
+ engine.checkPermission( next, userGroups, user.getJndiName(), user.getAuthenticationLevel(), name, null,
+ null, Collections.singleton( MicroOperation.MODIFY ), tuples, entry );
+
+ Collection perms = null;
+ Collection remove = Collections.singleton( MicroOperation.REMOVE );
+ Collection add = Collections.singleton( MicroOperation.ADD );
+ Collection replace = new HashSet();
+ replace.add( MicroOperation.ADD );
+ replace.add( MicroOperation.REMOVE );
+ for ( int ii = 0; ii < mods.length; ii++ )
+ {
+ switch( mods[ii].getModificationOp() )
+ {
+ case( DirContext.ADD_ATTRIBUTE ):
+ perms = add;
+ break;
+ case( DirContext.REMOVE_ATTRIBUTE ):
+ perms = remove;
+ break;
+ case( DirContext.REPLACE_ATTRIBUTE ):
+ perms = replace;
+ break;
+ }
- public Attributes getRootDSE( NextInterceptor next ) throws NamingException
- {
- 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 );
+ Attribute attr = mods[ii].getAttribute();
+ for ( int jj = 0; jj < attr.size(); jj++ )
+ {
+ engine.checkPermission( next, userGroups, user.getJndiName(), user.getAuthenticationLevel(),
+ name, attr.getID(), attr.get( jj ), perms, tuples, entry );
+ }
+ }
- return entry;
+ next.modify( name, mods );
+ tupleCache.subentryModified( name, mods, entry );
+ groupCache.groupModified( name, mods, entry );
}
@@ -462,56 +486,164 @@
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 );
+ // Access the principal requesting the operation, and bypass checks if it is the admin
+ Attributes entry = nexus.lookup( name );
+ LdapPrincipal user = ( ( ServerContext ) InvocationStack.getInstance().peek().getCaller() ).getPrincipal();
+ Name newName = ( Name ) name.clone();
+ newName.remove( name.size() - 1 );
+ newName.add( newRn );
+ if ( user.getName().equalsIgnoreCase( DirectoryPartitionNexus.ADMIN_PRINCIPAL ) || ! enabled )
+ {
+ next.modifyRn( name, newRn, deleteOldRn );
+ tupleCache.subentryRenamed( name, newName );
+ groupCache.groupRenamed( name, newName );
+ return;
+ }
- super.modifyRn( next, name, newRn, deleteOldRn );
+ Set userGroups = groupCache.getGroups( user.getName() );
+ Collection tuples = new HashSet();
+ addPerscriptiveAciTuples( tuples, name, entry );
+ addEntryAciTuples( tuples, entry );
+ addSubentryAciTuples( tuples, name, entry );
+
+ engine.checkPermission( next, userGroups, user.getJndiName(), user.getAuthenticationLevel(), name, null,
+ null, Collections.singleton( MicroOperation.RENAME ), tuples, entry );
+
+ if ( deleteOldRn )
+ {
+ String oldRn = name.get( name.size() - 1 );
+ if ( NamespaceTools.hasCompositeComponents( oldRn ) )
+ {
+ String[] comps = NamespaceTools.getCompositeComponents( oldRn );
+ for ( int ii = 0; ii < comps.length; ii++ )
+ {
+ String id = NamespaceTools.getRdnAttribute( comps[ii] );
+ String value = NamespaceTools.getRdnValue( comps[ii] );
+ engine.checkPermission( next, userGroups, user.getJndiName(),
+ user.getAuthenticationLevel(), name, id,
+ value, Collections.singleton( MicroOperation.REMOVE ),
+ tuples, entry );
+ }
+ }
+ else
+ {
+ String id = NamespaceTools.getRdnAttribute( oldRn );
+ String value = NamespaceTools.getRdnValue( oldRn );
+ engine.checkPermission( next, userGroups, user.getJndiName(),
+ user.getAuthenticationLevel(), name, id,
+ value, Collections.singleton( MicroOperation.REMOVE ),
+ tuples, entry );
+ }
+ }
+
+ next.modifyRn( name, newRn, deleteOldRn );
+ tupleCache.subentryRenamed( name, newName );
+ groupCache.groupRenamed( name, newName );
}
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 );
+ // Access the principal requesting the operation, and bypass checks if it is the admin
+ Attributes entry = nexus.lookup( oriChildName );
+ LdapPrincipal user = ( ( ServerContext ) InvocationStack.getInstance().peek().getCaller() ).getPrincipal();
+ Name newName = ( Name ) newParentName.clone();
+ newName.add( newRn );
+ if ( user.getName().equalsIgnoreCase( DirectoryPartitionNexus.ADMIN_PRINCIPAL ) || ! enabled )
+ {
+ next.move( oriChildName, newParentName, newRn, deleteOldRn );
+ tupleCache.subentryRenamed( oriChildName, newName );
+ groupCache.groupRenamed( oriChildName, newName );
+ return;
+ }
+
+ Set userGroups = groupCache.getGroups( user.getName() );
+ Collection tuples = new HashSet();
+ addPerscriptiveAciTuples( tuples, oriChildName, entry );
+ addEntryAciTuples( tuples, entry );
+ addSubentryAciTuples( tuples, oriChildName, entry );
+
+ Collection perms = new HashSet();
+ perms.add( MicroOperation.RENAME );
+ perms.add( MicroOperation.EXPORT );
+ engine.checkPermission( next, userGroups, user.getJndiName(), user.getAuthenticationLevel(),
+ oriChildName, null, null, perms, tuples, entry );
+
+ Collection destTuples = new HashSet();
+ addPerscriptiveAciTuples( destTuples, oriChildName, entry );
+ addEntryAciTuples( destTuples, entry );
+ addSubentryAciTuples( destTuples, oriChildName, entry );
+ engine.checkPermission( next, userGroups, user.getJndiName(), user.getAuthenticationLevel(),
+ oriChildName, null, null, Collections.singleton( MicroOperation.IMPORT ), tuples, entry );
- super.move( next, oriChildName, newParentName, newRn, deleteOldRn );
+ if ( deleteOldRn )
+ {
+ String oldRn = oriChildName.get( oriChildName.size() - 1 );
+ if ( NamespaceTools.hasCompositeComponents( oldRn ) )
+ {
+ String[] comps = NamespaceTools.getCompositeComponents( oldRn );
+ for ( int ii = 0; ii < comps.length; ii++ )
+ {
+ String id = NamespaceTools.getRdnAttribute( comps[ii] );
+ String value = NamespaceTools.getRdnValue( comps[ii] );
+ engine.checkPermission( next, userGroups, user.getJndiName(),
+ user.getAuthenticationLevel(), oriChildName, id,
+ value, Collections.singleton( MicroOperation.REMOVE ),
+ tuples, entry );
+ }
+ }
+ else
+ {
+ String id = NamespaceTools.getRdnAttribute( oldRn );
+ String value = NamespaceTools.getRdnValue( oldRn );
+ engine.checkPermission( next, userGroups, user.getJndiName(),
+ user.getAuthenticationLevel(), oriChildName, id,
+ value, Collections.singleton( MicroOperation.REMOVE ),
+ tuples, entry );
+ }
+ }
+
+ next.move( oriChildName, newParentName, newRn, deleteOldRn );
+ tupleCache.subentryRenamed( oriChildName, newName );
+ groupCache.groupRenamed( oriChildName, newName );
}
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 );
+ // Access the principal requesting the operation, and bypass checks if it is the admin
+ Attributes entry = nexus.lookup( oriChildName );
+ LdapPrincipal user = ( ( ServerContext ) InvocationStack.getInstance().peek().getCaller() ).getPrincipal();
+ Name newName = ( Name ) newParentName.clone();
+ newName.add( oriChildName.get( oriChildName.size() - 1 ) );
+ if ( user.getName().equalsIgnoreCase( DirectoryPartitionNexus.ADMIN_PRINCIPAL ) || ! enabled )
+ {
+ next.move( oriChildName, newParentName );
+ tupleCache.subentryRenamed( oriChildName, newName );
+ groupCache.groupRenamed( oriChildName, newName );
+ return;
+ }
+
+ Set userGroups = groupCache.getGroups( user.getName() );
+ Collection tuples = new HashSet();
+ addPerscriptiveAciTuples( tuples, oriChildName, entry );
+ addEntryAciTuples( tuples, entry );
+ addSubentryAciTuples( tuples, oriChildName, entry );
+
+ engine.checkPermission( next, userGroups, user.getJndiName(), user.getAuthenticationLevel(),
+ oriChildName, null, null, Collections.singleton( MicroOperation.EXPORT ), tuples, entry );
+
+ Collection destTuples = new HashSet();
+ addPerscriptiveAciTuples( destTuples, oriChildName, entry );
+ addEntryAciTuples( destTuples, entry );
+ addSubentryAciTuples( destTuples, oriChildName, entry );
+ engine.checkPermission( next, userGroups, user.getJndiName(), user.getAuthenticationLevel(),
+ oriChildName, null, null, Collections.singleton( MicroOperation.IMPORT ), tuples, entry );
+
+ next.move( oriChildName, newParentName );
+ tupleCache.subentryRenamed( oriChildName, newName );
+ groupCache.groupRenamed( oriChildName, newName );
}
@@ -536,19 +668,27 @@
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);
+ // Access the principal requesting the operation, and bypass checks if it is the admin
+ Attributes entry = nexus.lookup( name );
+ LdapPrincipal user = ( ( ServerContext ) InvocationStack.getInstance().peek().getCaller() ).getPrincipal();
+ if ( user.getName().equalsIgnoreCase( DirectoryPartitionNexus.ADMIN_PRINCIPAL ) || ! enabled )
+ {
+ return next.compare( name, oid, value );
+ }
+
+ Set userGroups = groupCache.getGroups( user.getName() );
+ Collection tuples = new HashSet();
+ addPerscriptiveAciTuples( tuples, name, entry );
+ addEntryAciTuples( tuples, entry );
+ addSubentryAciTuples( tuples, name, entry );
+
+ engine.checkPermission( next, userGroups, user.getJndiName(), user.getAuthenticationLevel(), name, null,
+ null, Collections.singleton( MicroOperation.READ ), tuples, entry );
+ engine.checkPermission( next, userGroups, user.getJndiName(), user.getAuthenticationLevel(), name, oid,
+ value, Collections.singleton( MicroOperation.COMPARE ), tuples, entry );
+
+ return next.compare( name, oid, value );
}
Modified: directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/GroupCache.java
URL: http://svn.apache.org/viewcvs/directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/GroupCache.java?rev=307270&r1=307269&r2=307270&view=diff
==============================================================================
--- directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/GroupCache.java (original)
+++ directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/GroupCache.java Sat Oct 8 00:07:47 2005
@@ -371,4 +371,10 @@
return memberGroups;
}
+
+
+ public void groupRenamed( Name oldName, Name newName )
+ {
+ groups.put( newName.toString(), groups.remove( oldName.toString() ) );
+ }
}
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=307270&r1=307269&r2=307270&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 Sat Oct 8 00:07:47 2005
@@ -226,4 +226,10 @@
}
return Collections.unmodifiableList( aciTuples );
}
+
+
+ public void subentryRenamed( Name oldName, Name newName )
+ {
+ tuples.put( newName.toString(), tuples.remove( oldName.toString() ) );
+ }
}
Modified: directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/exception/ExceptionService.java
URL: http://svn.apache.org/viewcvs/directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/exception/ExceptionService.java?rev=307270&r1=307269&r2=307270&view=diff
==============================================================================
--- directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/exception/ExceptionService.java (original)
+++ directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/exception/ExceptionService.java Sat Oct 8 00:07:47 2005
@@ -77,7 +77,7 @@
// check if the entry already exists
if ( nextInterceptor.hasEntry( normName ) )
{
- NamingException ne = new LdapNameAlreadyBoundException();
+ NamingException ne = new LdapNameAlreadyBoundException( normName.toString() + " already exists!" );
ne.setResolvedName( new LdapName( upName ) );
throw ne;
}
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=307270&r1=307269&r2=307270&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 Sat Oct 8 00:07:47 2005
@@ -22,10 +22,12 @@
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
+import javax.naming.Name;
import javax.naming.directory.*;
import org.apache.ldap.common.exception.LdapNoPermissionException;
import org.apache.ldap.common.message.LockableAttributesImpl;
+import org.apache.ldap.common.name.LdapName;
import org.apache.ldap.server.AbstractNonAdminTestCase;
import org.apache.ldap.server.subtree.SubentryService;
@@ -176,7 +178,7 @@
"itemOrUserFirst userFirst: { " +
"userClasses { allUsers }, " +
"userPermissions { { " +
- "protectedItems {entry}, " +
+ "protectedItems {entry, allUserAttributeTypesAndValues}, " +
"grantsAndDenials { grantAdd } } } } }" );
adminCtx.createSubcontext( "cn=anybodyAdd", subentry );
@@ -187,5 +189,203 @@
objectClass.add( "top" );
objectClass.add( "organizationalUnit" );
sysRoot.createSubcontext( "ou=testou", testEntry );
+ }
+
+
+ public Name createTestUser( String uid ) throws NamingException
+ {
+ DirContext adminCtx = getAdminContext();
+
+ Attributes testUser = new BasicAttributes( "uid", uid, true );
+ testUser.put( "userPassword", uid );
+ Attribute objectClass = new BasicAttribute( "objectClass" );
+ testUser.put( objectClass );
+ objectClass.add( "top" );
+ objectClass.add( "person" );
+ objectClass.add( "organizationalPerson" );
+ objectClass.add( "inetOrgPerson" );
+
+ adminCtx.createSubcontext( "uid="+uid+",ou=users", testUser );
+ return new LdapName( "uid="+uid+",ou=users,ou=system" );
+ }
+
+
+ public void addUserToGroup( String userUid, String groupCn ) throws NamingException
+ {
+ DirContext adminCtx = getAdminContext();
+ Attributes changes = new BasicAttributes( "uniqueMember", "uid="+userUid+",ou=users,ou=system", true );
+ adminCtx.modifyAttributes( "cn="+groupCn+",ou=groups", DirContext.ADD_ATTRIBUTE, changes );
+ }
+
+
+ public DirContext getUserContext( Name user, String password ) 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, user.toString() );
+ env.put( DirContext.SECURITY_CREDENTIALS, password );
+ return new InitialDirContext( env );
+ }
+
+
+ public void testGrantAddAdministrators() 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 );
+
+ Name userName = createTestUser( "billyd" );
+
+ // 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
+ {
+ DirContext userContext = getUserContext( userName, "billyd" );
+ userContext.createSubcontext( "ou=testou", testEntry );
+ fail( "should never get here due to a permission exception" );
+ }
+ catch ( LdapNoPermissionException e ) {}
+
+ // now add a subentry that enables users in the admin group to add an entry below ou=system
+ Attributes subentry = new BasicAttributes( "cn", "administratorAdd", 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 { userGroup { \"cn=Administrators,ou=groups,ou=system\" } }, " +
+ "userPermissions { { " +
+ "protectedItems {entry, allUserAttributeTypesAndValues}, " +
+ "grantsAndDenials { grantAdd } } } } }" );
+ adminCtx.createSubcontext( "cn=administratorAdd", subentry );
+
+ // see if we can now add that test entry which we could not before
+ // add op should still fail since akarasulu is not in the admin group
+ try
+ {
+ DirContext userContext = getUserContext( userName, "billyd" );
+ userContext.createSubcontext( "ou=testou", testEntry );
+ fail( "should never get here due to a permission exception" );
+ }
+ catch ( LdapNoPermissionException e ) {}
+
+ // now add akarasulu to the Administrator group and try again
+ addUserToGroup( "billyd", "Administrators" );
+ DirContext userContext = getUserContext( userName, "billyd" );
+ userContext.createSubcontext( "ou=testou", testEntry );
+ }
+
+
+ public void testGrantAddByName() 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 );
+
+ Name userName = createTestUser( "billyd" );
+
+ // 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
+ {
+ DirContext userContext = getUserContext( userName, "billyd" );
+ userContext.createSubcontext( "ou=testou", testEntry );
+ fail( "should never get here due to a permission exception" );
+ }
+ catch ( LdapNoPermissionException e ) {}
+
+ // now add a subentry that enables user billyd to add an entry below ou=system
+ Attributes subentry = new BasicAttributes( "cn", "billydAdd", 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 { name { \"uid=billyd,ou=users,ou=system\" } }, " +
+ "userPermissions { { " +
+ "protectedItems {entry, allUserAttributeTypesAndValues}, " +
+ "grantsAndDenials { grantAdd } } } } }" );
+ adminCtx.createSubcontext( "cn=billydAdd", subentry );
+
+ // should work now that billyd is authorized
+ DirContext userContext = getUserContext( userName, "billyd" );
+ userContext.createSubcontext( "ou=testou", testEntry );
+ }
+
+
+ public void testGrantAddBySubtree() 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 );
+
+ Name userName = createTestUser( "billyd" );
+
+ // 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
+ {
+ DirContext userContext = getUserContext( userName, "billyd" );
+ userContext.createSubcontext( "ou=testou", testEntry );
+ fail( "should never get here due to a permission exception" );
+ }
+ catch ( LdapNoPermissionException e ) {}
+
+ // now add a subentry that enables user billyd to add an entry below ou=system
+ Attributes subentry = new BasicAttributes( "cn", "billydAdd", 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 { subtree { { base \"ou=users,ou=system\" } } }, " +
+ "userPermissions { { " +
+ "protectedItems {entry, allUserAttributeTypesAndValues}, " +
+ "grantsAndDenials { grantAdd } } } } }" );
+ adminCtx.createSubcontext( "cn=billydAdd", subentry );
+
+ // should work now that billyd is authorized
+ DirContext userContext = getUserContext( userName, "billyd" );
+ userContext.createSubcontext( "ou=testou", testEntry );
}
}