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/04 06:03:03 UTC
svn commit: r293515 - in
/directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz:
AuthorizationService.java GroupCache.java TupleCache.java
Author: akarasulu
Date: Mon Oct 3 21:02:57 2005
New Revision: 293515
URL: http://svn.apache.org/viewcvs?rev=293515&view=rev
Log:
changes ...
o added new group tracking cache for rapidly looking up group membership
for making groupwise AC decisions
o fixed a bug in TupleCache that will cause NPE
o added lookup method for Tuple sets in TupleCache
Added:
directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/GroupCache.java (with props)
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/authz/TupleCache.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=293515&r1=293514&r2=293515&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 Mon Oct 3 21:02:57 2005
@@ -27,12 +27,10 @@
import org.apache.ldap.server.invocation.InvocationStack;
import org.apache.ldap.server.authn.LdapPrincipal;
import org.apache.ldap.common.filter.ExprNode;
-import org.apache.ldap.common.aci.AuthenticationLevel;
import javax.naming.Name;
import javax.naming.NamingException;
import javax.naming.NamingEnumeration;
-import javax.naming.Context;
import javax.naming.directory.Attributes;
import javax.naming.directory.ModificationItem;
import javax.naming.directory.SearchControls;
@@ -50,8 +48,10 @@
{
/** the partition nexus */
private ContextPartitionNexus nexus;
- /** a cache that responds to add, delete, and modify attempts */
- private TupleCache cache;
+ /** a tupleCache that responds to add, delete, and modify attempts */
+ private TupleCache tupleCache;
+ /** a groupCache that responds to add, delete, and modify attempts */
+ private GroupCache groupCache;
/** use and instance of the ACDF engine */
private ACDFEngine engine;
@@ -61,7 +61,8 @@
super.init( factoryCfg, cfg );
nexus = factoryCfg.getPartitionNexus();
- cache = new TupleCache( factoryCfg );
+ tupleCache = new TupleCache( factoryCfg );
+ groupCache = new GroupCache( factoryCfg );
engine = new ACDFEngine( factoryCfg.getGlobalRegistries().getOidRegistry(),
factoryCfg.getGlobalRegistries().getAttributeTypeRegistry() );
}
@@ -85,7 +86,8 @@
public void add( NextInterceptor next, String upName, Name normName, Attributes entry ) throws NamingException
{
next.add( upName, normName, entry );
- cache.subentryAdded( upName, normName, entry );
+ tupleCache.subentryAdded( upName, normName, entry );
+ groupCache.groupAdded( upName, normName, entry );
ServerContext ctx = ( ServerContext ) InvocationStack.getInstance().peek().getCaller();
LdapPrincipal user = ctx.getPrincipal();
@@ -100,7 +102,8 @@
{
Attributes entry = nexus.lookup( name );
next.delete( name );
- cache.subentryDeleted( name, entry );
+ tupleCache.subentryDeleted( name, entry );
+ groupCache.groupDeleted( name, entry );
}
@@ -108,7 +111,8 @@
{
Attributes entry = nexus.lookup( name );
next.modify( name, modOp, mods );
- cache.subentryModified( name, modOp, mods, entry );
+ tupleCache.subentryModified( name, modOp, mods, entry );
+ groupCache.groupModified( name, modOp, mods, entry );
}
@@ -116,7 +120,8 @@
{
Attributes entry = nexus.lookup( name );
next.modify( name, mods );
- cache.subentryModified( name, mods, entry );
+ tupleCache.subentryModified( name, mods, entry );
+ groupCache.groupModified( name, mods, entry );
}
Added: 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=293515&view=auto
==============================================================================
--- directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/GroupCache.java (added)
+++ directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/GroupCache.java Mon Oct 3 21:02:57 2005
@@ -0,0 +1,374 @@
+/*
+ * 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.name.DnParser;
+import org.apache.ldap.common.name.LdapName;
+import org.apache.ldap.common.filter.SimpleNode;
+import org.apache.ldap.common.filter.BranchNode;
+import org.apache.ldap.server.jndi.ContextFactoryConfiguration;
+import org.apache.ldap.server.schema.ConcreteNameComponentNormalizer;
+import org.apache.ldap.server.partition.ContextPartitionNexus;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.naming.Name;
+import javax.naming.NamingException;
+import javax.naming.NamingEnumeration;
+import javax.naming.directory.*;
+import java.util.*;
+
+
+/**
+ * A cache for tracking static group membership.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$
+ */
+public class GroupCache
+{
+ /** the attribute id for an object class: objectClass */
+ private static final String OC_ATTR = "objectClass";
+ /** the member attribute for a groupOfNames: member */
+ private static final String MEMBER_ATTR = "member";
+ /** the member attribute for a groupOfUniqueNames: uniqueMember */
+ private static final String UNIQUEMEMBER_ATTR = "uniqueMember";
+ /** the groupOfNames objectClass: groupOfNames */
+ private static final String GROUPOFNAMES_OC = "groupOfNames";
+ /** the groupOfUniqueNames objectClass: groupOfUniqueNames */
+ private static final String GROUPOFUNIQUENAMES_OC = "groupOfUniqueNames";
+ /** the logger for this class */
+ private static final Logger log = LoggerFactory.getLogger( GroupCache.class );
+
+ /** String key for the DN of a group to a Set (HashSet) for the Strings of member DNs */
+ private final Map groups = new HashMap();
+ /** a handle on the partition nexus */
+ private final ContextPartitionNexus nexus;
+ /** the env to use for searching */
+ private final Hashtable env;
+ /** the normalizing Dn parser for member names */
+ private DnParser parser;
+
+
+ /**
+ * Creates a static group cache.
+ *
+ * @param factoryCfg the context factory configuration for the server
+ */
+ public GroupCache( ContextFactoryConfiguration factoryCfg ) throws NamingException
+ {
+ this.nexus = factoryCfg.getPartitionNexus();
+ this.env = ( Hashtable ) factoryCfg.getEnvironment().clone();
+ this.parser = new DnParser( new ConcreteNameComponentNormalizer(
+ factoryCfg.getGlobalRegistries().getAttributeTypeRegistry() ) );
+ initialize();
+ }
+
+
+ private void initialize() throws NamingException
+ {
+ // search all naming contexts for static groups and generate
+ // normalized sets of members to cache within the map
+
+ BranchNode filter = new BranchNode( BranchNode.OR );
+ filter.addNode( new SimpleNode( OC_ATTR, GROUPOFNAMES_OC, SimpleNode.EQUALITY ) );
+ filter.addNode( new SimpleNode( OC_ATTR, GROUPOFUNIQUENAMES_OC, SimpleNode.EQUALITY ) );
+
+ Iterator suffixes = nexus.listSuffixes( true );
+ while ( suffixes.hasNext() )
+ {
+ String suffix = ( String ) suffixes.next();
+ Name baseDn = new LdapName( suffix );
+ SearchControls ctls = new SearchControls();
+ ctls.setSearchScope( SearchControls.SUBTREE_SCOPE );
+ NamingEnumeration results = nexus.search( baseDn, env, filter, ctls );
+
+ while ( results.hasMore() )
+ {
+ SearchResult result = ( SearchResult ) results.next();
+ String groupDn = result.getName();
+ groupDn = parser.parse( groupDn ).toString();
+ Attribute members = getMemberAttribute( result.getAttributes() );
+
+ if ( members != null )
+ {
+ Set memberSet = new HashSet( members.size() );
+ addMembers( memberSet, members );
+ groups.put( groupDn, memberSet );
+ }
+ else
+ {
+ log.warn( "Found group '" + groupDn + "' without any member or uniqueMember attributes" );
+ }
+ }
+ results.close();
+ }
+ }
+
+
+ /**
+ * Gets the member attribute regardless of whether groupOfNames or
+ * groupOfUniqueNames is used.
+ *
+ * @param entry the entry inspected for member attributes
+ * @return the member attribute
+ */
+ private Attribute getMemberAttribute( Attributes entry )
+ {
+ Attribute oc = entry.get( OC_ATTR );
+
+ if ( oc.contains( GROUPOFNAMES_OC ) )
+ {
+ return entry.get( MEMBER_ATTR );
+ }
+
+ if ( oc.contains( GROUPOFUNIQUENAMES_OC ) )
+ {
+ return entry.get( UNIQUEMEMBER_ATTR );
+ }
+
+ return null;
+ }
+
+
+ /**
+ * Adds normalized member DNs to the set of normalized member names.
+ *
+ * @param memberSet the set of member Dns (Strings)
+ * @param members the member attribute values being added
+ * @throws NamingException if there are problems accessing the attr values
+ */
+ private void addMembers( Set memberSet, Attribute members ) throws NamingException
+ {
+ for ( int ii = 0; ii < members.size(); ii++ )
+ {
+ // get and normalize the DN of the member
+ String memberDn = ( String ) members.get( ii );
+ memberDn = parser.parse( memberDn ).toString();
+ memberSet.add( memberDn );
+ }
+ }
+
+
+ /**
+ * Removes a set of member names from an existing set.
+ *
+ * @param memberSet the set of normalized member DNs
+ * @param members the set of member values
+ * @throws NamingException if there are problems accessing the attr values
+ */
+ private void removeMembers( Set memberSet, Attribute members ) throws NamingException
+ {
+ for ( int ii = 0; ii < members.size(); ii++ )
+ {
+ // get and normalize the DN of the member
+ String memberDn = ( String ) members.get( ii );
+ memberDn = parser.parse( memberDn ).toString();
+ memberSet.remove( memberDn );
+ }
+ }
+
+
+ /**
+ * Adds a groups members to the cache. Called by interceptor to account for new
+ * group additions.
+ *
+ * @param upName the user provided name for the group entry
+ * @param normName the normalized name for the group entry
+ * @param entry the group entry's attributes
+ * @throws NamingException if there are problems accessing the attr values
+ */
+ public void groupAdded( String upName, Name normName, Attributes entry ) throws NamingException
+ {
+ Attribute members = getMemberAttribute( entry );
+
+ if ( members == null )
+ {
+ return;
+ }
+
+ Set memberSet = new HashSet( members.size() );
+ addMembers( memberSet, members );
+ groups.put( normName.toString(), memberSet );
+ }
+
+
+ /**
+ * Deletes a group's members from the cache. Called by interceptor to account for
+ * the deletion of groups.
+ *
+ * @param name the normalized DN of the group entry
+ * @param entry the attributes of entry being deleted
+ */
+ public void groupDeleted( Name name, Attributes entry )
+ {
+ Attribute members = getMemberAttribute( entry );
+
+ if ( members == null )
+ {
+ return;
+ }
+
+ groups.remove( name.toString() );
+ }
+
+
+ /**
+ * Utility method to modify a set of member names based on a modify operation
+ * that changes the members of a group.
+ *
+ * @param memberSet the set of members to be altered
+ * @param modOp the type of modify operation being performed
+ * @param members the members being added, removed or replaced
+ * @throws NamingException if there are problems accessing attribute values
+ */
+ private void modify( Set memberSet, int modOp, Attribute members ) throws NamingException
+ {
+
+ switch ( modOp )
+ {
+ case ( DirContext.ADD_ATTRIBUTE ):
+ addMembers( memberSet, members );
+ break;
+ case ( DirContext.REPLACE_ATTRIBUTE ):
+ if ( members.size() > 0 )
+ {
+ memberSet.clear();
+ addMembers( memberSet, members );
+ }
+ break;
+ case ( DirContext.REMOVE_ATTRIBUTE ):
+ removeMembers( memberSet, members );
+ break;
+ default:
+ throw new InternalError( "Undefined modify operation value of " + modOp );
+ }
+ }
+
+
+ /**
+ * Modifies the cache to reflect changes via modify operations to the group entries.
+ * Called by the interceptor to account for modify ops on groups.
+ *
+ * @param name the normalized name of the group entry modified
+ * @param mods the modification operations being performed
+ * @param entry the group entry being modified
+ * @throws NamingException if there are problems accessing attribute values
+ */
+ public void groupModified( Name name, ModificationItem[] mods, Attributes entry ) throws NamingException
+ {
+ Attribute members = null;
+ String memberAttrId = null;
+ Attribute oc = entry.get( OC_ATTR );
+
+ if ( oc.contains( GROUPOFNAMES_OC ) )
+ {
+ members = entry.get( MEMBER_ATTR );
+ memberAttrId = MEMBER_ATTR;
+ }
+
+ if ( oc.contains( GROUPOFUNIQUENAMES_OC ) )
+ {
+ members = entry.get( UNIQUEMEMBER_ATTR );
+ memberAttrId = UNIQUEMEMBER_ATTR;
+ }
+
+ if ( members == null )
+ {
+ return;
+ }
+
+ for ( int ii = 0; ii < mods.length; ii++ )
+ {
+ if ( memberAttrId.equalsIgnoreCase( mods[ii].getAttribute().getID() ) )
+ {
+ Set memberSet = ( Set ) groups.get( name.toString() );
+ if ( memberSet != null )
+ {
+ modify( memberSet, mods[ii].getModificationOp(), members );
+ }
+ break;
+ }
+ }
+ }
+
+
+ /**
+ * Modifies the cache to reflect changes via modify operations to the group entries.
+ * Called by the interceptor to account for modify ops on groups.
+ *
+ * @param name the normalized name of the group entry modified
+ * @param modOp the modify operation being performed
+ * @param mods the modifications being performed
+ * @param entry the entry being modified
+ * @throws NamingException if there are problems accessing attribute values
+ */
+ public void groupModified( Name name, int modOp, Attributes mods, Attributes entry ) throws NamingException
+ {
+ Attribute members = getMemberAttribute( entry );
+
+ if ( members == null )
+ {
+ return;
+ }
+
+ Set memberSet = ( Set ) groups.get( name.toString() );
+ if ( memberSet != null )
+ {
+ modify( memberSet, modOp, members );
+ }
+ }
+
+
+ /**
+ * Gets the set of groups a user is a member of. The groups are returned
+ * as normalized Name objects within the set.
+ *
+ * @param member the member (user) to get the groups for
+ * @return a Set of Name objects representing the groups
+ * @throws NamingException if there are problems accessing attribute values
+ */
+ public Set getGroups( String member ) throws NamingException
+ {
+ member = parser.parse( member ).toString();
+ Set memberGroups = null;
+
+ Iterator list = groups.keySet().iterator();
+ while ( list.hasNext() )
+ {
+ String group = ( String ) list.next();
+ Set members = ( Set ) groups.get( group );
+ if ( members.contains( member ) )
+ {
+ if ( memberGroups == null )
+ {
+ memberGroups = new HashSet();
+ }
+
+ memberGroups.add( new LdapName( group ) );
+ }
+ }
+
+ if ( memberGroups == null )
+ {
+ return Collections.EMPTY_SET;
+ }
+
+ return memberGroups;
+ }
+}
Propchange: directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/GroupCache.java
------------------------------------------------------------------------------
svn:eol-style = native
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=293515&r1=293514&r2=293515&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 Mon Oct 3 21:02:57 2005
@@ -18,12 +18,7 @@
import java.text.ParseException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Hashtable;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
import javax.naming.Name;
import javax.naming.NamingEnumeration;
@@ -161,7 +156,7 @@
try
{
- aciParser.parse( ( String ) aci.get( ii ) );
+ item = aciParser.parse( ( String ) aci.get( ii ) );
}
catch ( ParseException e )
{
@@ -219,5 +214,16 @@
subentryDeleted( normName, entry );
subentryAdded( normName.toString(), normName, entry );
}
+ }
+
+
+ public List getACITuples( String subentryDn )
+ {
+ List aciTuples = ( List ) tuples.get( subentryDn );
+ if ( aciTuples == null )
+ {
+ return Collections.EMPTY_LIST;
+ }
+ return Collections.unmodifiableList( aciTuples );
}
}