You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by pf...@apache.org on 2005/03/17 09:14:54 UTC
cvs commit: jakarta-tapestry/junit/mock-scripts TestAssetService.xml
pferraro 2005/03/17 00:14:54
Modified: framework/src/org/apache/tapestry/engine Tag: branch-3-0
AbstractEngine.java
framework/src/org/apache/tapestry/asset Tag: branch-3-0
AssetService.java PrivateAsset.java
framework/src/org/apache/tapestry Tag: branch-3-0
TapestryStrings.properties IEngine.java
junit/mock-scripts Tag: branch-3-0 TestAssetService.xml
Added: framework/src/org/apache/tapestry/asset Tag: branch-3-0
ResourceChecksumSourceImpl.java
ResourceChecksumSource.java
Log:
TAPESTRY-281: fixes security flaw in asset service
Revision Changes Path
No revision
No revision
1.30.2.1 +53 -1 jakarta-tapestry/framework/src/org/apache/tapestry/engine/Attic/AbstractEngine.java
Index: AbstractEngine.java
===================================================================
RCS file: /home/cvs/jakarta-tapestry/framework/src/org/apache/tapestry/engine/Attic/AbstractEngine.java,v
retrieving revision 1.30
retrieving revision 1.30.2.1
diff -u -r1.30 -r1.30.2.1
--- AbstractEngine.java 6 Apr 2004 16:26:58 -0000 1.30
+++ AbstractEngine.java 17 Mar 2005 08:14:54 -0000 1.30.2.1
@@ -40,6 +40,7 @@
import javax.servlet.http.HttpSessionBindingListener;
import org.apache.bsf.BSFManager;
+import org.apache.commons.codec.binary.Hex;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -56,6 +57,8 @@
import org.apache.tapestry.StaleLinkException;
import org.apache.tapestry.StaleSessionException;
import org.apache.tapestry.Tapestry;
+import org.apache.tapestry.asset.ResourceChecksumSource;
+import org.apache.tapestry.asset.ResourceChecksumSourceImpl;
import org.apache.tapestry.enhance.DefaultComponentClassEnhancer;
import org.apache.tapestry.listener.ListenerMap;
import org.apache.tapestry.pageload.PageSource;
@@ -318,6 +321,14 @@
protected static final String DATA_SQUEEZER_NAME = "org.apache.tapestry.DataSqueezer";
/**
+ * Servlet context attribute name for a shared instance
+ * of {@link ResourceChecksumSource}.
+ * @since 3.0.3
+ */
+ protected static final String RESOURCE_CHECKSUM_SOURCE_NAME =
+ "org.apache.tapestry.ResourceChecksumSource";
+
+ /**
* The source for pages, which acts as a pool, but is capable of
* creating pages as needed. Stored in the
* {@link ServletContext}, like {@link #_templateSource}.
@@ -435,6 +446,12 @@
private transient IMonitorFactory _monitorFactory;
/**
+ * Used to obtain resource checksums for the asset service.
+ * @since 3.0.3
+ */
+ private transient ResourceChecksumSource _resourceChecksumSource;
+
+ /**
* Sets the Exception page's exception property, then renders the Exception page.
*
* <p>If the render throws an exception, then copious output is sent to
@@ -1124,6 +1141,7 @@
_scriptSource.reset();
_stringsSource.reset();
_enhancer.reset();
+ _resourceChecksumSource.reset();
}
/**
@@ -1390,6 +1408,20 @@
servletContext.setAttribute(name, _global);
}
}
+
+ if (_resourceChecksumSource == null)
+ {
+ String name = RESOURCE_CHECKSUM_SOURCE_NAME + ":" + servletName;
+
+ _resourceChecksumSource = (ResourceChecksumSource) servletContext.getAttribute(name);
+
+ if (_resourceChecksumSource == null)
+ {
+ _resourceChecksumSource = createResourceChecksumSource();
+
+ servletContext.setAttribute(name, _resourceChecksumSource);
+ }
+ }
String encoding = request.getCharacterEncoding();
if (encoding == null)
@@ -1496,6 +1528,19 @@
}
/**
+ * Invoked from {@link #setupForRequest(RequestContext)} to provide
+ * an instance of {@link ResourceChecksumSource} that will be stored into
+ * the {@link ServletContext}. Subclasses may override this method
+ * to provide a different implementation.
+ * @return an instance of {@link ResourceChecksumSourceImpl} that uses MD5 and Hex encoding.
+ * @since 3.0.3
+ */
+ protected ResourceChecksumSource createResourceChecksumSource()
+ {
+ return new ResourceChecksumSourceImpl("MD5", new Hex());
+ }
+
+ /**
* Returns an object which can find resources and classes.
*
**/
@@ -2036,6 +2081,13 @@
return _propertySource;
}
+ /** @since 3.0.3 */
+
+ public ResourceChecksumSource getResourceChecksumSource()
+ {
+ return _resourceChecksumSource;
+ }
+
/** @since 3.0 **/
protected String getExceptionPageName()
No revision
No revision
1.8.2.1 +15 -7 jakarta-tapestry/framework/src/org/apache/tapestry/asset/Attic/AssetService.java
Index: AssetService.java
===================================================================
RCS file: /home/cvs/jakarta-tapestry/framework/src/org/apache/tapestry/asset/Attic/AssetService.java,v
retrieving revision 1.8
retrieving revision 1.8.2.1
diff -u -r1.8 -r1.8.2.1
--- AssetService.java 19 Feb 2004 17:38:09 -0000 1.8
+++ AssetService.java 17 Mar 2005 08:14:54 -0000 1.8.2.1
@@ -22,7 +22,6 @@
import java.util.Map;
import javax.servlet.ServletContext;
-import javax.servlet.ServletException;
import org.apache.tapestry.ApplicationRuntimeException;
import org.apache.tapestry.IComponent;
@@ -85,7 +84,7 @@
public ILink getLink(IRequestCycle cycle, IComponent component, Object[] parameters)
{
- if (Tapestry.size(parameters) != 1)
+ if (Tapestry.size(parameters) != 2)
throw new ApplicationRuntimeException(
Tapestry.format("service-single-parameter", Tapestry.ASSET_SERVICE));
@@ -129,22 +128,31 @@
IEngineServiceView engine,
IRequestCycle cycle,
ResponseOutputStream output)
- throws ServletException, IOException
+ throws IOException
{
Object[] parameters = getParameters(cycle);
- if (Tapestry.size(parameters) != 1)
+ if (Tapestry.size(parameters) != 2)
throw new ApplicationRuntimeException(
- Tapestry.format("service-single-parameter", Tapestry.ASSET_SERVICE));
+ Tapestry.format("service-incorrect-parameter-count", Tapestry.ASSET_SERVICE, new Integer(2)));
String resourcePath = (String) parameters[0];
+ String checksum = (String) parameters[1];
- URL resourceURL = cycle.getEngine().getResourceResolver().getResource(resourcePath);
+ URL resourceURL = engine.getResourceResolver().getResource(resourcePath);
if (resourceURL == null)
throw new ApplicationRuntimeException(
Tapestry.format("missing-resource", resourcePath));
+ String actualChecksum = engine.getResourceChecksumSource().getChecksum(resourceURL);
+
+ if (!actualChecksum.equals(checksum))
+ {
+ throw new ApplicationRuntimeException(
+ Tapestry.format("AssetService.checksum-failure", checksum, resourcePath));
+ }
+
URLConnection resourceConnection = resourceURL.openConnection();
ServletContext servletContext = cycle.getRequestContext().getServlet().getServletContext();
1.7.2.1 +9 -5 jakarta-tapestry/framework/src/org/apache/tapestry/asset/Attic/PrivateAsset.java
Index: PrivateAsset.java
===================================================================
RCS file: /home/cvs/jakarta-tapestry/framework/src/org/apache/tapestry/asset/Attic/PrivateAsset.java,v
retrieving revision 1.7
retrieving revision 1.7.2.1
diff -u -r1.7 -r1.7.2.1
--- PrivateAsset.java 19 Feb 2004 17:38:09 -0000 1.7
+++ PrivateAsset.java 17 Mar 2005 08:14:54 -0000 1.7.2.1
@@ -18,11 +18,11 @@
import java.net.URL;
import org.apache.tapestry.ApplicationRuntimeException;
+import org.apache.tapestry.IEngine;
import org.apache.tapestry.ILocation;
import org.apache.tapestry.IRequestCycle;
import org.apache.tapestry.IResourceLocation;
import org.apache.tapestry.Tapestry;
-import org.apache.tapestry.engine.IEngineService;
import org.apache.tapestry.engine.ILink;
import org.apache.tapestry.resource.ClasspathResourceLocation;
@@ -71,10 +71,14 @@
// Otherwise, the service is responsible for dynamically retrieving the
// resource.
- String[] parameters = new String[] { path };
-
- IEngineService service = cycle.getEngine().getService(Tapestry.ASSET_SERVICE);
+ IEngine engine = cycle.getEngine();
+
+ URL resourceURL = engine.getResourceResolver().getResource(path);
+ String checksum = engine.getResourceChecksumSource().getChecksum(resourceURL);
+
+ String[] parameters = new String[] { path, checksum };
+ AssetService service = (AssetService) engine.getService(Tapestry.ASSET_SERVICE);
ILink link = service.getLink(cycle, null, parameters);
return link.getURL();
No revision
Index: PrivateAsset.java
===================================================================
RCS file: /home/cvs/jakarta-tapestry/framework/src/org/apache/tapestry/asset/Attic/PrivateAsset.java,v
retrieving revision 1.7
retrieving revision 1.7.2.1
diff -u -r1.7 -r1.7.2.1
--- PrivateAsset.java 19 Feb 2004 17:38:09 -0000 1.7
+++ PrivateAsset.java 17 Mar 2005 08:14:54 -0000 1.7.2.1
@@ -18,11 +18,11 @@
import java.net.URL;
import org.apache.tapestry.ApplicationRuntimeException;
+import org.apache.tapestry.IEngine;
import org.apache.tapestry.ILocation;
import org.apache.tapestry.IRequestCycle;
import org.apache.tapestry.IResourceLocation;
import org.apache.tapestry.Tapestry;
-import org.apache.tapestry.engine.IEngineService;
import org.apache.tapestry.engine.ILink;
import org.apache.tapestry.resource.ClasspathResourceLocation;
@@ -71,10 +71,14 @@
// Otherwise, the service is responsible for dynamically retrieving the
// resource.
- String[] parameters = new String[] { path };
-
- IEngineService service = cycle.getEngine().getService(Tapestry.ASSET_SERVICE);
+ IEngine engine = cycle.getEngine();
+
+ URL resourceURL = engine.getResourceResolver().getResource(path);
+ String checksum = engine.getResourceChecksumSource().getChecksum(resourceURL);
+
+ String[] parameters = new String[] { path, checksum };
+ AssetService service = (AssetService) engine.getService(Tapestry.ASSET_SERVICE);
ILink link = service.getLink(cycle, null, parameters);
return link.getURL();
No revision
Index: PrivateAsset.java
===================================================================
RCS file: /home/cvs/jakarta-tapestry/framework/src/org/apache/tapestry/asset/Attic/PrivateAsset.java,v
retrieving revision 1.7
retrieving revision 1.7.2.1
diff -u -r1.7 -r1.7.2.1
--- PrivateAsset.java 19 Feb 2004 17:38:09 -0000 1.7
+++ PrivateAsset.java 17 Mar 2005 08:14:54 -0000 1.7.2.1
@@ -18,11 +18,11 @@
import java.net.URL;
import org.apache.tapestry.ApplicationRuntimeException;
+import org.apache.tapestry.IEngine;
import org.apache.tapestry.ILocation;
import org.apache.tapestry.IRequestCycle;
import org.apache.tapestry.IResourceLocation;
import org.apache.tapestry.Tapestry;
-import org.apache.tapestry.engine.IEngineService;
import org.apache.tapestry.engine.ILink;
import org.apache.tapestry.resource.ClasspathResourceLocation;
@@ -71,10 +71,14 @@
// Otherwise, the service is responsible for dynamically retrieving the
// resource.
- String[] parameters = new String[] { path };
-
- IEngineService service = cycle.getEngine().getService(Tapestry.ASSET_SERVICE);
+ IEngine engine = cycle.getEngine();
+
+ URL resourceURL = engine.getResourceResolver().getResource(path);
+ String checksum = engine.getResourceChecksumSource().getChecksum(resourceURL);
+
+ String[] parameters = new String[] { path, checksum };
+ AssetService service = (AssetService) engine.getService(Tapestry.ASSET_SERVICE);
ILink link = service.getLink(cycle, null, parameters);
return link.getURL();
1.1.2.1 +120 -0 jakarta-tapestry/framework/src/org/apache/tapestry/asset/Attic/ResourceChecksumSourceImpl.java
1.1.2.1 +42 -0 jakarta-tapestry/framework/src/org/apache/tapestry/asset/Attic/ResourceChecksumSource.java
No revision
No revision
1.41.2.1 +3 -1 jakarta-tapestry/framework/src/org/apache/tapestry/Attic/TapestryStrings.properties
Index: TapestryStrings.properties
===================================================================
RCS file: /home/cvs/jakarta-tapestry/framework/src/org/apache/tapestry/Attic/TapestryStrings.properties,v
retrieving revision 1.41
retrieving revision 1.41.2.1
diff -u -r1.41 -r1.41.2.1
--- TapestryStrings.properties 30 Mar 2004 18:45:25 -0000 1.41
+++ TapestryStrings.properties 17 Mar 2005 08:14:54 -0000 1.41.2.1
@@ -91,6 +91,8 @@
AssetExternalizer.externalize-failure=Could not externalize asset {0} to {1}.
AssetService.exception-report-title=Failure to export asset {0}.
+AssetService.checksum-failure=Checksum {0} does not match that of resource {1}.
+AssetService.checksum-compute-failure=Failed to compute checksum for resource {1}.
ExternalAsset.resource-missing=Could not access external asset {0}.
1.10.2.1 +8 -1 jakarta-tapestry/framework/src/org/apache/tapestry/Attic/IEngine.java
Index: IEngine.java
===================================================================
RCS file: /home/cvs/jakarta-tapestry/framework/src/org/apache/tapestry/Attic/IEngine.java,v
retrieving revision 1.10
retrieving revision 1.10.2.1
diff -u -r1.10 -r1.10.2.1
--- IEngine.java 19 Feb 2004 17:37:36 -0000 1.10
+++ IEngine.java 17 Mar 2005 08:14:54 -0000 1.10.2.1
@@ -19,6 +19,7 @@
import javax.servlet.ServletException;
+import org.apache.tapestry.asset.ResourceChecksumSource;
import org.apache.tapestry.engine.IComponentClassEnhancer;
import org.apache.tapestry.engine.IComponentMessagesSource;
import org.apache.tapestry.engine.IEngineService;
@@ -376,4 +377,10 @@
**/
public String getOutputEncoding();
+
+ /**
+ * Returns an object that can compute the checksum of a resource.
+ * @since 3.0.3
+ */
+ public ResourceChecksumSource getResourceChecksumSource();
}
No revision
No revision
1.3.2.1 +54 -7 jakarta-tapestry/junit/mock-scripts/Attic/TestAssetService.xml
Index: TestAssetService.xml
===================================================================
RCS file: /home/cvs/jakarta-tapestry/junit/mock-scripts/Attic/TestAssetService.xml,v
retrieving revision 1.3
retrieving revision 1.3.2.1
diff -u -r1.3 -r1.3.2.1
--- TestAssetService.xml 9 Mar 2004 22:09:52 -0000 1.3
+++ TestAssetService.xml 17 Mar 2005 08:14:54 -0000 1.3.2.1
@@ -34,14 +34,17 @@
<assert-output name="Image Tag">
<![CDATA[
-<img src="/c16/app?service=asset&sp=S%2Forg%2Fapache%2Ftapestry%2Fjunit%2Fmock%2Fc16%2Flogo.png" border="0"/>
+<img src="/c16/app?service=asset&sp=S%2Forg%2Fapache%2Ftapestry%2Fjunit%2Fmock%2Fc16%2Flogo.png&sp=Sf6324ac8f24f0a7f4850221b0f14c865" border="0"/>
]]>
</assert-output>
</request>
<request>
<parameter name="service" value="asset"/>
- <parameter name="sp" value="/org/apache/tapestry/junit/mock/c16/logo.png"/>
+ <parameter name="sp">
+ <value>/org/apache/tapestry/junit/mock/c16/logo.png</value>
+ <value>Sf6324ac8f24f0a7f4850221b0f14c865</value>
+ </parameter>
<assert-output-stream name="Image Content"
content-type="image/png"
@@ -50,19 +53,46 @@
<request>
<parameter name="service" value="asset"/>
- <parameter name="sp" value="/org/apache/tapestry/junit/mock/c16/globe.jpg"/>
+ <parameter name="sp">
+ <value>/org/apache/tapestry/junit/mock/c16/globe.jpg</value>
+ <value>S52463f90c449b2546814d8929aa7d5cd</value>
+ </parameter>
<assert-output-stream name="Image Content"
content-type="image/jpeg"
path="src/org/apache/tapestry/junit/mock/c16/globe.jpg"/>
</request>
+
+ <!-- Request a file using a bad checksum. -->
+
+ <request>
+ <parameter name="service" value="asset"/>
+ <parameter name="sp">
+ <value>/org/apache/tapestry/junit/mock/c16/logo.png</value>
+ <value>Sabcdef</value>
+ </parameter>
+
+ <assert-output name="Page Title">
+<![CDATA[
+<title>Exception</title>
+]]>
+ </assert-output>
+
+ <assert-output name="Message">
+ Checksum abcdef does not match that of resource /org/apache/tapestry/junit/mock/c16/logo.png.
+ </assert-output>
+
+ </request>
<!-- Request a file which does not exist. -->
<request>
<parameter name="service" value="asset"/>
- <parameter name="sp" value="/org/apache/tapestry/junit/mock/c16/MISSING.gif"/>
-
+ <parameter name="sp">
+ <value>/org/apache/tapestry/junit/mock/c16/MISSING.gif</value>
+ <value>Sabcdef</value>
+ </parameter>
+
<assert-output name="Page Title">
<![CDATA[
<title>Exception</title>
@@ -87,7 +117,24 @@
</assert-output>
<assert-output name="Message">
- Service asset requires exactly one service parameter.
+ Service asset requires exactly 2 service parameters.
+ </assert-output>
+ </request>
+
+ <!-- Request missing the checksum -->
+
+ <request>
+ <parameter name="service" value="asset"/>
+ <parameter name="sp" value="/org/apache/tapestry/junit/mock/c16/MISSING.gif"/>
+
+ <assert-output name="Page Title">
+<![CDATA[
+<title>Exception</title>
+]]>
+ </assert-output>
+
+ <assert-output name="Message">
+ Service asset requires exactly 2 service parameters.
</assert-output>
</request>
---------------------------------------------------------------------
To unsubscribe, e-mail: tapestry-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tapestry-dev-help@jakarta.apache.org