You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2016/08/22 20:48:39 UTC

svn commit: r1757271 - in /tomcat/trunk: java/org/apache/catalina/core/NamingContextListener.java java/org/apache/naming/factory/ResourceLinkFactory.java test/org/apache/naming/TestNamingContext.java webapps/docs/changelog.xml

Author: markt
Date: Mon Aug 22 20:48:39 2016
New Revision: 1757271

URL: http://svn.apache.org/viewvc?rev=1757271&view=rev
Log:
When adding and removing ResourceLinks dynamically, ensure
that the global resource is only visible via the
ResourceLinkFactory when it is meant to be.

Added:
    tomcat/trunk/test/org/apache/naming/TestNamingContext.java   (with props)
Modified:
    tomcat/trunk/java/org/apache/catalina/core/NamingContextListener.java
    tomcat/trunk/java/org/apache/naming/factory/ResourceLinkFactory.java
    tomcat/trunk/webapps/docs/changelog.xml

Modified: tomcat/trunk/java/org/apache/catalina/core/NamingContextListener.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/core/NamingContextListener.java?rev=1757271&r1=1757270&r2=1757271&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/core/NamingContextListener.java (original)
+++ tomcat/trunk/java/org/apache/catalina/core/NamingContextListener.java Mon Aug 22 20:48:39 2016
@@ -40,6 +40,7 @@ import javax.naming.StringRefAddr;
 import org.apache.catalina.ContainerEvent;
 import org.apache.catalina.ContainerListener;
 import org.apache.catalina.Context;
+import org.apache.catalina.Engine;
 import org.apache.catalina.Host;
 import org.apache.catalina.Lifecycle;
 import org.apache.catalina.LifecycleEvent;
@@ -58,6 +59,7 @@ import org.apache.naming.ResourceLinkRef
 import org.apache.naming.ResourceRef;
 import org.apache.naming.ServiceRef;
 import org.apache.naming.TransactionRef;
+import org.apache.naming.factory.ResourceLinkFactory;
 import org.apache.tomcat.util.descriptor.web.ContextEjb;
 import org.apache.tomcat.util.descriptor.web.ContextEnvironment;
 import org.apache.tomcat.util.descriptor.web.ContextHandler;
@@ -316,6 +318,11 @@ public class NamingContextListener
                         registry.unregisterComponent(objectName);
                     }
                 }
+
+                javax.naming.Context global = getGlobalNamingContext();
+                if (global != null) {
+                    ResourceLinkFactory.deregisterGlobalResourceAccess(global);
+                }
             } finally {
                 objectNames.clear();
 
@@ -1152,6 +1159,17 @@ public class NamingContextListener
             log.error(sm.getString("naming.bindFailed", e));
         }
 
+        ResourceLinkFactory.registerGlobalResourceAccess(
+                getGlobalNamingContext(), resourceLink.getName(), resourceLink.getGlobal());
+    }
+
+
+    private javax.naming.Context getGlobalNamingContext() {
+        if (container instanceof Context) {
+            Engine e = (Engine) ((Context) container).getParent().getParent();
+            return e.getService().getServer().getGlobalNamingContext();
+        }
+        return null;
     }
 
 
@@ -1269,6 +1287,7 @@ public class NamingContextListener
             log.error(sm.getString("naming.unbindFailed", e));
         }
 
+        ResourceLinkFactory.deregisterGlobalResourceAccess(getGlobalNamingContext(), name);
     }
 
 

Modified: tomcat/trunk/java/org/apache/naming/factory/ResourceLinkFactory.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/naming/factory/ResourceLinkFactory.java?rev=1757271&r1=1757270&r2=1757271&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/naming/factory/ResourceLinkFactory.java (original)
+++ tomcat/trunk/java/org/apache/naming/factory/ResourceLinkFactory.java Mon Aug 22 20:48:39 2016
@@ -16,7 +16,10 @@
  */
 package org.apache.naming.factory;
 
+import java.util.HashMap;
 import java.util.Hashtable;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
 
 import javax.naming.Context;
 import javax.naming.Name;
@@ -41,6 +44,8 @@ public class ResourceLinkFactory impleme
      */
     private static Context globalContext = null;
 
+    private static Map<ClassLoader,Map<String,String>> globalResourceRegistrations =
+            new ConcurrentHashMap<>();
 
     // --------------------------------------------------------- Public Methods
 
@@ -59,6 +64,56 @@ public class ResourceLinkFactory impleme
     }
 
 
