On Sat, 18 Aug 2001 04:24, [EMAIL PROTECTED] wrote:
> It is based on the assumption that each webapp has a separate class
> loader, that the class loader is set as context class loader ( in JDK1.1
> we don't have much security anyway, so no need to worry ), and that it's
> not possible from one webapp to forge the context class loader ( if it
> can, it means it's trusted code with "AllPermissions", so it can do
> anything anyway ).
>
> private static Hashtable hierarchies=new Hashtable();
>
> public static Category getInstance(String name) {
> // First, find the (guarded) hierarchy
> ClassLoader cl=Thread.currentThread().getContextClassLoader();
> if( cl==null ) {
> // Top level or system - use this class loader
> cl= Log4j.class.getClassLoader();
> }
> Hierarchy h=(Hierarchy)hierarchies.get( cl );
> if( h == null ) {
> Category rootC=new Category("");
> h=new Hierarchy(rootC);
> hierarchies.put( cl, h );
> }
> return h.getInstance( name );
> }
Thats no more secure or safe than current version. You could simply do
something like
Thread.currentThread.
setContextClassLoader( mySecureObject.getClass().getClassLoader() );
Category c = Category.getInstance( "auth" );
c.setAppenders( myEvilSubversiveAppenders );
This will work when security is turned off or on any complex
webapps/applications.
You can try to make it based on caller class using something like code below
... however that really doesn't work in general case. Besides it is slow and
requires giveing almost full permissions to Log4j code.
In Avalon we came across much of these same problems a while back. The only
real solution was to change the paradigm. Instead of static access you get
access via an interface. SOmething like
/**
* Components that need to log can implement this interface to
* be provided Loggers.
*
* @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a>
*/
public interface Loggable
{
/**
* Provide component with a logger.
*
* @param logger the logger
*/
void setLogger( Logger logger );
}
Then for every component you need to create you do something like.
if( myComponent instanceof Loggable )
{
((Loggable)myComponent).setLogger( myLogger );
}
Now if you want to assume a logging hierarchy this could be changed to
if( myComponent instanceof Loggable )
{
((Loggable)myComponent).setLogger( myLogger.getChildLogger( "myComponent" );
}
Which would allow a hierarchial logging tree to be constructed. Tighten up
Logger/Category object and it is extremely secure.
----------------------------------------
Get Caller Class code snippet
----------------------------------------
/**
* A set of utilities to inspect current stack frame.
*
* @author <a href="mailto:[EMAIL PROTECTED]">Sylvain Wallez</a>
* @author <a href="mailto:[EMAIL PROTECTED]">Stuart Roebuck</a>
* @version CVS $Revision: 1.3 $ $Date: 2001/08/16 08:55:18 $
*/
public final class StackIntrospector
{
/**
* Hack to get the call stack as an array of classes. The
* SecurityManager class provides it as a protected method, so
* change it to public through a new method !
*/
private final static class CallStack
extends SecurityManager
{
/**
* Returns the current execution stack as an array of classes.
* The length of the array is the number of methods on the execution
* stack. The element at index 0 is the class of the currently
executing
* method, the element at index 1 is the class of that method's
caller,
* and so on.
*/
public Class[] get()
{
return getClassContext();
}
}
///Method to cache CallStack hack as needed
private static CallStack c_callStack;
/**
* Private constructor to block instantiation.
*
*/
private StackIntrospector()
{
}
/**
* Create Hack SecurityManager to get CallStack.
*
* @return the CallStack object
* @exception SecurityException if an existing SecurityManager disallows
construction
* of another SecurityManager
*/
private synchronized static CallStack getCallStack()
throws SecurityException
{
if( null == c_callStack )
{
//Lazily create CallStack accessor as appropriate
c_callStack = new CallStack();
}
return c_callStack;
}
/**
* Find the caller of the passed in Class.
* May return null if caller not found on execution stack
*
* @param clazz the Class to search for on stack to find caller of
* @return the Class of object that called parrameter class
* @exception SecurityException if an existing SecurityManager disallows
construction
* of another SecurityManager and thus blocks method results
*/
public final static Class getCallerClass( final Class clazz )
throws SecurityException
{
final Class[] stack = getCallStack().get();
// Traverse the call stack in reverse order until we find clazz
for( int i = stack.length - 1; i >= 0; i-- )
{
if( clazz.isAssignableFrom( stack[ i ] ) )
{
// Found : the caller is the previous stack element
return stack[ i + 1 ];
}
}
//Unable to locate class in call stack
return null;
}
...
}
--
Cheers,
Pete
*-----------------------------------------------------*
* "Faced with the choice between changing one's mind, *
* and proving that there is no need to do so - almost *
* everyone gets busy on the proof." *
* - John Kenneth Galbraith *
*-----------------------------------------------------*