directory-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From akaras...@apache.org
Subject svn commit: r326825 - in /directory/apacheds/trunk/core/src: main/java/org/apache/ldap/server/authz/ main/java/org/apache/ldap/server/exception/ main/java/org/apache/ldap/server/partition/ test/org/apache/ldap/server/authz/
Date Thu, 20 Oct 2005 05:09:52 GMT
Author: akarasulu
Date: Wed Oct 19 22:09:43 2005
New Revision: 326825

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

 o added tests for permission to disclose on error 
 o added functionality (guards) to getMatchedName() for disclose on error
 o created constant unmodifiable collections for all permission collections
   used in Authz service
 o made some code in exception service use proxy to getMatchedName()
 o added new constant for lookups in getMatchedName() so normalization occurs


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/exception/ExceptionService.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=326825&r1=326824&r2=326825&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
Wed Oct 19 22:09:43 2005
@@ -74,8 +74,57 @@
      */
     private static final String AC_SUBENTRY_ATTR = "accessControlSubentries";
 
-    /** the partition nexus */
-    private DirectoryPartitionNexus nexus;
+    private static final Collection ADD_PERMS;
+    private static final Collection READ_PERMS;
+    private static final Collection COMPARE_PERMS;
+    private static final Collection SEARCH_ENTRY_PERMS;
+    private static final Collection SEARCH_ATTRVAL_PERMS;
+    private static final Collection REMOVE_PERMS;
+    private static final Collection MATCHEDNAME_PERMS;
+    private static final Collection BROWSE_PERMS;
+    private static final Collection LOOKUP_PERMS;
+    private static final Collection REPLACE_PERMS;
+    private static final Collection RENAME_PERMS;
+    private static final Collection EXPORT_PERMS;
+    private static final Collection IMPORT_PERMS;
+    private static final Collection MOVERENAME_PERMS;
+
+
+    static
+    {
+        HashSet set = new HashSet( 2 );
+        set.add( MicroOperation.BROWSE );
+        set.add( MicroOperation.RETURN_DN );
+        SEARCH_ENTRY_PERMS = Collections.unmodifiableCollection( set );
+
+        set = new HashSet( 2 );
+        set.add( MicroOperation.READ );
+        set.add( MicroOperation.BROWSE );
+        LOOKUP_PERMS = Collections.unmodifiableCollection( set );
+
+        set = new HashSet( 2 );
+        set.add( MicroOperation.ADD );
+        set.add( MicroOperation.REMOVE );
+        REPLACE_PERMS = Collections.unmodifiableCollection( set );
+
+        set = new HashSet( 3 );
+        set.add( MicroOperation.IMPORT );
+        set.add( MicroOperation.EXPORT );
+        set.add( MicroOperation.RENAME );
+        MOVERENAME_PERMS = Collections.unmodifiableCollection( set );
+
+        SEARCH_ATTRVAL_PERMS = Collections.singleton( MicroOperation.READ );
+        ADD_PERMS = Collections.singleton( MicroOperation.ADD );
+        READ_PERMS = Collections.singleton( MicroOperation.READ );
+        COMPARE_PERMS = Collections.singleton( MicroOperation.COMPARE );
+        REMOVE_PERMS = Collections.singleton( MicroOperation.REMOVE );
+        MATCHEDNAME_PERMS = Collections.singleton( MicroOperation.DISCLOSE_ON_ERROR );
+        BROWSE_PERMS = Collections.singleton( MicroOperation.BROWSE );
+        RENAME_PERMS = Collections.singleton( MicroOperation.RENAME );
+        EXPORT_PERMS = Collections.singleton( MicroOperation.EXPORT );
+        IMPORT_PERMS = Collections.singleton( MicroOperation.IMPORT );
+    }
+
     /** a tupleCache that responds to add, delete, and modify attempts */
     private TupleCache tupleCache;
     /** a groupCache that responds to add, delete, and modify attempts */
