niclas 2004/01/18 17:26:19
Modified: merlin/composition/api/src/java/org/apache/avalon/composition/data
ClassLoaderDirective.java ContainmentProfile.java
merlin/composition/api/src/java/org/apache/avalon/composition/model
ClassLoaderModel.java
merlin/composition/impl/src/java/org/apache/avalon/composition/data/builder
XMLContainmentProfileCreator.java
merlin/composition/impl/src/java/org/apache/avalon/composition/model/impl
DefaultClassLoaderContext.java
DefaultClassLoaderModel.java
Added: merlin/composition/api/src/java/org/apache/avalon/composition/data
GrantDirective.java PermissionDirective.java
merlin/composition/impl/src/test/conf secure-block.xml
merlin/composition/impl/src/test/org/apache/avalon/composition/model/test
SecurityTestCase.java
Log:
The first step towards the codelevel security has been made. The directives are read
from the block.xml into the ClassLoaderModel.
Revision Changes Path
1.3 +16 -3
avalon/merlin/composition/api/src/java/org/apache/avalon/composition/data/ClassLoaderDirective.java
Index: ClassLoaderDirective.java
===================================================================
RCS file:
/home/cvs/avalon/merlin/composition/api/src/java/org/apache/avalon/composition/data/ClassLoaderDirective.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- ClassLoaderDirective.java 28 Oct 2003 12:53:48 -0000 1.2
+++ ClassLoaderDirective.java 19 Jan 2004 01:26:19 -0000 1.3
@@ -73,12 +73,14 @@
*/
private ClasspathDirective m_classpath;
+ private GrantDirective m_grantDirective;
+
/**
* Create an empty ClassloaderDirective.
*/
public ClassLoaderDirective()
{
- this( null, null );
+ this( null, null, null );
}
/**
@@ -86,10 +88,12 @@
*
* @param library the library descriptor
* @param classpath the classpath descriptor
+ * @param grant the security policy declared for the classloader
*/
public ClassLoaderDirective(
final LibraryDirective library,
- final ClasspathDirective classpath )
+ final ClasspathDirective classpath,
+ final GrantDirective grant )
{
if( library == null )
{
@@ -108,6 +112,10 @@
{
m_classpath = classpath;
}
+ if( grant == null )
+ m_grantDirective = new GrantDirective();
+ else
+ m_grantDirective = grant;
}
/**
@@ -140,5 +148,10 @@
public ClasspathDirective getClasspathDirective()
{
return m_classpath;
+ }
+
+ public GrantDirective getGrantDirective()
+ {
+ return m_grantDirective;
}
}
1.4 +2 -2
avalon/merlin/composition/api/src/java/org/apache/avalon/composition/data/ContainmentProfile.java
Index: ContainmentProfile.java
===================================================================
RCS file:
/home/cvs/avalon/merlin/composition/api/src/java/org/apache/avalon/composition/data/ContainmentProfile.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- ContainmentProfile.java 13 Jan 2004 11:41:24 -0000 1.3
+++ ContainmentProfile.java 19 Jan 2004 01:26:19 -0000 1.4
@@ -86,7 +86,7 @@
private static final CategoriesDirective EMPTY_CATEGORIES = new
CategoriesDirective();
private static final ClassLoaderDirective EMPTY_CLASSLOADER =
- new ClassLoaderDirective( new LibraryDirective(), new ClasspathDirective() );
+ new ClassLoaderDirective( new LibraryDirective(), new ClasspathDirective(),
new GrantDirective() );
//========================================================================
// state
1.1
avalon/merlin/composition/api/src/java/org/apache/avalon/composition/data/GrantDirective.java
Index: GrantDirective.java
===================================================================
/*
============================================================================
The Apache Software License, Version 1.1
============================================================================
Copyright (C) 1999-2002 The Apache Software Foundation. All rights reserved.
Redistribution and use in source and binary forms, with or without modifica-
tion, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. The end-user documentation included with the redistribution, if any, must
include the following acknowledgment: "This product includes software
developed by the Apache Software Foundation (http://www.apache.org/)."
Alternately, this acknowledgment may appear in the software itself, if
and wherever such third-party acknowledgments normally appear.
4. The names "Jakarta", "Apache Avalon", "Avalon Framework" and
"Apache Software Foundation" must not be used to endorse or promote
products derived from this software without prior written
permission. For written permission, please contact [EMAIL PROTECTED]
5. Products derived from this software may not be called "Apache", nor may
"Apache" appear in their name, without prior written permission of the
Apache Software Foundation.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This software consists of voluntary contributions made by many individuals
on behalf of the Apache Software Foundation. For more information on the
Apache Software Foundation, please see <http://www.apache.org/>.
*/
package org.apache.avalon.composition.data;
import java.io.Serializable;
/**
* Description of classpath.
*
* @author <a href="mailto:[EMAIL PROTECTED]">Avalon Development Team</a>
* @version $Revision: 1.1 $ $Date: 2004/01/19 01:26:19 $
*/
public final class GrantDirective implements Serializable
{
private static final PermissionDirective[] EMPTY_PERMISSIONSETS = new
PermissionDirective[0];
/**
* The permission directives
*/
private PermissionDirective[] m_permissions;
public GrantDirective()
{
this( null );
}
/**
* Create a GrantDirective instance.
*
* @param permissions the permissions to be included in the grant
*/
public GrantDirective( final PermissionDirective[] permissions )
{
if( permissions == null )
{
m_permissions = EMPTY_PERMISSIONSETS;
}
else
{
m_permissions = permissions;
}
}
/**
* Return the default status of this directive.
*
* If TRUE the enclosed permission directives are empty.
*/
public boolean isEmpty()
{
return m_permissions.length == 0;
}
/**
* Return the set of permission directives.
*
* @return the permission directives
*/
public PermissionDirective[] getPermissionDirectives()
{
return m_permissions;
}
}
1.1
avalon/merlin/composition/api/src/java/org/apache/avalon/composition/data/PermissionDirective.java
Index: PermissionDirective.java
===================================================================
/*
============================================================================
The Apache Software License, Version 1.1
============================================================================
Copyright (C) 1999-2002 The Apache Software Foundation. All rights reserved.
Redistribution and use in source and binary forms, with or without modifica-
tion, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. The end-user documentation included with the redistribution, if any, must
include the following acknowledgment: "This product includes software
developed by the Apache Software Foundation (http://www.apache.org/)."
Alternately, this acknowledgment may appear in the software itself, if
and wherever such third-party acknowledgments normally appear.
4. The names "Jakarta", "Apache Avalon", "Avalon Framework" and
"Apache Software Foundation" must not be used to endorse or promote
products derived from this software without prior written
permission. For written permission, please contact [EMAIL PROTECTED]
5. Products derived from this software may not be called "Apache", nor may
"Apache" appear in their name, without prior written permission of the
Apache Software Foundation.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This software consists of voluntary contributions made by many individuals
on behalf of the Apache Software Foundation. For more information on the
Apache Software Foundation, please see <http://www.apache.org/>.
*/
package org.apache.avalon.composition.data;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.security.Permission;
/**
* Description of classpath.
*
* @author <a href="mailto:[EMAIL PROTECTED]">Avalon Development Team</a>
* @version $Revision: 1.1 $ $Date: 2004/01/19 01:26:19 $
*/
public final class PermissionDirective implements Serializable
{
/** The Permission object **/
private Permission m_permission;
/**
* Create a PermissionDirective instance.
*
* @param classname Permission class
* @param name The name associated with the permission.
* @param action The action associated with the permission. Note that some
* Permissions doesn't support actions.
* @throws InstantiationException if the class could not be instantiated.
* @throws IllegalAccessException, if the class does not have a
* public constructor
* @throws ClassNotFoundException, if the class could not be reached by the
* classloader.
* @throws ClassCastException, if the class is not a subclass of
* java.security.Permission
* @throws InvocationTargetException, if the constructor in the Permission
* class throws an exception.
*/
public PermissionDirective(
final String classname,
final String name,
final String action
)
throws
InstantiationException,
IllegalAccessException,
ClassNotFoundException,
ClassCastException,
InvocationTargetException
{
if( classname == null )
{
throw new NullPointerException( "classname" );
}
ClassLoader trustedClassloader = this.getClass().getClassLoader();
Class clazz = trustedClassloader.loadClass( classname );
Constructor[] constructors = clazz.getConstructors();
if( name == null )
{
m_permission = (Permission) clazz.newInstance();
}
else if( action == null )
{
Constructor cons = getConstructor( constructors, 1 );
Object[] arg = new Object[] { name };
m_permission = (Permission) cons.newInstance( arg );
}
else
{
Constructor cons = getConstructor( constructors, 2 );
Object[] args = new Object[] { name, action };
m_permission = (Permission) cons.newInstance( args );
}
}
/**
* Return the Permission.
*
* @return the fileset directives
*/
public Permission getPermission()
{
return m_permission;
}
private Constructor getConstructor( Constructor[] constructors, int
noOfParameters )
{
for ( int i=0 ; i < constructors.length ; i++ )
{
Class[] params = constructors[i].getParameterTypes();
if( params.length == noOfParameters )
return constructors[i];
}
return null;
}
}
1.2 +14 -1
avalon/merlin/composition/api/src/java/org/apache/avalon/composition/model/ClassLoaderModel.java
Index: ClassLoaderModel.java
===================================================================
RCS file:
/home/cvs/avalon/merlin/composition/api/src/java/org/apache/avalon/composition/model/ClassLoaderModel.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- ClassLoaderModel.java 24 Sep 2003 09:31:15 -0000 1.1
+++ ClassLoaderModel.java 19 Jan 2004 01:26:19 -0000 1.2
@@ -51,6 +51,7 @@
package org.apache.avalon.composition.model;
import java.net.URL;
+import java.security.Permission;
import org.apache.avalon.extension.manager.OptionalPackage;
import org.apache.avalon.extension.manager.ExtensionManager;
@@ -136,4 +137,16 @@
*/
ClassLoaderContext createChildContext(
Logger logger, ContainmentProfile profile, URL[] implied );
+
+ /**
+ * Return the security Permissions defined for this ClassLoaderModel.
+ *
+ * These Permissions will be enforced if code level security is enabled
+ * globally. If no Permissions are returned, all the components under
+ * this container will run without Permissions.
+ *
+ * @return A SecurityPolicy which should be enagaged if codelevel
+ * security is enabled for the Classloader.
+ **/
+ Permission[] getSecurityPermissions();
}
1.5 +46 -3
avalon/merlin/composition/impl/src/java/org/apache/avalon/composition/data/builder/XMLContainmentProfileCreator.java
Index: XMLContainmentProfileCreator.java
===================================================================
RCS file:
/home/cvs/avalon/merlin/composition/impl/src/java/org/apache/avalon/composition/data/builder/XMLContainmentProfileCreator.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- XMLContainmentProfileCreator.java 13 Jan 2004 11:41:25 -0000 1.4
+++ XMLContainmentProfileCreator.java 19 Jan 2004 01:26:19 -0000 1.5
@@ -63,12 +63,14 @@
import org.apache.avalon.composition.data.CategoriesDirective;
import org.apache.avalon.composition.data.ClasspathDirective;
import org.apache.avalon.composition.data.ContainmentProfile;
+import org.apache.avalon.composition.data.DeploymentProfile;
import org.apache.avalon.composition.data.FilesetDirective;
+import org.apache.avalon.composition.data.GrantDirective;
import org.apache.avalon.composition.data.IncludeDirective;
import org.apache.avalon.composition.data.LibraryDirective;
import org.apache.avalon.composition.data.MetaDataException;
import org.apache.avalon.composition.data.NamedComponentProfile;
-import org.apache.avalon.composition.data.DeploymentProfile;
+import org.apache.avalon.composition.data.PermissionDirective;
import org.apache.avalon.composition.data.RepositoryDirective;
import org.apache.avalon.composition.data.ResourceDirective;
import org.apache.avalon.composition.data.ServiceDirective;
@@ -186,9 +188,50 @@
createLibraryDirective( config.getChild( "library", false ) );
ClasspathDirective classpath =
createClasspathDirective( config.getChild( "classpath", false ) );
- return new ClassLoaderDirective( library, classpath );
+ GrantDirective grants =
+ createGrantDirective( config.getChild( "grant" ) );
+ return new ClassLoaderDirective( library, classpath, grants );
}
+ private GrantDirective createGrantDirective( Configuration config )
+ throws ConfigurationException
+ {
+ ArrayList result = new ArrayList();
+ Configuration[] permChildren = config.getChildren( "permission" );
+ for( int i = 0; i < permChildren.length; i++ )
+ {
+ Configuration child = permChildren[i];
+ PermissionDirective perm = createPermissionDirective( child );
+ result.add( perm );
+ }
+ PermissionDirective[] pd = new PermissionDirective[ result.size() ];
+ result.toArray( pd );
+ return new GrantDirective( pd );
+ }
+
+ private PermissionDirective createPermissionDirective( Configuration config )
+ throws ConfigurationException
+ {
+ String classname = config.getAttribute( "class" );
+ String name = config.getAttribute( "name", null );
+ String result = "";
+ Configuration[] actions = config.getChildren( "action" );
+ for( int i=0 ; i < actions.length ; i ++ )
+ {
+ if( i > 0 )
+ result = result + "," + actions[i].getValue();
+ else
+ result = result + actions[i].getValue();
+ }
+ try
+ {
+ return new PermissionDirective( classname, name, result );
+ } catch( Exception e )
+ {
+ throw new ConfigurationException( "Unable to create the Permission
Directive.", e );
+ }
+ }
+
private ClasspathDirective createClasspathDirective( Configuration config )
throws ConfigurationException
{
1.3 +2 -1
avalon/merlin/composition/impl/src/java/org/apache/avalon/composition/model/impl/DefaultClassLoaderContext.java
Index: DefaultClassLoaderContext.java
===================================================================
RCS file:
/home/cvs/avalon/merlin/composition/impl/src/java/org/apache/avalon/composition/model/impl/DefaultClassLoaderContext.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- DefaultClassLoaderContext.java 28 Oct 2003 20:21:00 -0000 1.2
+++ DefaultClassLoaderContext.java 19 Jan 2004 01:26:19 -0000 1.3
@@ -52,6 +52,7 @@
import java.io.File;
import java.net.URL;
+import java.security.Permission;
import org.apache.avalon.composition.model.ClassLoaderContext;
import org.apache.avalon.composition.model.TypeRepository;
1.5 +34 -3
avalon/merlin/composition/impl/src/java/org/apache/avalon/composition/model/impl/DefaultClassLoaderModel.java
Index: DefaultClassLoaderModel.java
===================================================================
RCS file:
/home/cvs/avalon/merlin/composition/impl/src/java/org/apache/avalon/composition/model/impl/DefaultClassLoaderModel.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- DefaultClassLoaderModel.java 16 Dec 2003 01:34:55 -0000 1.4
+++ DefaultClassLoaderModel.java 19 Jan 2004 01:26:19 -0000 1.5
@@ -58,11 +58,14 @@
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLClassLoader;
+import java.security.Permission;
import org.apache.avalon.composition.data.ContainmentProfile;
import org.apache.avalon.composition.data.ClassLoaderDirective;
import org.apache.avalon.composition.data.FilesetDirective;
+import org.apache.avalon.composition.data.GrantDirective;
import org.apache.avalon.composition.data.IncludeDirective;
+import org.apache.avalon.composition.data.PermissionDirective;
import org.apache.avalon.composition.data.RepositoryDirective;
import org.apache.avalon.composition.data.ResourceDirective;
import org.apache.avalon.composition.model.ClassLoaderContext;
@@ -114,7 +117,7 @@
* @version $Revision$ $Date$
*/
public class DefaultClassLoaderModel extends AbstractLogEnabled
- implements ClassLoaderModel
+ implements ClassLoaderModel
{
//==============================================================
// static
@@ -148,6 +151,8 @@
private final URLClassLoader m_classLoader;
+ private Permission[] m_permissions;
+
private final DefaultTypeRepository m_types;
private final DefaultServiceRepository m_services;
@@ -210,7 +215,7 @@
m_manager = new PackageManager( m_extension );
m_classpath = createClassPath( base, repository, directive, implicit );
-
+ m_permissions = createPermissions( directive.getGrantDirective() );
if( getLocalLogger().isDebugEnabled() )
{
String str = "classpath: " + StringHelper.toString( m_classpath );
@@ -369,6 +374,21 @@
return m_classLoader;
}
+ /**
+ * Return the security Permissions defined for this ClassLoaderModel.
+ *
+ * These Permissions will be enforced if code level security is enabled
+ * globally. If no Permissions are returned, all the components under
+ * this container will run without Permissions.
+ *
+ * @return A SecurityPolicy which should be enagaged if codelevel
+ * security is enabled for the Classloader.
+ **/
+ public Permission[] getSecurityPermissions()
+ {
+ return m_permissions;
+ }
+
//==============================================================
// private implementation
//==============================================================
@@ -478,6 +498,17 @@
return (String[]) classpath.toArray( new String[0] );
}
+ private Permission[] createPermissions( GrantDirective directive )
+ {
+ PermissionDirective[] permissions = directive.getPermissionDirectives();
+ Permission[] result = new Permission[ permissions.length ];
+ for( int i=0 ; i < permissions.length ; i++ )
+ {
+ result[i] = permissions[i].getPermission();
+ }
+ return result;
+ }
+
/**
* Retrieve the files for the optional packages required by
* the jars in ClassPath.
1.1 avalon/merlin/composition/impl/src/test/conf/secure-block.xml
Index: secure-block.xml
===================================================================
<container name="secure-block">
<classloader>
<classpath>
<repository>
<resource id="avalon-framework:avalon-framework-impl" version="4.1.5"/>
</repository>
</classpath>
<grant>
<permission class="java.util.PropertyPermission" name="org.apache" >
<action>read</action>
<action>write</action>
</permission>
<permission class="java.lang.RuntimePermission" name="getClassLoader" />
<permission class="java.security.AllPermission" />
</grant>
</classloader>
</container>
1.1
avalon/merlin/composition/impl/src/test/org/apache/avalon/composition/model/test/SecurityTestCase.java
Index: SecurityTestCase.java
===================================================================
package org.apache.avalon.composition.model.test;
import java.security.Permission;
import org.apache.avalon.composition.model.DeploymentModel;
import org.apache.avalon.composition.model.ContainmentModel;
import org.apache.avalon.composition.model.ComponentModel;
import org.apache.avalon.composition.model.DependencyModel;
import org.apache.avalon.composition.model.AbstractTestCase;
import org.apache.avalon.util.exception.ExceptionHelper;
public class SecurityTestCase extends AbstractTestCase
{
//-------------------------------------------------------
// constructor
//-------------------------------------------------------
public SecurityTestCase()
{
super( "secure-block.xml" );
}
//-------------------------------------------------------
// tests
//-------------------------------------------------------
/**
* Validate the composition model.
*/
public void testAssembly() throws Exception
{
m_model.assemble();
Permission[] permissions =
m_model.getClassLoaderModel().getSecurityPermissions();
assertEquals( "Not all permissions were read.", 3, permissions.length );
Permission[] p = new Permission[3];
p[0] = new java.util.PropertyPermission( "org.apache", "read, write" );
p[1] = new java.lang.RuntimePermission( "getClassLoader" );
p[2] = new java.security.AllPermission();
for( int i=0 ; i < 3 ; i++ )
assertEquals( "Permission is not the expected.", p[i], permissions[i] );
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]