3

I was reading through the Tomcat source code, trying to figure out how the tomcat internals are protected against unauthorized access from servlets. One thing I noticed was the fact that the servlets gain access to the StandardContext through the ApplicationContextFacade, which seems to act as a broker for the ApplicationContext, rather than allowing servlets to have direct access to the ApplicationContext.

I was wondering why the ApplicationContextFacade is passed to the servlet rather than the ApplicationContext. I suspect this has something to do with security (as the facade is hardly a simplification of the interface, so not really a typical facade pattern). I looked at the code and saw that it basically forwards requests (as expected), but conditioned on some security settings (such as Globals.IS_SECURITY_ENABLED and SecurityUtil.isPackageProtectionEnabled()) it seems to use java reflection to pass the request. I know that the permissions change when using reflection, but I'm not entirely sure how this would enforce some security policy in the ApplicationContextFacade?

It would be great if somebody could clarify this for me!

Thank you in advance for your help.

link to javadoc http://tomcat.apache.org/tomcat-7.0-doc/api/org/apache/catalina/core/ApplicationContextFacade.html

link to tomcat source: http://tomcat.apache.org/download-70.cgi

example of the facade code:

public String getMimeType(String file) {
        if (SecurityUtil.isPackageProtectionEnabled()) {
            return (String)doPrivileged("getMimeType", new Object[]{file});
        } else {
            return context.getMimeType(file);
        }
    }

where context is the associated ApplicationContext object and doPrivileged is defined as follows:

 private Object doPrivileged(final String methodName, final Object[] params){
        try{
            return invokeMethod(context, methodName, params);
        }catch(Throwable t){
            throw new RuntimeException(t.getMessage(), t);
        }
    }

and finally invokeMethod

private Object invokeMethod(ApplicationContext appContext,
                                final String methodName, 
                                Object[] params) 
        throws Throwable{

        try{
            Method method = (Method)objectCache.get(methodName);
            if (method == null){
                method = appContext.getClass()
                    .getMethod(methodName, (Class[])classCache.get(methodName));
                objectCache.put(methodName, method);
            }

            return executeMethod(method,appContext,params);
        } catch (Exception ex){
            handleException(ex, methodName);
            return null;
        } finally {
            params = null;
        }
    }
codelidoo
  • 219
  • 1
  • 11

1 Answers1

2

I think you needed to visit one more method:

ApplicationContextFacade.executeMethod

468 private Object executeMethod(final Method method, 
469                              final ApplicationContext context,
470                              final Object[] params) 
471         throws PrivilegedActionException, 
472                IllegalAccessException,
473                InvocationTargetException {
474                                  
475     if (SecurityUtil.isPackageProtectionEnabled()){
476        return AccessController.doPrivileged(new PrivilegedExceptionAction(){
477             public Object run() throws IllegalAccessException, InvocationTargetException{
478                 return method.invoke(context,  params);
479             }
480         });
481     } else {
482         return method.invoke(context, params);
483     }        
484 }

I would take a look at that in combination with this answer - When should AccessController.doPrivileged() be used?.

I think that the untrusted code/classloader (the webapp) might not be allowed to do certain things, so the trusted code (Tomcat) can invoke a doPrivileged in order to temporarily override the webapp's more restricted privileges.

Community
  • 1
  • 1
Paul Grime
  • 14,970
  • 4
  • 36
  • 58
  • First thank you for responding and adding the missing code fragment! Ok As I see it now, the web application code is limited in access permissions by the security manager (e.g. can't access the file it wan't the Mime type of), without the doprivileged the limited permissions of the caller would propagate to tomcat and tomcat wouldn't be able to access the file for that webapp. By invoking doPrivileged the facade actually vauches for the webapp overriding its access permissions by its own (trusted) for the duration of the call. Would that be right? Why do they use reflection? – codelidoo Mar 04 '12 at 14:12
  • That sounds right to me. I guess they use reflection to contain the `doPrivileged` code to a certain part of the codebase, instead of having individual `doPrivileged` calls scattered amongst the codebase; this pattern might be better for developers to comprehend the places where such tricks are being used. That's a guess those, I don't know for sure. – Paul Grime Mar 04 '12 at 19:23