@@ -103,7 +152,6 @@
     public void init( DirectoryServiceConfiguration factoryCfg, InterceptorConfiguration
cfg ) throws NamingException
     {
         super.init( factoryCfg, cfg );
-        nexus = factoryCfg.getPartitionNexus();
         tupleCache = new TupleCache( factoryCfg );
         groupCache = new GroupCache( factoryCfg );
         attrRegistry = factoryCfg.getGlobalRegistries().getAttributeTypeRegistry();
@@ -300,12 +348,11 @@
         // NOTE: entryACI are NOT considered in adds (it would be a security breech)
         addPerscriptiveAciTuples( invocation.getProxy(), tuples, normName, subentryAttrs
);
         addSubentryAciTuples( invocation.getProxy(), tuples, normName, subentryAttrs );
-        Collection perms = Collections.singleton( MicroOperation.ADD );
 
         // check if entry scope permission is granted
         DirectoryPartitionNexusProxy proxy = invocation.getProxy();
         engine.checkPermission( proxy, userGroups, user.getJndiName(), user.getAuthenticationLevel(),
-                normName, null, null, perms, tuples, subentryAttrs );
+                normName, null, null, ADD_PERMS, tuples, subentryAttrs );
 
         // now we must check if attribute type and value scope permission is granted
         NamingEnumeration attributeList = entry.getAll();
@@ -316,7 +363,7 @@
             {
                 engine.checkPermission( proxy, userGroups, user.getJndiName(),
                         user.getAuthenticationLevel(), normName, attr.getID(),
-                        attr.get( ii ), perms, tuples, entry );
+                        attr.get( ii ), ADD_PERMS, tuples, entry );
             }
         }
 
@@ -352,7 +399,7 @@
         addSubentryAciTuples( proxy, tuples, name, entry );
 
         engine.checkPermission( proxy, userGroups, user.getJndiName(), user.getAuthenticationLevel(),
name, null,
-                null, Collections.singleton( MicroOperation.REMOVE ), tuples, entry );
+                null, REMOVE_PERMS, tuples, entry );
 
         next.delete( name );
         tupleCache.subentryDeleted( name, entry );
@@ -389,15 +436,13 @@
         switch( modOp )
         {
             case( DirContext.ADD_ATTRIBUTE ):
-                perms = Collections.singleton( MicroOperation.ADD );
+                perms = ADD_PERMS;
                 break;
             case( DirContext.REMOVE_ATTRIBUTE ):
-                perms = Collections.singleton( MicroOperation.REMOVE );
+                perms = REMOVE_PERMS;
                 break;
             case( DirContext.REPLACE_ATTRIBUTE ):
-                perms = new HashSet();
-                perms.add( MicroOperation.ADD );
-                perms.add( MicroOperation.REMOVE );
+                perms = REPLACE_PERMS;
                 break;
         }
 
@@ -442,24 +487,18 @@
                 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;
+                    perms = ADD_PERMS;
                     break;
                 case( DirContext.REMOVE_ATTRIBUTE ):
-                    perms = remove;
+                    perms = REMOVE_PERMS;
                     break;
                 case( DirContext.REPLACE_ATTRIBUTE ):
-                    perms = replace;
+                    perms = REPLACE_PERMS;
                     break;
             }
 
@@ -497,7 +536,7 @@
 
         // check that we have browse access to the entry
         engine.checkPermission( proxy, userGroups, user.getJndiName(), user.getAuthenticationLevel(),
name, null,
-                null, Collections.singleton( MicroOperation.BROWSE ), tuples, entry );
+                null, BROWSE_PERMS, tuples, entry );
 
         return next.hasEntry( name );
     }
@@ -528,16 +567,11 @@
         addEntryAciTuples( tuples, entry );
         addSubentryAciTuples( proxy, tuples, dn, entry );
 
-        Collection perms = new HashSet();
-        perms.add( MicroOperation.READ );
-        perms.add( MicroOperation.BROWSE );
-
         // check that we have read access to the entry
         engine.checkPermission( proxy, userGroups, user.getJndiName(), user.getAuthenticationLevel(),
dn, null,
-                null, perms, tuples, entry );
+                null, LOOKUP_PERMS, tuples, entry );
 
         // check that we have read access to every attribute type and value
-        perms = Collections.singleton( MicroOperation.READ );
         NamingEnumeration attributeList = entry.getAll();
         while ( attributeList.hasMore() )
         {
@@ -545,7 +579,7 @@
             for ( int ii = 0; ii < attr.size(); ii++ )
             {
                 engine.checkPermission( proxy, userGroups, user.getJndiName(), user.getAuthenticationLevel(),
dn,
-                        attr.getID(), attr.get( ii ), perms, tuples, entry );
+                        attr.getID(), attr.get( ii ), READ_PERMS, tuples, entry );
             }
         }
     }
