niclas 2004/01/19 13:45:07
Modified:
merlin/activation/impl/src/java/org/apache/avalon/activation/appliance/impl
AbstractBlock.java DefaultAppliance.java
DefaultBlock.java Deployer.java
Added: merlin/activation/impl project.properties
Log:
Code level security implemented in DefaultAppliance.
Revision Changes Path
1.1 avalon/merlin/activation/impl/project.properties
Index: project.properties
===================================================================
maven.junit.fork=false
maven.junit.sysproperties=java.security.policy
java.security.policy=${basedir}/src/test/conf/security.policy
1.15 +56 -3
avalon/merlin/activation/impl/src/java/org/apache/avalon/activation/appliance/impl/AbstractBlock.java
Index: AbstractBlock.java
===================================================================
RCS file:
/home/cvs/avalon/merlin/activation/impl/src/java/org/apache/avalon/activation/appliance/impl/AbstractBlock.java,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -r1.14 -r1.15
--- AbstractBlock.java 16 Jan 2004 16:39:02 -0000 1.14
+++ AbstractBlock.java 19 Jan 2004 21:45:06 -0000 1.15
@@ -51,6 +51,15 @@
package org.apache.avalon.activation.appliance.impl;
import java.net.URL;
+import java.net.URLClassLoader;
+
+import java.security.AccessControlContext;
+import java.security.CodeSource;
+import java.security.Permission;
+import java.security.Permissions;
+import java.security.ProtectionDomain;
+import java.security.cert.Certificate;
+
import java.util.ArrayList;
import java.util.Hashtable;
@@ -70,6 +79,7 @@
import org.apache.avalon.composition.model.SystemContext;
import org.apache.avalon.composition.model.ContainmentModel;
+import org.apache.avalon.composition.model.ClassLoaderModel;
import org.apache.avalon.composition.model.DependencyModel;
import org.apache.avalon.composition.model.ComponentModel;
import org.apache.avalon.composition.model.DeploymentModel;
@@ -123,6 +133,7 @@
private final DefaultState m_self = new DefaultState();
private final Engine m_engine;
+ private final AccessControlContext m_accessControlContext;
//-------------------------------------------------------------------
// constructor
@@ -137,7 +148,12 @@
AbstractBlock( ContainmentModel model, Engine engine )
{
super( model );
-
+ ClassLoaderModel clmodel = model.getClassLoaderModel();
+ if( model.isSecureExecutionEnabled() )
+ m_accessControlContext = createAccessControlContext( clmodel );
+ else
+ m_accessControlContext = null;
+
m_model = model;
m_engine = engine;
@@ -239,6 +255,42 @@
}
}
+ protected AccessControlContext getAccessControlContext()
+ {
+ return m_accessControlContext;
+ }
+
+ /**
+ * Creates the AccessControlContext based on the Permissons granted
+ * in the ContainmentModel and the ClassLoader used to load the class.
+ **/
+ private AccessControlContext createAccessControlContext( ClassLoaderModel model
)
+ {
+ ClassLoader classloader = model.getClassLoader();
+ if( classloader instanceof URLClassLoader )
+ {
+ Permissions permissionGroup = new Permissions();
+ Permission[] permissions = model.getSecurityPermissions();
+ for( int i=0 ; i < permissions.length ; i++ )
+ permissionGroup.add( permissions[i] );
+
+ Certificate[] certs = model.getCertificates();
+ URL[] jars = ((URLClassLoader) classloader).getURLs();
+ ProtectionDomain[] domains = new ProtectionDomain[ jars.length ];
+ for( int i=0 ; i < jars.length ; i++ )
+ {
+ CodeSource cs = new CodeSource( jars[i], certs );
+ domains[i] = new ProtectionDomain( cs, permissionGroup );
+ }
+ return new AccessControlContext( domains );
+ }
+ else
+ {
+ // TODO: No other idea on how to handle this at the moment.
+ throw new SecurityException( "ClassLoader's must inherit from
URLClassLoader." );
+ }
+ }
+
//-------------------------------------------------------------------
// Deployable
//-------------------------------------------------------------------
@@ -270,6 +322,7 @@
//
ContainmentModel model = getContainmentModel();
+
DeploymentModel[] startup = model.getStartupGraph();
long timeout = model.getDeploymentTimeout();
@@ -391,7 +444,7 @@
{
getLogger().debug( "creating appliance: " + path );
ComponentModel component = (ComponentModel) model;
- appliance = new DefaultAppliance( component, this );
+ appliance = new DefaultAppliance( component, this,
m_accessControlContext );
}
else if( model instanceof ContainmentModel )
{
1.20 +242 -35
avalon/merlin/activation/impl/src/java/org/apache/avalon/activation/appliance/impl/DefaultAppliance.java
Index: DefaultAppliance.java
===================================================================
RCS file:
/home/cvs/avalon/merlin/activation/impl/src/java/org/apache/avalon/activation/appliance/impl/DefaultAppliance.java,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -r1.19 -r1.20
--- DefaultAppliance.java 19 Jan 2004 01:27:01 -0000 1.19
+++ DefaultAppliance.java 19 Jan 2004 21:45:06 -0000 1.20
@@ -55,6 +55,10 @@
import java.lang.reflect.UndeclaredThrowableException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedExceptionAction;
import java.util.Hashtable;
import java.util.ArrayList;
import java.util.Map;
@@ -151,6 +155,8 @@
private Object m_instance;
+ private AccessControlContext m_accessControlContext;
+
//-------------------------------------------------------------------
// mutable state
//-------------------------------------------------------------------
@@ -182,11 +188,31 @@
// constructor
//-------------------------------------------------------------------
- public DefaultAppliance( ComponentModel model, Engine engine )
+ public DefaultAppliance( ComponentModel model,
+ Engine engine,
+ AccessControlContext access )
{
super( model );
m_model = (ComponentModel) model;
m_engine = engine;
+ m_accessControlContext = access;
+
+ // Enabled the SecurityManager is none already exists, and that
+ // the kernel setting for enabling the secure execution has been
+ // set. The parameter in the kernel is urn:composition:security.enabled
+ if( System.getSecurityManager() == null )
+ {
+ System.setSecurityManager( new SecurityManager() );
+ }
+ }
+
+ public DefaultAppliance( ComponentModel model,
+ Engine engine )
+ {
+ super( model );
+ m_model = (ComponentModel) model;
+ m_engine = engine;
+ m_accessControlContext = null;
}
//-------------------------------------------------------------------
@@ -431,8 +457,10 @@
*/
private void release( Object instance, boolean finalized )
{
- if( instance == null ) return;
- if( !m_deployment.isEnabled() ) return;
+ if( instance == null )
+ return;
+ if( !m_deployment.isEnabled() )
+ return;
releaseInstance( getProviderInstance( instance ) );
m_lifestyle.release( instance, finalized );
}
@@ -515,7 +543,7 @@
}
}
- private void applyLogger( Object instance )
+ private void applyLogger( final Object instance )
{
if( instance instanceof LogEnabled )
{
@@ -525,20 +553,34 @@
getLogger().debug( "applying logger to: " + id );
}
final Logger logger = m_model.getLogger();
- ((LogEnabled)instance).enableLogging( logger );
+ if( m_accessControlContext == null )
+ {
+ ((LogEnabled)instance).enableLogging( logger );
+ }
+ else
+ {
+ AccessController.doPrivileged( new PrivilegedAction()
+ {
+ public Object run()
+ {
+ ((LogEnabled)instance).enableLogging( logger );
+ return null;
+ }
+ }, m_accessControlContext );
+ }
}
}
- private void applyContext( Object instance )
+ private void applyContext( final Object instance )
throws Exception
{
- if( instance == null ) throw new NullPointerException( "context" );
-
+ if( instance == null )
+ throw new NullPointerException( "context" );
final ContextModel model = m_model.getContextModel();
+ if( model == null )
+ return;
- if( model == null ) return;
-
- Context context = model.getContext();
+ final Context context = model.getContext();
if( m_contextualization != null )
{
if( getLogger().isDebugEnabled() )
@@ -548,7 +590,21 @@
}
try
{
- m_contextualization.contextualize( instance, context );
+ if( m_accessControlContext == null )
+ {
+ m_contextualization.contextualize( instance, context );
+ }
+ else
+ {
+ AccessController.doPrivileged( new PrivilegedExceptionAction()
+ {
+ public Object run() throws Exception
+ {
+ m_contextualization.contextualize( instance, context );
+ return null;
+ }
+ }, m_accessControlContext );
+ }
}
catch( Throwable e )
{
@@ -569,7 +625,21 @@
try
{
- ((Contextualizable)instance).contextualize( context );
+ if( m_accessControlContext == null )
+ {
+ ((Contextualizable)instance).contextualize( context );
+ }
+ else
+ {
+ AccessController.doPrivileged( new PrivilegedExceptionAction()
+ {
+ public Object run() throws Exception
+ {
+ ((Contextualizable)instance).contextualize( context );
+ return null;
+ }
+ }, m_accessControlContext );
+ }
}
catch( Throwable e )
{
@@ -582,7 +652,7 @@
}
}
- private void applyServices( Object instance )
+ private void applyServices( final Object instance )
throws Exception
{
if( instance instanceof Serviceable )
@@ -594,12 +664,26 @@
}
Map providers = getServiceProviders();
- ServiceManager manager = new DefaultServiceManager( getLogger(),
providers );
- ((Serviceable)instance).service( manager );
+ final ServiceManager manager = new DefaultServiceManager( getLogger(),
providers );
+ if( m_accessControlContext == null )
+ {
+ ((Serviceable)instance).service( manager );
+ }
+ else
+ {
+ AccessController.doPrivileged( new PrivilegedExceptionAction()
+ {
+ public Object run() throws Exception
+ {
+ ((Serviceable)instance).service( manager );
+ return null;
+ }
+ }, m_accessControlContext );
+ }
}
}
- private void applyConfiguration( Object instance )
+ private void applyConfiguration( final Object instance )
throws Exception
{
if( instance instanceof Configurable )
@@ -609,11 +693,25 @@
int id = System.identityHashCode( instance );
getLogger().debug( "applying configuration to: " + id );
}
- ((Configurable)instance).configure( m_model.getConfiguration() );
+ if( m_accessControlContext == null )
+ {
+ ((Configurable)instance).configure( m_model.getConfiguration() );
+ }
+ else
+ {
+ AccessController.doPrivileged( new PrivilegedExceptionAction()
+ {
+ public Object run() throws Exception
+ {
+ ((Configurable)instance).configure(
m_model.getConfiguration() );
+ return null;
+ }
+ }, m_accessControlContext );
+ }
}
}
- private void applyParameters( Object instance )
+ private void applyParameters( final Object instance )
throws Exception
{
if( instance instanceof Parameterizable )
@@ -623,7 +721,21 @@
int id = System.identityHashCode( instance );
getLogger().debug( "applying parameters to: " + id );
}
- ((Parameterizable)instance).parameterize( m_model.getParameters() );
+ if( m_accessControlContext == null )
+ {
+ ((Parameterizable)instance).parameterize( m_model.getParameters() );
+ }
+ else
+ {
+ AccessController.doPrivileged( new PrivilegedExceptionAction()
+ {
+ public Object run() throws Exception
+ {
+ ((Parameterizable)instance).parameterize(
m_model.getParameters() );
+ return null;
+ }
+ }, m_accessControlContext );
+ }
}
}
@@ -807,7 +919,7 @@
return instance;
}
- private void applyInitialization( Object instance )
+ private void applyInitialization( final Object instance )
throws LifecycleException
{
if( instance instanceof Initializable )
@@ -819,7 +931,21 @@
}
try
{
- ((Initializable)instance).initialize();
+ if( m_accessControlContext == null )
+ {
+ ((Initializable)instance).initialize();
+ }
+ else
+ {
+ AccessController.doPrivileged( new PrivilegedExceptionAction()
+ {
+ public Object run() throws Exception
+ {
+ ((Initializable)instance).initialize();
+ return null;
+ }
+ }, m_accessControlContext );
+ }
}
catch( Throwable e )
{
@@ -830,7 +956,7 @@
}
}
- private void applyStart( Object instance )
+ private void applyStart( final Object instance )
throws LifecycleException
{
if( instance instanceof Startable )
@@ -842,7 +968,21 @@
}
try
{
- ((Startable)instance).start();
+ if( m_accessControlContext == null )
+ {
+ ((Startable)instance).start();
+ }
+ else
+ {
+ AccessController.doPrivileged( new PrivilegedExceptionAction()
+ {
+ public Object run() throws Exception
+ {
+ ((Startable)instance).start();
+ return null;
+ }
+ }, m_accessControlContext );
+ }
}
catch( Throwable e )
{
@@ -860,7 +1000,21 @@
}
try
{
- ((Executable)instance).execute();
+ if( m_accessControlContext == null )
+ {
+ ((Executable)instance).execute();
+ }
+ else
+ {
+ AccessController.doPrivileged( new PrivilegedExceptionAction()
+ {
+ public Object run() throws Exception
+ {
+ ((Executable)instance).execute();
+ return null;
+ }
+ }, m_accessControlContext );
+ }
}
catch( Throwable e )
{
@@ -871,7 +1025,7 @@
}
}
- private void applyStop( Object instance )
+ private void applyStop( final Object instance )
{
if( instance instanceof Startable )
{
@@ -882,7 +1036,21 @@
}
try
{
- ((Startable)instance).stop();
+ if( m_accessControlContext == null )
+ {
+ ((Startable)instance).stop();
+ }
+ else
+ {
+ AccessController.doPrivileged( new PrivilegedExceptionAction()
+ {
+ public Object run() throws Exception
+ {
+ ((Startable)instance).stop();
+ return null;
+ }
+ }, m_accessControlContext );
+ }
}
catch( Throwable e )
{
@@ -893,7 +1061,7 @@
}
}
- private void applyDispose( Object instance )
+ private void applyDispose( final Object instance )
{
if( instance instanceof Disposable )
{
@@ -904,7 +1072,21 @@
}
try
{
- ((Disposable)instance).dispose();
+ if( m_accessControlContext == null )
+ {
+ ((Disposable)instance).dispose();
+ }
+ else
+ {
+ AccessController.doPrivileged( new PrivilegedExceptionAction()
+ {
+ public Object run() throws Exception
+ {
+ ((Disposable)instance).dispose();
+ return null;
+ }
+ }, m_accessControlContext );
+ }
}
catch( Throwable e )
{
@@ -1057,13 +1239,16 @@
final Object[] args )
throws Throwable
{
- if( proxy == null ) throw new NullPointerException( "proxy" );
- if( method == null ) throw new NullPointerException( "method" );
- if( m_destroyed ) throw new IllegalStateException( "destroyed" );
+ if( proxy == null )
+ throw new NullPointerException( "proxy" );
+ if( method == null )
+ throw new NullPointerException( "method" );
+ if( m_destroyed )
+ throw new IllegalStateException( "destroyed" );
try
{
- return method.invoke( m_instance, args );
+ return secureInvocation( method, m_instance, args );
}
catch( UndeclaredThrowableException e )
{
@@ -1076,7 +1261,8 @@
catch( InvocationTargetException e )
{
Throwable cause = e.getTargetException();
- if( cause != null ) throw cause;
+ if( cause != null )
+ throw cause;
final String error =
"Delegation error raised by component: " +
m_model.getQualifiedName();
throw new ApplianceException( error, e );
@@ -1117,6 +1303,27 @@
void notifyDestroyed()
{
m_destroyed = true;
+ }
+
+ private Object secureInvocation( final Method method, final Object object,
final Object[] args )
+ throws Exception
+ {
+ if( m_accessControlContext == null )
+ {
+ return method.invoke( object, args );
+ }
+ else
+ {
+ Object result = AccessController.doPrivileged(
+ new PrivilegedExceptionAction()
+ {
+ public Object run() throws Exception
+ {
+ return method.invoke( object, args );
+ }
+ }, m_accessControlContext );
+ return result;
+ }
}
}
1.10 +5 -3
avalon/merlin/activation/impl/src/java/org/apache/avalon/activation/appliance/impl/DefaultBlock.java
Index: DefaultBlock.java
===================================================================
RCS file:
/home/cvs/avalon/merlin/activation/impl/src/java/org/apache/avalon/activation/appliance/impl/DefaultBlock.java,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- DefaultBlock.java 13 Jan 2004 18:43:15 -0000 1.9
+++ DefaultBlock.java 19 Jan 2004 21:45:07 -0000 1.10
@@ -197,7 +197,8 @@
* @param block the underlying block implementation
* @exception if an invocation handler establishment error occurs
*/
- protected BlockInvocationHandler( final Logger logger, final DefaultBlock
block )
+ protected BlockInvocationHandler( final Logger logger,
+ final DefaultBlock block )
throws Exception
{
if( block == null )
@@ -243,7 +244,8 @@
String path = service.getServiceDirective().getPath();
Appliance provider = (Appliance) m_block.locate( path );
- m_logger.debug( "delegating: " + method.getName() );
+ if( m_logger.isDebugEnabled() )
+ m_logger.debug( "delegating: " + method.getName() );
//
// resolve the service object from the appliance
1.7 +2 -1
avalon/merlin/activation/impl/src/java/org/apache/avalon/activation/appliance/impl/Deployer.java
Index: Deployer.java
===================================================================
RCS file:
/home/cvs/avalon/merlin/activation/impl/src/java/org/apache/avalon/activation/appliance/impl/Deployer.java,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- Deployer.java 16 Jan 2004 16:39:02 -0000 1.6
+++ Deployer.java 19 Jan 2004 21:45:07 -0000 1.7
@@ -97,6 +97,7 @@
Deployer( Logger logger )
{
m_logger = logger;
+
m_deploymentThread =
new Thread( this, "Deployer " + m_ThreadCounter++ );
m_deploymentThread.start();
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]