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