@@ -612,7 +646,7 @@
         addSubentryAciTuples( proxy, tuples, name, entry );
 
         engine.checkPermission( proxy, userGroups, user.getJndiName(), user.getAuthenticationLevel(),
name, null,
-                null, Collections.singleton( MicroOperation.RENAME ), tuples, entry );
+                null, RENAME_PERMS, tuples, entry );
 
 //        if ( deleteOldRn )
 //        {
@@ -671,19 +705,15 @@
         addEntryAciTuples( tuples, entry );
         addSubentryAciTuples( proxy, tuples, oriChildName, entry );
 
-        Collection perms = new HashSet();
-        perms.add( MicroOperation.IMPORT );
-        perms.add( MicroOperation.EXPORT );
-        perms.add( MicroOperation.RENAME );
         engine.checkPermission( proxy, userGroups, user.getJndiName(), user.getAuthenticationLevel(),
-                oriChildName, null, null, perms, tuples, entry );
+                oriChildName, null, null, MOVERENAME_PERMS, tuples, entry );
 
         Collection destTuples = new HashSet();
         addPerscriptiveAciTuples( proxy, destTuples, oriChildName, entry );
         addEntryAciTuples( destTuples, entry );
         addSubentryAciTuples( proxy, destTuples, oriChildName, entry );
         engine.checkPermission( proxy, userGroups, user.getJndiName(), user.getAuthenticationLevel(),
-                oriChildName, null, null, Collections.singleton( MicroOperation.IMPORT ),
tuples, entry );
+                oriChildName, null, null, IMPORT_PERMS, tuples, entry );
 
 //        if ( deleteOldRn )
 //        {
@@ -742,14 +772,14 @@
         addSubentryAciTuples( proxy, tuples, oriChildName, entry );
 
         engine.checkPermission( proxy, userGroups, user.getJndiName(), user.getAuthenticationLevel(),
-                oriChildName, null, null, Collections.singleton( MicroOperation.EXPORT ),
tuples, entry );
+                oriChildName, null, null, EXPORT_PERMS, tuples, entry );
 
         Collection destTuples = new HashSet();
         addPerscriptiveAciTuples( proxy, destTuples, oriChildName, entry );
         addEntryAciTuples( destTuples, entry );
         addSubentryAciTuples( proxy, destTuples, oriChildName, entry );
         engine.checkPermission( proxy, userGroups, user.getJndiName(), user.getAuthenticationLevel(),
-                oriChildName, null, null, Collections.singleton( MicroOperation.IMPORT ),
tuples, entry );
+                oriChildName, null, null, IMPORT_PERMS, tuples, entry );
 
         next.move( oriChildName, newParentName );
         tupleCache.subentryRenamed( oriChildName, newName );
@@ -792,7 +822,6 @@
 
     public boolean compare( NextInterceptor next, Name name, String oid, Object value ) 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();
@@ -810,31 +839,68 @@
         addSubentryAciTuples( proxy, tuples, name, entry );
 
         engine.checkPermission( proxy, userGroups, user.getJndiName(), user.getAuthenticationLevel(),
name, null,
-                null, Collections.singleton( MicroOperation.READ ), tuples, entry );
+                null, READ_PERMS, tuples, entry );
         engine.checkPermission( proxy, userGroups, user.getJndiName(), user.getAuthenticationLevel(),
name, oid,
-                value, Collections.singleton( MicroOperation.COMPARE ), tuples, entry );
+                value, COMPARE_PERMS, tuples, entry );
 
         return next.compare( name, oid, value );
     }
 
 