+    public static void registerGlobalResourceAccess(Context globalContext, String localName,
+            String globalName) {
+        validateGlobalContext(globalContext);
+        ClassLoader cl = Thread.currentThread().getContextClassLoader();
+        Map<String,String> registrations = globalResourceRegistrations.get(cl);
+        if (registrations == null) {
+            // Web application initialization is single threaded so this is
+            // safe.
+            registrations = new HashMap<>();
+            globalResourceRegistrations.put(cl, registrations);
+        }
+        registrations.put(localName, globalName);
+    }
+
+
+    public static void deregisterGlobalResourceAccess(Context globalContext, String localName) {
+        validateGlobalContext(globalContext);
+        ClassLoader cl = Thread.currentThread().getContextClassLoader();
+        Map<String,String> registrations = globalResourceRegistrations.get(cl);
+        if (registrations != null) {
+            registrations.remove(localName);
+        }
+    }
+
+
+    public static void deregisterGlobalResourceAccess(Context globalContext) {
+        validateGlobalContext(globalContext);
+        ClassLoader cl = Thread.currentThread().getContextClassLoader();
+        globalResourceRegistrations.remove(cl);
+    }
+
+
+    private static void validateGlobalContext(Context globalContext) {
+        if (ResourceLinkFactory.globalContext != null &&
+                ResourceLinkFactory.globalContext != globalContext) {
+            throw new SecurityException("Caller provided invalid global context");
+        }
+    }
+
+
+    private static boolean validateGlobalResourceAccess(String globalName) {
+        ClassLoader cl = Thread.currentThread().getContextClassLoader();
+        Map<String,String> registrations = globalResourceRegistrations.get(cl);
+        if (registrations != null && registrations.containsValue(globalName)) {
+            return true;
+        }
+        return false;
+    }
+
+
     // -------------------------------------------------- ObjectFactory Methods
 
     /**
@@ -82,6 +137,12 @@ public class ResourceLinkFactory impleme
         RefAddr refAddr = ref.get(ResourceLinkRef.GLOBALNAME);
         if (refAddr != null) {
             globalName = refAddr.getContent().toString();
+            // When running under a security manager confirm that the current
+            // web application has really been configured to access the specified
+            // global resource
+            if (!validateGlobalResourceAccess(globalName)) {
+                return null;
+            }
             Object result = null;
             result = globalContext.lookup(globalName);
             // Check the expected type

Added: tomcat/trunk/test/org/apache/naming/TestNamingContext.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/naming/TestNamingContext.java?rev=1757271&view=auto
==============================================================================
--- tomcat/trunk/test/org/apache/naming/TestNamingContext.java (added)
+++ tomcat/trunk/test/org/apache/naming/TestNamingContext.java Mon Aug 22 20:48:39 2016
@@ -0,0 +1,87 @@
+package org.apache.naming;
+
+import javax.naming.Context;
+import javax.naming.NamingException;
+
+import org.apache.catalina.startup.Tomcat;
+import org.apache.catalina.startup.TomcatBaseTest;
+import org.apache.naming.factory.ResourceLinkFactory;
+import org.apache.tomcat.util.descriptor.web.ContextEnvironment;
+import org.apache.tomcat.util.descriptor.web.ContextResourceLink;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestNamingContext extends TomcatBaseTest {
+
+    private static final String COMP_ENV = "comp/env";
+    private static final String GLOBAL_NAME = "global";
+    private static final String LOCAL_NAME = "local";
+    private static final String DATA = "Cabbage";
+
+
+    @Test
+    public void testGlobalNaming() throws Exception {
+        Tomcat tomcat = getTomcatInstance();
+        tomcat.enableNaming();
+
+        org.apache.catalina.Context ctx = tomcat.addContext("", null);
+
+        tomcat.start();
+
+        Context webappInitial = ContextBindings.getContext(ctx);
+
+        // Nothing added at the moment so should be null
+        Object obj = doLookup(webappInitial, COMP_ENV + "/" + LOCAL_NAME);
+        Assert.assertNull(obj);
+
+        ContextEnvironment ce = new ContextEnvironment();
+        ce.setName(GLOBAL_NAME);
+        ce.setValue(DATA);
+        ce.setType(DATA.getClass().getName());
+
+        tomcat.getServer().getGlobalNamingResources().addEnvironment(ce);
+
+        // No link so still should be null
+        obj = doLookup(webappInitial, COMP_ENV + "/" + LOCAL_NAME);
+        Assert.assertNull(obj);
+
+        // Now add a resource link to the context
+        ContextResourceLink crl = new ContextResourceLink();
+        crl.setGlobal(GLOBAL_NAME);
+        crl.setName(LOCAL_NAME);
+        crl.setType(DATA.getClass().getName());
+        ctx.getNamingResources().addResourceLink(crl);
+
+        // Link exists so should be OK now
+        obj = doLookup(webappInitial, COMP_ENV + "/" + LOCAL_NAME);
+        Assert.assertEquals(DATA, obj);
+
+        // Try shortcut
+        ResourceLinkFactory factory = new ResourceLinkFactory();
+        ResourceLinkRef rlr = new ResourceLinkRef(DATA.getClass().getName(), GLOBAL_NAME, null, null);
+        obj = factory.getObjectInstance(rlr, null, null, null);
+        Assert.assertEquals(DATA, obj);
+
+        // Remove the link
+        ctx.getNamingResources().removeResourceLink(LOCAL_NAME);
+
+        // No link so should be null
+        obj = doLookup(webappInitial, COMP_ENV + "/" + LOCAL_NAME);
+        Assert.assertNull(obj);
+
+        // Shortcut should fail too
+        obj = factory.getObjectInstance(rlr, null, null, null);
+        Assert.assertNull(obj);
+    }
+
+
+    private Object doLookup(Context context, String name) {
+        Object result = null;
+        try {
+            result = context.lookup(name);
+        } catch (NamingException nnfe) {
+            // Ignore
+        }
+        return result;
+    }
+}

Propchange: tomcat/trunk/test/org/apache/naming/TestNamingContext.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: tomcat/trunk/webapps/docs/changelog.xml
URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/changelog.xml?rev=1757271&r1=1757270&r2=1757271&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/trunk/webapps/docs/changelog.xml Mon Aug 22 20:48:39 2016
@@ -153,6 +153,11 @@
         >CVE-2016-5388</a>) by default and to provide a mechanism that can be
         used to mitigate any future, similar issues. (markt)
       </add>
+      <add>
+        When adding and removing <code>ResourceLink</code>s dynamically, ensure
+        that the global resource is only visible via the
+        <code>ResourceLinkFactory</code> when it is meant to be. (markt)
+      </add>
     </changelog>
   </subsection>
   <subsection name="Coyote">



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org