package org.dspace.app.xmlui.cocoon;
import java.io.IOException;
import java.util.Map;
import org.apache.avalon.framework.configuration.Configurable;
import org.apache.avalon.framework.parameters.Parameters;
import org.apache.cocoon.ResourceNotFoundException;
import org.apache.cocoon.reading.ResourceReader;
import org.apache.cocoon.ProcessingException;
import org.apache.cocoon.caching.CacheableProcessingComponent;
import org.apache.cocoon.environment.SourceResolver;
import org.apache.excalibur.source.Source;
import org.xml.sax.SAXException;
/**
* The SafeResourceReader blocks access to specific paths which we do NOT want
* to be readable on the web. By default, the Cocoon ResourceReader just loads
* whatever local file you request, which is not very secure and exposes XMLUI
* to possible directory traversal vulnerabilities (when encoded dots or slashes
* are passed on the URL).
*/
public class SafeResourceReader extends ResourceReader
implements CacheableProcessingComponent, Configurable {
/**
* Setup the reader.
* The resource is opened to get an <code>InputStream</code>,
* the length and the last modification date
*/
@Override
public void setup(SourceResolver resolver, Map objectModel, String src, Parameters par)
throws ProcessingException, SAXException, IOException {
// If the requested path includes any of the following strings/characters
// then block access and return "Resource Not Found"
if(src != null && (
// %252e = double encoded dot (.)
src.toLowerCase().contains("%252e") ||
// %2e = encoded dot (.)
src.toLowerCase().contains("%2e") ||
// %2f = encoded slash (/)
src.toLowerCase().contains("%2f") ||
// block public access to all Cocoon Sitemaps (*.xmap)
src.toLowerCase().contains(".xmap") ||
// block public access to all Theme XSLs
src.toLowerCase().contains(".xsl")
))
{
// Block access by throwing a ResourceNotFound (triggers a 404)
throw new ResourceNotFoundException("Resource not found (" + src + ")");
}
// See if this resource actually exists by attempting to resolve it
// If not, throw a ResourceNotFound (triggers a 404)
Source resource = resolver.resolveURI(src);
if(!resource.exists())
{
throw new ResourceNotFoundException("Resource not found (" + src + ")");
}
// Otherwise, simply load the requested resource via ResourceReader
super.setup(resolver, objectModel, src, par);
}
}