-    public void cacheNewGroup( String upName, Name normName, Attributes entry ) throws NamingException
+    public Name getMatchedName( NextInterceptor next, Name dn, boolean normalized ) throws
NamingException
     {
-        this.groupCache.groupAdded( upName, normName, entry );
+        // Access the principal requesting the operation, and bypass checks if it is the
admin
+        Invocation invocation = InvocationStack.getInstance().peek();
+        DirectoryPartitionNexusProxy proxy = invocation.getProxy();
+        LdapPrincipal user = ( ( ServerContext ) invocation.getCaller() ).getPrincipal();
+        if ( user.getName().equalsIgnoreCase( DirectoryPartitionNexus.ADMIN_PRINCIPAL ) ||
! enabled )
+        {
+            return next.getMatchedName( dn, normalized );
+        }
+
+        // get the present matched name
+        Attributes entry;
+        Name matched = next.getMatchedName( dn, normalized );
+
+        // check if we have disclose on error permission for the entry at the matched dn
+        // if not remove rdn and check that until nothing is left in the name and return
+        // that but if permission is granted then short the process and return the dn
+        while ( matched.size() > 0 )
+        {
+            if ( normalized )
+            {
+                entry = proxy.lookup( matched, DirectoryPartitionNexusProxy.GETMATCHEDDN_BYPASS
);
+            }
+            else
+            {
+                entry = proxy.lookup( matched, DirectoryPartitionNexusProxy.LOOKUP_BYPASS
);
+            }
+
+            Set userGroups = groupCache.getGroups( user.getName() );
+            Collection tuples = new HashSet();
+            addPerscriptiveAciTuples( proxy, tuples, matched, entry );
+            addEntryAciTuples( tuples, entry );
+            addSubentryAciTuples( proxy, tuples, matched, entry );
+
+            if ( engine.hasPermission( proxy, userGroups, user.getJndiName(),
+                    user.getAuthenticationLevel(), matched, null, null,
+                    MATCHEDNAME_PERMS, tuples, entry ) )
+            {
+                return matched;
+            }
+
+            matched.remove( matched.size() - 1 );
+        }
+
+        return matched;
     }
 
 
-    /** @todo move this up and add more collections that can be made constants */
-    private static final Collection SEARCH_ENTRY_PERMS;
-    private static final Collection SEARCH_ATTRVAL_PERMS;
-    static
+    public void cacheNewGroup( String upName, Name normName, Attributes entry ) throws NamingException
     {
-        HashSet set = new HashSet( 2 );
-        set.add( MicroOperation.BROWSE );
-        set.add( MicroOperation.RETURN_DN );
-        SEARCH_ENTRY_PERMS = Collections.unmodifiableCollection( set );
-        SEARCH_ATTRVAL_PERMS = Collections.singleton( MicroOperation.READ );
+        this.groupCache.groupAdded( upName, normName, entry );
     }
+
 
     private boolean filter( Invocation invocation, Name normName, SearchResult result ) throws
NamingException
     {

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=326825&r1=326824&r2=326825&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
Wed Oct 19 22:09:43 2005
@@ -29,11 +29,14 @@
 import org.apache.ldap.common.message.ResultCodeEnum;
 import org.apache.ldap.common.name.LdapName;
 import org.apache.ldap.server.DirectoryServiceConfiguration;
+import org.apache.ldap.server.invocation.Invocation;
+import org.apache.ldap.server.invocation.InvocationStack;
 import org.apache.ldap.server.configuration.InterceptorConfiguration;
 import org.apache.ldap.server.interceptor.BaseInterceptor;
 import org.apache.ldap.server.interceptor.NextInterceptor;
 import org.apache.ldap.server.partition.DirectoryPartition;
 import org.apache.ldap.server.partition.DirectoryPartitionNexus;
+import org.apache.ldap.server.partition.DirectoryPartitionNexusProxy;
 
 
 /**
@@ -302,8 +305,8 @@
      * LdapException.
      */
     public void move( NextInterceptor nextInterceptor,
-            Name oriChildName, Name newParentName, String newRn,
-            boolean deleteOldRn ) throws NamingException
+                      Name oriChildName, Name newParentName, String newRn,
+                      boolean deleteOldRn ) throws NamingException
     {
         // check if child to move exists
         String msg = "Attempt to move to non-existant parent: ";
@@ -332,9 +335,9 @@
     /**
      * Checks to see the entry being searched exists, otherwise throws the appropriate LdapException.
      */
-    public NamingEnumeration search( NextInterceptor nextInterceptor, 
-            Name base, Map env, ExprNode filter,
-            SearchControls searchCtls ) throws NamingException
+    public NamingEnumeration search( NextInterceptor nextInterceptor,
+                                     Name base, Map env, ExprNode filter,
+                                     SearchControls searchCtls ) throws NamingException
     {
         String msg = "Attempt to search under non-existant entry: ";
 
@@ -365,6 +368,8 @@
      */
     private void assertHasEntry( NextInterceptor nextInterceptor, String msg, Name dn ) throws
NamingException
     {
+        Invocation invocation = InvocationStack.getInstance().peek();
+        DirectoryPartitionNexusProxy proxy = invocation.getProxy();
         if ( !nextInterceptor.hasEntry( dn ) )
         {
             LdapNameNotFoundException e = null;
@@ -378,7 +383,7 @@
                 e = new LdapNameNotFoundException( dn.toString() );
             }
 
-            e.setResolvedName( nextInterceptor.getMatchedName( dn, false ) );
+            e.setResolvedName( proxy.getMatchedName( dn, false ) );
             throw e;
         }
     }

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=326825&r1=326824&r2=326825&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
Wed Oct 19 22:09:43 2005
@@ -56,6 +56,8 @@
 {
     /** safe to use set of bypass instructions to lookup raw entries */
     public static final Collection LOOKUP_BYPASS;
+    /** safe to use set of bypass instructions to getMatchedDn */
+    public static final Collection GETMATCHEDDN_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 */
@@ -84,6 +86,16 @@
         c.add( "operationalAttributeService" );
         c.add( "eventService" );
         LOOKUP_BYPASS = Collections.unmodifiableCollection( c );
+
+        c = new HashSet();
+        c.add( "authenticationService" );
+        c.add( "authorizationService" );
+        c.add( "oldAuthorizationService" );
+        c.add( "schemaService" );
+        c.add( "subentryService" );
+        c.add( "operationalAttributeService" );
+        c.add( "eventService" );
+        GETMATCHEDDN_BYPASS = Collections.unmodifiableCollection( c );
     }
 
 

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=326825&r1=326824&r2=326825&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
Wed Oct 19 22:09:43 2005
@@ -822,4 +822,65 @@
         // now we should not be able to access the subentry with a search
         assertNull( checkCanSearhSubentryAs( "billyd", "billyd", new LdapName( "cn=anybodySearch"
) ) );
     }
