Return-Path: Delivered-To: apmail-incubator-directory-cvs-archive@www.apache.org Received: (qmail 62101 invoked from network); 3 Nov 2004 04:20:06 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (209.237.227.199) by minotaur-2.apache.org with SMTP; 3 Nov 2004 04:20:06 -0000 Received: (qmail 22096 invoked by uid 500); 3 Nov 2004 04:20:06 -0000 Delivered-To: apmail-incubator-directory-cvs-archive@incubator.apache.org Received: (qmail 22041 invoked by uid 500); 3 Nov 2004 04:20:05 -0000 Mailing-List: contact directory-cvs-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: directory-dev@incubator.apache.org Delivered-To: mailing list directory-cvs@incubator.apache.org Received: (qmail 22020 invoked by uid 99); 3 Nov 2004 04:20:05 -0000 X-ASF-Spam-Status: No, hits=-10.0 required=10.0 tests=ALL_TRUSTED,NO_REAL_NAME X-Spam-Check-By: apache.org Received: from [209.237.227.194] (HELO minotaur.apache.org) (209.237.227.194) by apache.org (qpsmtpd/0.28) with SMTP; Tue, 02 Nov 2004 20:20:01 -0800 Received: (qmail 61979 invoked by uid 65534); 3 Nov 2004 04:19:54 -0000 Date: 3 Nov 2004 04:19:54 -0000 Message-ID: <20041103041954.61975.qmail@minotaur.apache.org> From: akarasulu@apache.org To: directory-cvs@incubator.apache.org Subject: svn commit: rev 56471 - in incubator/directory/eve/trunk/jndi-provider/src: java/org/apache/eve java/org/apache/eve/jndi java/org/apache/eve/jndi/ibs test/org/apache/eve/jndi X-Virus-Checked: Checked X-Spam-Rating: minotaur-2.apache.org 1.6.2 0/1000/N Author: akarasulu Date: Tue Nov 2 20:19:53 2004 New Revision: 56471 Added: incubator/directory/eve/trunk/jndi-provider/src/test/org/apache/eve/jndi/RootDSETest.java Modified: incubator/directory/eve/trunk/jndi-provider/src/java/org/apache/eve/RootNexus.java incubator/directory/eve/trunk/jndi-provider/src/java/org/apache/eve/jndi/EveContext.java incubator/directory/eve/trunk/jndi-provider/src/java/org/apache/eve/jndi/EveContextFactory.java incubator/directory/eve/trunk/jndi-provider/src/java/org/apache/eve/jndi/ibs/AuthorizationService.java incubator/directory/eve/trunk/jndi-provider/src/java/org/apache/eve/jndi/ibs/OperationalAttributeService.java Log: Changes ... o added authorization code to reject alterations to root DSE in authorization service before calls even reach the target nexus o added root DSE attribute to the nexus o implemented nexus' getRootDSE method and added some code to add to the namingContexts attribute of the rootDSE as more ContextPartitions are registered with the system o also added the vendorName attribute to rootDSE in constructor which is proudly fixed at "Apache Software Foundation" o added hooks to catch lookups and hasEntry calls for the rootDSE Note: o note that lookup(Name) will return empty Attributes since all attributes in the DSE are operational and these are filtered out by the op attr service interceptor o the lookup(Name,String) method is the only one that returns attributes when they are explicitly asked for o other methods are protected by the authorization service: basically no alterations are allowed on the root DSE! Modified: incubator/directory/eve/trunk/jndi-provider/src/java/org/apache/eve/RootNexus.java ============================================================================== --- incubator/directory/eve/trunk/jndi-provider/src/java/org/apache/eve/RootNexus.java (original) +++ incubator/directory/eve/trunk/jndi-provider/src/java/org/apache/eve/RootNexus.java Tue Nov 2 20:19:53 2004 @@ -27,9 +27,13 @@ import javax.naming.NameNotFoundException; import javax.naming.directory.SearchControls; import javax.naming.directory.ModificationItem; +import javax.naming.directory.Attribute; import org.apache.ldap.common.filter.ExprNode; import org.apache.ldap.common.NotImplementedException; +import org.apache.ldap.common.message.LockableAttributeImpl; +import org.apache.ldap.common.message.LockableAttributes; +import org.apache.ldap.common.message.LockableAttributesImpl; /** @@ -43,6 +47,12 @@ */ public class RootNexus implements PartitionNexus { + /** the vendorName string proudly set to: Apache Software Foundation*/ + private static final String ASF = "Apache Software Foundation"; + /** the vendorName DSE operational attribute */ + private static final String VENDORNAME_ATTR = "vendorName"; + /** the namingContexts DSE operational attribute */ + private static final String NAMINGCTXS_ATTR = "namingContexts"; /** Handle on the singleton instance of this class within the entire JVM. */ private static RootNexus s_singleton = null; @@ -50,13 +60,19 @@ private SystemPartition system; /** the backends keyed by normalized suffix strings */ private HashMap backends = new HashMap(); - - + /** the read only rootDSE attributes */ + private final Attributes rootDSE; + + /** - * Default constructor that checks to make sure that there is only one - * instance of this class within the entire JVM. + * Creates the root nexus singleton of the entire system. The root DSE has + * several attributes that are injected into it besides those that may + * already exist. As partitions are added to the system more namingContexts + * attributes are added to the rootDSE. + * + * @see Vendor Information */ - public RootNexus( SystemPartition system ) + public RootNexus( SystemPartition system, Attributes rootDSE ) { if ( null != s_singleton ) { @@ -65,6 +81,18 @@ s_singleton = this; this.system = system; + + // setup that root DSE + this.rootDSE = rootDSE; + Attribute attr = new LockableAttributeImpl( NAMINGCTXS_ATTR ); + attr.add( "" ); + rootDSE.put( attr ); + + attr = new LockableAttributeImpl( VENDORNAME_ATTR ); + attr.add( ASF ); + rootDSE.put( attr ); + + // register will add to the list of namingContexts as well register( this.system ); } @@ -107,8 +135,7 @@ /** * @see PartitionNexus#listSuffixes(boolean) */ - public Iterator listSuffixes( boolean normalized ) - throws NamingException + public Iterator listSuffixes( boolean normalized ) throws NamingException { return Collections.unmodifiableSet( backends.keySet() ).iterator(); } @@ -121,7 +148,7 @@ */ public Attributes getRootDSE() { - throw new NotImplementedException(); + return rootDSE; } @@ -131,6 +158,8 @@ */ public void register( ContextPartition backend ) { + Attribute namingContexts = rootDSE.get( NAMINGCTXS_ATTR ); + namingContexts.add( backend.getSuffix( false ).toString() ); backends.put( backend.getSuffix( true ).toString(), backend ); } @@ -141,6 +170,8 @@ */ public void unregister( ContextPartition backend ) { + Attribute namingContexts = rootDSE.get( NAMINGCTXS_ATTR ); + namingContexts.remove( backend.getSuffix( false ).toString() ); backends.remove( backend.getSuffix( true ).toString() ); } @@ -224,6 +255,13 @@ */ public Attributes lookup( Name dn ) throws NamingException { + if ( dn.size() == 0 ) + { + LockableAttributes retval = ( LockableAttributes ) rootDSE.clone(); + retval.setLocked( true ); + return retval; + } + ContextPartition backend = getBackend( dn ); return backend.lookup( dn ); } @@ -234,6 +272,21 @@ */ public Attributes lookup( Name dn, String[] attrIds ) throws NamingException { + if ( dn.size() == 0 ) + { + LockableAttributes retval = new LockableAttributesImpl(); + NamingEnumeration list = rootDSE.getIDs(); + while ( list.hasMore() ) + { + String id = ( String ) list.next(); + Attribute attr = rootDSE.get( id ); + retval.put( ( Attribute ) attr.clone() ); + } + + retval.setLocked( true ); + return retval; + } + ContextPartition backend = getBackend( dn ); return backend.lookup( dn, attrIds ); } @@ -244,6 +297,11 @@ */ public boolean hasEntry( Name dn ) throws NamingException { + if ( dn.size() == 0 ) + { + return true; + } + ContextPartition backend = getBackend( dn ); return backend.hasEntry( dn ); } Modified: incubator/directory/eve/trunk/jndi-provider/src/java/org/apache/eve/jndi/EveContext.java ============================================================================== --- incubator/directory/eve/trunk/jndi-provider/src/java/org/apache/eve/jndi/EveContext.java (original) +++ incubator/directory/eve/trunk/jndi-provider/src/java/org/apache/eve/jndi/EveContext.java Tue Nov 2 20:19:53 2004 @@ -28,6 +28,7 @@ import org.apache.ldap.common.filter.PresenceNode; import org.apache.ldap.common.util.NamespaceTools; import org.apache.ldap.common.message.LockableAttributesImpl; +import org.apache.ldap.common.exception.LdapNoPermissionException; import org.apache.eve.PartitionNexus; import org.apache.eve.auth.LdapPrincipal; @@ -305,6 +306,12 @@ public void destroySubcontext( Name name ) throws NamingException { Name target = buildTarget( name ); + + if ( target.size() == 0 ) + { + throw new LdapNoPermissionException( "can't delete the rootDSE" ); + } + nexusProxy.delete( target ); } @@ -364,6 +371,12 @@ { Name oldDn = buildTarget( oldName ); Name newDn = buildTarget( newName ); + + if ( oldDn.size() == 0 ) + { + throw new LdapNoPermissionException( "can't rename the rootDSE" ); + } + Name oldBase = oldName.getSuffix( 1 ); Name newBase = newName.getSuffix( 1 ); Modified: incubator/directory/eve/trunk/jndi-provider/src/java/org/apache/eve/jndi/EveContextFactory.java ============================================================================== --- incubator/directory/eve/trunk/jndi-provider/src/java/org/apache/eve/jndi/EveContextFactory.java (original) +++ incubator/directory/eve/trunk/jndi-provider/src/java/org/apache/eve/jndi/EveContextFactory.java Tue Nov 2 20:19:53 2004 @@ -42,7 +42,6 @@ import org.apache.eve.RootNexus; import org.apache.eve.SystemPartition; import org.apache.eve.ApplicationPartition; -import org.apache.ldap.common.exception.LdapConfigurationException; import org.apache.eve.jndi.ibs.*; import org.apache.eve.db.*; import org.apache.eve.db.jdbm.JdbmDatabase; @@ -361,7 +360,7 @@ system = new SystemPartition( db, eng, attributes ); globalRegistries = new GlobalRegistries( system, bootstrapRegistries ); - nexus = new RootNexus( system ); + nexus = new RootNexus( system, new LockableAttributesImpl() ); provider = new EveJndiProvider( nexus ); Modified: incubator/directory/eve/trunk/jndi-provider/src/java/org/apache/eve/jndi/ibs/AuthorizationService.java ============================================================================== --- incubator/directory/eve/trunk/jndi-provider/src/java/org/apache/eve/jndi/ibs/AuthorizationService.java (original) +++ incubator/directory/eve/trunk/jndi-provider/src/java/org/apache/eve/jndi/ibs/AuthorizationService.java Tue Nov 2 20:19:53 2004 @@ -32,7 +32,6 @@ import org.apache.eve.jndi.*; import org.apache.ldap.common.name.NameComponentNormalizer; import org.apache.ldap.common.name.DnParser; -import org.apache.ldap.common.exception.LdapNoPermissionException; /** @@ -94,6 +93,12 @@ { Name principalDn = getPrincipal( invocation ).getDn(); + if ( name.toString().equals( "" ) ) + { + String msg = "The rootDSE cannot be deleted!"; + throw new LdapNoPermissionException( msg ); + } + if ( name == ADMIN_DN || name.equals( ADMIN_DN ) ) { String msg = "User " + principalDn; @@ -177,6 +182,12 @@ { Name principalDn = getPrincipal( invocation ).getDn(); + if ( dn.toString().equals( "" ) ) + { + String msg = "The rootDSE cannot be modified!"; + throw new LdapNoPermissionException( msg ); + } + if ( ! principalDn.equals( ADMIN_DN ) ) { if ( dn == ADMIN_DN || dn.equals( ADMIN_DN ) ) @@ -244,6 +255,12 @@ if ( invocation.getState() == InvocationStateEnum.PREINVOCATION ) { Name principalDn = getPrincipal( invocation ).getDn(); + + if ( dn.toString().equals( "" ) ) + { + String msg = "The rootDSE cannot be moved or renamed!"; + throw new LdapNoPermissionException( msg ); + } if ( dn == ADMIN_DN || dn.equals( ADMIN_DN ) ) { Modified: incubator/directory/eve/trunk/jndi-provider/src/java/org/apache/eve/jndi/ibs/OperationalAttributeService.java ============================================================================== --- incubator/directory/eve/trunk/jndi-provider/src/java/org/apache/eve/jndi/ibs/OperationalAttributeService.java (original) +++ incubator/directory/eve/trunk/jndi-provider/src/java/org/apache/eve/jndi/ibs/OperationalAttributeService.java Tue Nov 2 20:19:53 2004 @@ -275,6 +275,4 @@ } return true; } - - } Added: incubator/directory/eve/trunk/jndi-provider/src/test/org/apache/eve/jndi/RootDSETest.java ============================================================================== --- (empty file) +++ incubator/directory/eve/trunk/jndi-provider/src/test/org/apache/eve/jndi/RootDSETest.java Tue Nov 2 20:19:53 2004 @@ -0,0 +1,286 @@ +/* + * 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.eve.jndi; + + +import java.util.Hashtable; +import java.io.File; +import java.io.IOException; + +import javax.naming.Context; +import javax.naming.InitialContext; +import javax.naming.NamingException; +import javax.naming.directory.Attributes; +import javax.naming.directory.DirContext; +import javax.naming.directory.ModificationItem; + +import junit.framework.TestCase; +import org.apache.commons.io.FileUtils; +import org.apache.ldap.common.exception.LdapNoPermissionException; + + +/** + * Testing RootDSE lookups and context creation using the empty string. + * + * @author Apache Directory Project + * @version $Rev$ + */ +public class RootDSETest extends TestCase +{ + /** flag whether to delete database files for each test or not */ + protected boolean doDelete = true; + + + /** + * Get's the initial context factory for the provider's ou=system context + * root. + * + * @see junit.framework.TestCase#setUp() + */ + protected void setUp() throws Exception + { + super.setUp(); + doDelete( new File( "target" + File.separator + "eve" ) ); + } + + + /** + * Deletes the Eve working directory. + * + * @throws java.io.IOException if there are failures while deleting. + */ + protected void doDelete( File wkdir ) throws IOException + { + if ( doDelete ) + { + if ( wkdir.exists() ) + { + FileUtils.deleteDirectory( wkdir ); + } + } + } + + + /** + * Sets the system context root to null. + * + * @see junit.framework.TestCase#tearDown() + */ + protected void tearDown() throws Exception + { + super.tearDown(); + Hashtable env = new Hashtable(); + env.put( Context.PROVIDER_URL, "ou=system" ); + env.put( Context.INITIAL_CONTEXT_FACTORY, "org.apache.eve.jndi.EveContextFactory" ); + env.put( EveContextFactory.SHUTDOWN_OP_ENV, "" ); + env.put( Context.SECURITY_PRINCIPAL, "uid=admin,ou=system" ); + env.put( Context.SECURITY_CREDENTIALS, "testing" ); + try { new InitialContext( env ); } catch( Exception e ) {} + } + + + /** + * Creates an initial context using the empty string for the provider URL. + * This should work. + * + * @throws NamingException if there are any problems + */ + public void testGetInitialContext() throws NamingException + { + Hashtable env = new Hashtable(); + env.put( EveContextFactory.WKDIR_ENV, "target/eve" ); + env.put( Context.PROVIDER_URL, "" ); + env.put( Context.INITIAL_CONTEXT_FACTORY, EveContextFactory.class.getName() ); + InitialContext initCtx = new InitialContext( env ); + assertNotNull( initCtx ); + } + + + /** + * Gets a DirContext from the InitialContext for the empty string or RootDSE + * and checks that none of the operational attributes are returned. + * + * @throws NamingException if there are any problems + */ + public void testGetInitialContextLookupAttributes() throws NamingException + { + Hashtable env = new Hashtable(); + env.put( EveContextFactory.WKDIR_ENV, "target/eve" ); + env.put( Context.PROVIDER_URL, "" ); + env.put( Context.INITIAL_CONTEXT_FACTORY, EveContextFactory.class.getName() ); + InitialContext initCtx = new InitialContext( env ); + assertNotNull( initCtx ); + + DirContext ctx = ( DirContext ) initCtx.lookup( "" ); + Attributes attributes = ctx.getAttributes( "" ); + assertEquals( 0, attributes.size() ); + } + + + /** + * Checks for namingContexts and vendorName attributes. + * + * @throws NamingException if there are any problems + */ + public void testGetInitialContextLookupAttributesByName() throws NamingException + { + Hashtable env = new Hashtable(); + env.put( EveContextFactory.WKDIR_ENV, "target/eve" ); + env.put( Context.PROVIDER_URL, "" ); + env.put( Context.INITIAL_CONTEXT_FACTORY, EveContextFactory.class.getName() ); + InitialContext initCtx = new InitialContext( env ); + assertNotNull( initCtx ); + + DirContext ctx = ( DirContext ) initCtx.lookup( "" ); + Attributes attributes = ctx.getAttributes( "", + new String[]{ "namingContexts", "vendorName" }); + assertEquals( 2, attributes.size() ); + assertEquals( "Apache Software Foundation", attributes.get( "vendorName" ).get() ); + assertTrue( attributes.get( "namingContexts" ).contains( "" ) ); + assertTrue( attributes.get( "namingContexts" ).contains( "ou=system" ) ); + } + + + /** + * Checks for lack of permissions to delete this entry. + * + * @throws NamingException if there are any problems + */ + public void testDelete() throws NamingException + { + Hashtable env = new Hashtable(); + env.put( EveContextFactory.WKDIR_ENV, "target/eve" ); + env.put( Context.PROVIDER_URL, "" ); + env.put( Context.INITIAL_CONTEXT_FACTORY, EveContextFactory.class.getName() ); + InitialContext initCtx = new InitialContext( env ); + assertNotNull( initCtx ); + + DirContext ctx = ( DirContext ) initCtx.lookup( "" ); + + LdapNoPermissionException notNull = null; + + try + { + ctx.destroySubcontext( "" ); + fail( "we should never get here" ); + } + catch ( LdapNoPermissionException e ) + { + notNull = e; + } + + assertNotNull( notNull ); + } + + + /** + * Checks for lack of permissions to rename or move this entry. + * + * @throws NamingException if there are any problems + */ + public void testRename() throws NamingException + { + Hashtable env = new Hashtable(); + env.put( EveContextFactory.WKDIR_ENV, "target/eve" ); + env.put( Context.PROVIDER_URL, "" ); + env.put( Context.INITIAL_CONTEXT_FACTORY, EveContextFactory.class.getName() ); + InitialContext initCtx = new InitialContext( env ); + assertNotNull( initCtx ); + + DirContext ctx = ( DirContext ) initCtx.lookup( "" ); + + LdapNoPermissionException notNull = null; + + try + { + ctx.rename( "", "ou=system" ); + fail( "we should never get here" ); + } + catch ( LdapNoPermissionException e ) + { + notNull = e; + } + + assertNotNull( notNull ); + } + + + /** + * Checks for lack of permissions to modify this entry. + * + * @throws NamingException if there are any problems + */ + public void testModify() throws NamingException + { + Hashtable env = new Hashtable(); + env.put( EveContextFactory.WKDIR_ENV, "target/eve" ); + env.put( Context.PROVIDER_URL, "" ); + env.put( Context.INITIAL_CONTEXT_FACTORY, EveContextFactory.class.getName() ); + InitialContext initCtx = new InitialContext( env ); + assertNotNull( initCtx ); + + DirContext ctx = ( DirContext ) initCtx.lookup( "" ); + + LdapNoPermissionException notNull = null; + + try + { + ctx.modifyAttributes( "", 0, null ); + fail( "we should never get here" ); + } + catch ( LdapNoPermissionException e ) + { + notNull = e; + } + + assertNotNull( notNull ); + } + + + + + /** + * Checks for lack of permissions to modify this entry. + * + * @throws NamingException if there are any problems + */ + public void testModify2() throws NamingException + { + Hashtable env = new Hashtable(); + env.put( EveContextFactory.WKDIR_ENV, "target/eve" ); + env.put( Context.PROVIDER_URL, "" ); + env.put( Context.INITIAL_CONTEXT_FACTORY, EveContextFactory.class.getName() ); + InitialContext initCtx = new InitialContext( env ); + assertNotNull( initCtx ); + + DirContext ctx = ( DirContext ) initCtx.lookup( "" ); + + LdapNoPermissionException notNull = null; + + try + { + ctx.modifyAttributes( "", new ModificationItem[]{} ); + fail( "we should never get here" ); + } + catch ( LdapNoPermissionException e ) + { + notNull = e; + } + + assertNotNull( notNull ); + } +}