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 <a href="http://www.faqs.org/rfcs/rfc3045.html">Vendor
Information</a>
*/
- 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 <a href="mailto:[EMAIL PROTECTED]">Apache Directory Project</a>
+ * @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 );
+ }
+}