+
+
+    public void testGetMatchedName() throws  NamingException
+    {
+        // create the non-admin user
+        createUser( "billyd", "billyd" );
+
+        // now add a subentry that enables anyone to search/lookup and disclose on error
+        // below ou=system, with the exclusion of ou=groups and everything below it
+        createAccessControlSubentry( "selectiveDiscloseOnError",
+                "{ specificExclusions { chopBefore:\"ou=groups\" } }",
+                "{ " +
+                "identificationTag \"searchAci\", " +
+                "precedence 14, " +
+                "authenticationLevel none, " +
+                "itemOrUserFirst userFirst: { " +
+                "userClasses { allUsers }, " +
+                "userPermissions { { " +
+                "protectedItems {entry, allUserAttributeTypesAndValues}, " +
+                "grantsAndDenials { grantRead, grantReturnDN, grantBrowse, grantDiscloseOnError
} } } } }" );
+
+        // get a context as the user and try a lookup of a non-existant entry under ou=groups,ou=system
+        DirContext userCtx = getContextAs( new LdapName( "uid=billyd,ou=users,ou=system"
), "billyd" );
+        try
+        {
+            userCtx.lookup( "cn=blah,ou=groups" );
+        }
+        catch( NamingException e )
+        {
+            Name matched = e.getResolvedName();
+
+            // we should not see ou=groups,ou=system for the remaining name
+            assertEquals( matched.toString(), "ou=system" );
+        }
+
+        // now delete and replace subentry with one that does not excluse ou=groups,ou=system
+        deleteAccessControlSubentry( "selectiveDiscloseOnError" );
+        createAccessControlSubentry( "selectiveDiscloseOnError",
+                "{ " +
+                "identificationTag \"searchAci\", " +
+                "precedence 14, " +
+                "authenticationLevel none, " +
+                "itemOrUserFirst userFirst: { " +
+                "userClasses { allUsers }, " +
+                "userPermissions { { " +
+                "protectedItems {entry, allUserAttributeTypesAndValues}, " +
+                "grantsAndDenials { grantRead, grantReturnDN, grantBrowse, grantDiscloseOnError
} } } } }" );
+
+        // now try a lookup of a non-existant entry under ou=groups,ou=system again
+        try
+        {
+            userCtx.lookup( "cn=blah,ou=groups" );
+        }
+        catch( NamingException e )
+        {
+            Name matched = e.getResolvedName();
+
+            // we should not see ou=groups,ou=system for the remaining name
+            assertEquals( matched.toString(), "ou=groups,ou=system" );
+        }
+    }
 }



Mime
View raw message