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&amp;sp=S%2Forg%2Fapache%2Ftapestry%2Fjunit%2Fmock%2Fc16%2Flogo.png" border="0"/>
  +<img src="/c16/app?service=asset&amp;sp=S%2Forg%2Fapache%2Ftapestry%2Fjunit%2Fmock%2Fc16%2Flogo.png&amp;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