Author: markt Date: Mon Dec 9 10:01:16 2013 New Revision: 1549528 URL: http://svn.apache.org/r1549528 Log: Add an option to the Context to control the blocking of XML external entities when parsing XML configuration files and enable this blocking by default. The block is implemented via a custom resolver to enable the logging of any blocked entities.
Modified: tomcat/trunk/java/org/apache/catalina/Context.java tomcat/trunk/java/org/apache/catalina/Globals.java tomcat/trunk/java/org/apache/catalina/ant/ValidatorTask.java tomcat/trunk/java/org/apache/catalina/core/ApplicationContext.java tomcat/trunk/java/org/apache/catalina/core/StandardContext.java tomcat/trunk/java/org/apache/catalina/startup/ContextConfig.java tomcat/trunk/java/org/apache/catalina/startup/FailedContext.java tomcat/trunk/java/org/apache/jasper/Constants.java tomcat/trunk/java/org/apache/jasper/JspC.java tomcat/trunk/java/org/apache/jasper/compiler/ImplicitTagLibraryInfo.java tomcat/trunk/java/org/apache/jasper/compiler/JspDocumentParser.java tomcat/trunk/java/org/apache/jasper/compiler/TagPluginManager.java tomcat/trunk/java/org/apache/jasper/compiler/TldCache.java tomcat/trunk/java/org/apache/jasper/servlet/JasperInitializer.java tomcat/trunk/java/org/apache/jasper/servlet/JspCServletContext.java tomcat/trunk/java/org/apache/jasper/servlet/TldScanner.java tomcat/trunk/java/org/apache/tomcat/util/descriptor/DigesterFactory.java tomcat/trunk/java/org/apache/tomcat/util/descriptor/LocalResolver.java tomcat/trunk/java/org/apache/tomcat/util/descriptor/LocalStrings.properties tomcat/trunk/java/org/apache/tomcat/util/descriptor/tagplugin/TagPluginParser.java tomcat/trunk/java/org/apache/tomcat/util/descriptor/tld/TldParser.java tomcat/trunk/java/org/apache/tomcat/util/descriptor/web/WebXmlParser.java tomcat/trunk/test/javax/servlet/resources/TestSchemaValidation.java tomcat/trunk/test/org/apache/catalina/core/TesterContext.java tomcat/trunk/test/org/apache/jasper/servlet/TestTldScanner.java tomcat/trunk/test/org/apache/tomcat/util/descriptor/TestLocalResolver.java tomcat/trunk/test/org/apache/tomcat/util/descriptor/tld/TestTldParser.java tomcat/trunk/webapps/docs/config/context.xml tomcat/trunk/webapps/docs/security-howto.xml Modified: tomcat/trunk/java/org/apache/catalina/Context.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/Context.java?rev=1549528&r1=1549527&r2=1549528&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/Context.java (original) +++ tomcat/trunk/java/org/apache/catalina/Context.java Mon Dec 9 10:01:16 2013 @@ -617,6 +617,25 @@ public interface Context extends Contain /** + * Will the parsing of web.xml, web-fragment.xml, *.tld, *.jspx, *.tagx and + * tagplugin.xml files for this Context block the use of external entities? + * + * @return true if access to external entities is blocked + */ + public boolean getXmlBlockExternal(); + + + /** + * Controls whether the parsing of web.xml, web-fragment.xml, *.tld, *.jspx, + * *.tagx and tagplugin.xml files for this Context will block the use of + * external entities. + * + * @param xmlBlockExternal true to block external entities + */ + public void setXmlBlockExternal(boolean xmlBlockExternal); + + + /** * Will the parsing of *.tld files for this Context be performed by a * validating parser? * Modified: tomcat/trunk/java/org/apache/catalina/Globals.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/Globals.java?rev=1549528&r1=1549527&r2=1549528&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/Globals.java (original) +++ tomcat/trunk/java/org/apache/catalina/Globals.java Mon Dec 9 10:01:16 2013 @@ -279,4 +279,15 @@ public final class Globals { */ public static final String JASPER_XML_VALIDATION_TLD_INIT_PARAM = "org.apache.jasper.XML_VALIDATE_TLD"; + + + /** + * Name of the ServletContext init-param that determines if the JSP engine + * will block external entities from being used in *.tld, *.jspx, *.tagx and + * tagplugin.xml files. + * <p> + * This must be kept in sync with org.apache.jasper.Constants + */ + public static final String JASPER_XML_BLOCK_EXTERNAL_INIT_PARAM = + "org.apache.jasper.XML_BLOCK_EXTERNAL"; } Modified: tomcat/trunk/java/org/apache/catalina/ant/ValidatorTask.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/ant/ValidatorTask.java?rev=1549528&r1=1549527&r2=1549528&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/ant/ValidatorTask.java (original) +++ tomcat/trunk/java/org/apache/catalina/ant/ValidatorTask.java Mon Dec 9 10:01:16 2013 @@ -24,6 +24,7 @@ import java.io.File; import java.io.FileInputStream; import java.io.InputStream; +import org.apache.catalina.Globals; import org.apache.catalina.startup.Constants; import org.apache.tomcat.util.descriptor.DigesterFactory; import org.apache.tomcat.util.digester.Digester; @@ -90,7 +91,10 @@ public class ValidatorTask extends BaseR Thread.currentThread().setContextClassLoader (ValidatorTask.class.getClassLoader()); - Digester digester = DigesterFactory.newDigester(true, true, null); + // Called through trusted manager interface. If running under a + // SecurityManager assume that untrusted applications may be deployed. + Digester digester = DigesterFactory.newDigester( + true, true, null, Globals.IS_SECURITY_ENABLED); try { file = file.getCanonicalFile(); InputStream stream = Modified: tomcat/trunk/java/org/apache/catalina/core/ApplicationContext.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/core/ApplicationContext.java?rev=1549528&r1=1549527&r2=1549528&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/core/ApplicationContext.java (original) +++ tomcat/trunk/java/org/apache/catalina/core/ApplicationContext.java Mon Dec 9 10:01:16 2013 @@ -304,12 +304,20 @@ public class ApplicationContext */ @Override public String getInitParameter(final String name) { - // Special handling for XML validation as the context setting must + // Special handling for XML settings as the context setting must // always override anything that might have been set by an application. if (Globals.JASPER_XML_VALIDATION_TLD_INIT_PARAM.equals(name) && context.getTldValidation()) { return "true"; } + if (Globals.JASPER_XML_BLOCK_EXTERNAL_INIT_PARAM.equals(name)) { + if (context.getXmlBlockExternal()) { + return "true"; + } else if (Globals.IS_SECURITY_ENABLED) { + // System admin has explicitly changed the default + return "false"; + } + } return parameters.get(name); } @@ -322,11 +330,14 @@ public class ApplicationContext public Enumeration<String> getInitParameterNames() { Set<String> names = new HashSet<>(); names.addAll(parameters.keySet()); - // Special handling for XML validation as this attribute will always be - // available if validation has been enabled on the context + // Special handling for XML settings as these attributes will always be + // available if they have been set on the context if (context.getTldValidation()) { names.add(Globals.JASPER_XML_VALIDATION_TLD_INIT_PARAM); } + if (context.getXmlBlockExternal() || Globals.IS_SECURITY_ENABLED) { + names.add(Globals.JASPER_XML_BLOCK_EXTERNAL_INIT_PARAM); + } return Collections.enumeration(names); } Modified: tomcat/trunk/java/org/apache/catalina/core/StandardContext.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/core/StandardContext.java?rev=1549528&r1=1549527&r2=1549528&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/core/StandardContext.java (original) +++ tomcat/trunk/java/org/apache/catalina/core/StandardContext.java Mon Dec 9 10:01:16 2013 @@ -699,6 +699,13 @@ public class StandardContext extends Con */ private boolean webXmlNamespaceAware = Globals.STRICT_SERVLET_COMPLIANCE; + + /** + * Attribute used to turn on/off the use of external entities. + */ + private boolean xmlBlockExternal = Globals.IS_SECURITY_ENABLED; + + /** * Attribute value used to turn on/off XML validation */ @@ -6387,6 +6394,18 @@ public class StandardContext extends Con @Override + public void setXmlBlockExternal(boolean xmlBlockExternal) { + this.xmlBlockExternal = xmlBlockExternal; + } + + + @Override + public boolean getXmlBlockExternal() { + return xmlBlockExternal; + } + + + @Override public void setTldValidation(boolean tldValidation) { this.tldValidation = tldValidation; } Modified: tomcat/trunk/java/org/apache/catalina/startup/ContextConfig.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/startup/ContextConfig.java?rev=1549528&r1=1549527&r2=1549528&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/startup/ContextConfig.java (original) +++ tomcat/trunk/java/org/apache/catalina/startup/ContextConfig.java Mon Dec 9 10:01:16 2013 @@ -730,7 +730,7 @@ public class ContextConfig implements Li contextConfig(contextDigester); webXmlParser = new WebXmlParser(context.getXmlNamespaceAware(), - context.getXmlValidation()); + context.getXmlValidation(), context.getXmlBlockExternal()); } Modified: tomcat/trunk/java/org/apache/catalina/startup/FailedContext.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/startup/FailedContext.java?rev=1549528&r1=1549527&r2=1549528&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/startup/FailedContext.java (original) +++ tomcat/trunk/java/org/apache/catalina/startup/FailedContext.java Mon Dec 9 10:01:16 2013 @@ -456,6 +456,11 @@ public class FailedContext extends Lifec public void setXmlValidation(boolean xmlValidation) { /* NO-OP */ } @Override + public boolean getXmlBlockExternal() { return true; } + @Override + public void setXmlBlockExternal(boolean xmlBlockExternal) { /* NO-OP */ } + + @Override public boolean getTldValidation() { return false; } @Override public void setTldValidation(boolean tldValidation){ /* NO-OP */ } Modified: tomcat/trunk/java/org/apache/jasper/Constants.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/jasper/Constants.java?rev=1549528&r1=1549527&r2=1549528&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/jasper/Constants.java (original) +++ tomcat/trunk/java/org/apache/jasper/Constants.java Mon Dec 9 10:01:16 2013 @@ -160,4 +160,13 @@ public class Constants { */ public static final String XML_VALIDATION_TLD_INIT_PARAM = "org.apache.jasper.XML_VALIDATE_TLD"; + + /** + * Name of the ServletContext init-param that determines if the XML parsers + * will block the resolution of external entities. + * <p> + * This must be kept in sync with org.apache.catalina.Globals + */ + public static final String XML_BLOCK_EXTERNAL_INIT_PARAM = + "org.apache.jasper.XML_BLOCK_EXTERNAL"; } Modified: tomcat/trunk/java/org/apache/jasper/JspC.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/jasper/JspC.java?rev=1549528&r1=1549527&r2=1549528&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/jasper/JspC.java (original) +++ tomcat/trunk/java/org/apache/jasper/JspC.java Mon Dec 9 10:01:16 2013 @@ -134,6 +134,7 @@ public class JspC extends Task implement protected static final String SWITCH_SMAP = "-smap"; protected static final String SWITCH_DUMP_SMAP = "-dumpsmap"; protected static final String SWITCH_VALIDATE_TLD = "-validateTld"; + protected static final String SWITCH_BLOCK_EXTERNAL = "-blockExternal"; protected static final String SHOW_SUCCESS ="-s"; protected static final String LIST_ERRORS = "-l"; protected static final int INC_WEBXML = 10; @@ -165,6 +166,7 @@ public class JspC extends Task implement protected boolean trimSpaces = false; protected boolean genStringAsCharArray = false; protected boolean validateTld; + protected boolean blockExternal; protected boolean xpoweredBy; protected boolean mappedFile = false; protected boolean poolingEnabled = true; @@ -373,6 +375,8 @@ public class JspC extends Task implement smapDumped = true; } else if (tok.equals(SWITCH_VALIDATE_TLD)) { setValidateTld(true); + } else if (tok.equals(SWITCH_BLOCK_EXTERNAL)) { + setBlockExternal(true); } else { if (tok.startsWith("-")) { throw new JasperException("Unrecognized option: " + tok + @@ -860,6 +864,14 @@ public class JspC extends Task implement return validateTld; } + public void setBlockExternal( boolean b ) { + this.blockExternal = b; + } + + public boolean isBlockExternal() { + return blockExternal; + } + public void setListErrors( boolean b ) { listErrors = b; } @@ -1440,8 +1452,12 @@ public class JspC extends Task implement if (isValidateTld()) { context.setInitParameter(Constants.XML_VALIDATION_TLD_INIT_PARAM, "true"); } + if (isBlockExternal()) { + context.setInitParameter(Constants.XML_BLOCK_EXTERNAL_INIT_PARAM, "true"); + } - TldScanner scanner = new TldScanner(context, true, isValidateTld()); + TldScanner scanner = new TldScanner( + context, true, isValidateTld(), isBlockExternal()); scanner.setClassLoader(classLoader); try { Modified: tomcat/trunk/java/org/apache/jasper/compiler/ImplicitTagLibraryInfo.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/jasper/compiler/ImplicitTagLibraryInfo.java?rev=1549528&r1=1549527&r2=1549528&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/jasper/compiler/ImplicitTagLibraryInfo.java (original) +++ tomcat/trunk/java/org/apache/jasper/compiler/ImplicitTagLibraryInfo.java Mon Dec 9 10:01:16 2013 @@ -24,6 +24,7 @@ import java.util.Hashtable; import java.util.Set; import java.util.Vector; +import javax.servlet.ServletContext; import javax.servlet.jsp.tagext.FunctionInfo; import javax.servlet.jsp.tagext.TagFileInfo; import javax.servlet.jsp.tagext.TagInfo; @@ -119,10 +120,20 @@ class ImplicitTagLibraryInfo extends Tag try { URL url = ctxt.getResource(path); TldResourcePath resourcePath = new TldResourcePath(url, path); + ServletContext servletContext = ctxt.getServletContext(); boolean validate = Boolean.parseBoolean( - ctxt.getServletContext().getInitParameter( + servletContext.getInitParameter( Constants.XML_VALIDATION_TLD_INIT_PARAM)); - TldParser parser = new TldParser(true, validate, new ImplicitTldRuleSet()); + String blockExternalString = servletContext.getInitParameter( + Constants.XML_BLOCK_EXTERNAL_INIT_PARAM); + boolean blockExternal; + if (blockExternalString == null) { + blockExternal = Constants.IS_SECURITY_ENABLED; + } else { + blockExternal = Boolean.parseBoolean(blockExternalString); + } + TldParser parser = new TldParser(true, validate, + new ImplicitTldRuleSet(), blockExternal); taglibXml = parser.parse(resourcePath); } catch (IOException | SAXException e) { err.jspError(e); Modified: tomcat/trunk/java/org/apache/jasper/compiler/JspDocumentParser.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/jasper/compiler/JspDocumentParser.java?rev=1549528&r1=1549527&r2=1549528&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/jasper/compiler/JspDocumentParser.java (original) +++ tomcat/trunk/java/org/apache/jasper/compiler/JspDocumentParser.java Mon Dec 9 10:01:16 2013 @@ -28,8 +28,11 @@ import javax.servlet.jsp.tagext.TagLibra import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; +import org.apache.jasper.Constants; import org.apache.jasper.JasperException; import org.apache.jasper.JspCompilationContext; +import org.apache.tomcat.util.descriptor.DigesterFactory; +import org.apache.tomcat.util.descriptor.LocalResolver; import org.apache.tomcat.util.descriptor.tld.TldResourcePath; import org.apache.tomcat.util.scan.Jar; import org.xml.sax.Attributes; @@ -39,6 +42,7 @@ import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; import org.xml.sax.XMLReader; import org.xml.sax.ext.DefaultHandler2; +import org.xml.sax.ext.EntityResolver2; import org.xml.sax.helpers.AttributesImpl; /** @@ -91,6 +95,7 @@ class JspDocumentParser private boolean inDTD; private boolean isValidating; + private final EntityResolver2 entityResolver; private final ErrorDispatcher err; private final boolean isTagFile; @@ -119,6 +124,20 @@ class JspDocumentParser this.isTagFile = isTagFile; this.directivesOnly = directivesOnly; this.isTop = true; + + String blockExternalString = ctxt.getServletContext().getInitParameter( + Constants.XML_BLOCK_EXTERNAL_INIT_PARAM); + boolean blockExternal; + if (blockExternalString == null) { + blockExternal = Constants.IS_SECURITY_ENABLED; + } else { + blockExternal = Boolean.parseBoolean(blockExternalString); + } + + this.entityResolver = new LocalResolver( + DigesterFactory.SERVLET_API_PUBLIC_IDS, + DigesterFactory.SERVLET_API_SYSTEM_IDS, + blockExternal); } /* @@ -232,13 +251,26 @@ class JspDocumentParser } } + + @Override + public InputSource getExternalSubset(String name, String baseURI) + throws SAXException, IOException { + return entityResolver.getExternalSubset(name, baseURI); + } + @Override - public InputSource resolveEntity(String name, String publicId, String baseURI, String systemId) + public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException { - // TODO URLs returned by the Jar abstraction may be of the form jar:jar: which - // is not a URL that can be resolved by the JRE. This should use the JarFactory - // to construct and return a valid InputSource. - return null; + return entityResolver.resolveEntity(publicId, systemId); + } + + @Override + public InputSource resolveEntity(String name, String publicId, + String baseURI, String systemId) throws SAXException, IOException { + // TODO URLs returned by the Jar abstraction may be of the form jar:jar: + // which is not a URL that can be resolved by the JRE. This should + // use the JarFactory to construct and return a valid InputSource. + return entityResolver.resolveEntity(name, publicId, baseURI, systemId); } /* Modified: tomcat/trunk/java/org/apache/jasper/compiler/TagPluginManager.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/jasper/compiler/TagPluginManager.java?rev=1549528&r1=1549527&r2=1549528&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/jasper/compiler/TagPluginManager.java (original) +++ tomcat/trunk/java/org/apache/jasper/compiler/TagPluginManager.java Mon Dec 9 10:01:16 2013 @@ -24,6 +24,7 @@ import java.util.Map; import javax.servlet.ServletContext; +import org.apache.jasper.Constants; import org.apache.jasper.JasperException; import org.apache.jasper.compiler.tagplugin.TagPlugin; import org.apache.jasper.compiler.tagplugin.TagPluginContext; @@ -61,7 +62,16 @@ public class TagPluginManager { if (initialized) return; - TagPluginParser parser = new TagPluginParser(ctxt); + String blockExternalString = ctxt.getInitParameter( + Constants.XML_BLOCK_EXTERNAL_INIT_PARAM); + boolean blockExternal; + if (blockExternalString == null) { + blockExternal = Constants.IS_SECURITY_ENABLED; + } else { + blockExternal = Boolean.parseBoolean(blockExternalString); + } + + TagPluginParser parser = new TagPluginParser(ctxt, blockExternal); try { Enumeration<URL> urls = Modified: tomcat/trunk/java/org/apache/jasper/compiler/TldCache.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/jasper/compiler/TldCache.java?rev=1549528&r1=1549527&r2=1549528&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/jasper/compiler/TldCache.java (original) +++ tomcat/trunk/java/org/apache/jasper/compiler/TldCache.java Mon Dec 9 10:01:16 2013 @@ -74,7 +74,15 @@ public class TldCache { } boolean validate = Boolean.parseBoolean( servletContext.getInitParameter(Constants.XML_VALIDATION_TLD_INIT_PARAM)); - tldParser = new TldParser(true, validate); + String blockExternalString = servletContext.getInitParameter( + Constants.XML_BLOCK_EXTERNAL_INIT_PARAM); + boolean blockExternal; + if (blockExternalString == null) { + blockExternal = Constants.IS_SECURITY_ENABLED; + } else { + blockExternal = Boolean.parseBoolean(blockExternalString); + } + tldParser = new TldParser(true, validate, blockExternal); } Modified: tomcat/trunk/java/org/apache/jasper/servlet/JasperInitializer.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/jasper/servlet/JasperInitializer.java?rev=1549528&r1=1549527&r2=1549528&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/jasper/servlet/JasperInitializer.java (original) +++ tomcat/trunk/java/org/apache/jasper/servlet/JasperInitializer.java Mon Dec 9 10:01:16 2013 @@ -80,9 +80,17 @@ public class JasperInitializer implement boolean validate = Boolean.parseBoolean( context.getInitParameter(Constants.XML_VALIDATION_TLD_INIT_PARAM)); + String blockExternalString = context.getInitParameter( + Constants.XML_BLOCK_EXTERNAL_INIT_PARAM); + boolean blockExternal; + if (blockExternalString == null) { + blockExternal = Constants.IS_SECURITY_ENABLED; + } else { + blockExternal = Boolean.parseBoolean(blockExternalString); + } // scan the application for TLDs - TldScanner scanner = new TldScanner(context, true, validate); + TldScanner scanner = new TldScanner(context, true, validate, blockExternal); try { scanner.scan(); } catch (IOException | SAXException e) { Modified: tomcat/trunk/java/org/apache/jasper/servlet/JspCServletContext.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/jasper/servlet/JspCServletContext.java?rev=1549528&r1=1549527&r2=1549528&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/jasper/servlet/JspCServletContext.java (original) +++ tomcat/trunk/java/org/apache/jasper/servlet/JspCServletContext.java Mon Dec 9 10:01:16 2013 @@ -44,11 +44,11 @@ import javax.servlet.SessionCookieConfig import javax.servlet.SessionTrackingMode; import javax.servlet.descriptor.JspConfigDescriptor; +import org.apache.jasper.Constants; import org.apache.jasper.JasperException; import org.apache.jasper.compiler.Localizer; import org.apache.jasper.util.ExceptionUtils; import org.apache.tomcat.JarScanType; -import org.apache.tomcat.util.descriptor.web.Constants; import org.apache.tomcat.util.descriptor.web.FragmentJarScannerCallback; import org.apache.tomcat.util.descriptor.web.WebXml; import org.apache.tomcat.util.descriptor.web.WebXmlParser; @@ -124,13 +124,21 @@ public class JspCServletContext implemen private WebXml buildMergedWebXml() throws JasperException { WebXml webXml = new WebXml(); - - WebXmlParser webXmlParser = new WebXmlParser(false, false); + String blockExternalString = getInitParameter( + Constants.XML_BLOCK_EXTERNAL_INIT_PARAM); + boolean blockExternal; + if (blockExternalString == null) { + blockExternal = Constants.IS_SECURITY_ENABLED; + } else { + blockExternal = Boolean.parseBoolean(blockExternalString); + } + WebXmlParser webXmlParser = new WebXmlParser(false, false, blockExternal); // Use this class's classloader as Ant will have set the TCCL to its own webXmlParser.setClassLoader(getClass().getClassLoader()); try { - URL url = getResource(Constants.WEB_XML_LOCATION); + URL url = getResource( + org.apache.tomcat.util.descriptor.web.Constants.WEB_XML_LOCATION); if (!webXmlParser.parseWebXml(url, webXml, false)) { throw new JasperException(Localizer.getMessage("jspc.error.invalidWebXml")); } Modified: tomcat/trunk/java/org/apache/jasper/servlet/TldScanner.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/jasper/servlet/TldScanner.java?rev=1549528&r1=1549527&r2=1549528&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/jasper/servlet/TldScanner.java (original) +++ tomcat/trunk/java/org/apache/jasper/servlet/TldScanner.java Mon Dec 9 10:01:16 2013 @@ -72,9 +72,11 @@ public class TldScanner { */ public TldScanner(ServletContext context, boolean namespaceAware, - boolean validation) { + boolean validation, + boolean blockExternal) { this.context = context; - this.tldParser = new TldParser(namespaceAware, validation); + + this.tldParser = new TldParser(namespaceAware, validation, blockExternal); } /** Modified: tomcat/trunk/java/org/apache/tomcat/util/descriptor/DigesterFactory.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/descriptor/DigesterFactory.java?rev=1549528&r1=1549527&r2=1549528&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/descriptor/DigesterFactory.java (original) +++ tomcat/trunk/java/org/apache/tomcat/util/descriptor/DigesterFactory.java Mon Dec 9 10:01:16 2013 @@ -16,6 +16,7 @@ */ package org.apache.tomcat.util.descriptor; +import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -23,6 +24,7 @@ import javax.servlet.ServletContext; import org.apache.tomcat.util.digester.Digester; import org.apache.tomcat.util.digester.RuleSet; +import org.xml.sax.ext.EntityResolver2; /** * Wrapper class around the Digester that hide Digester's initialization @@ -31,10 +33,16 @@ import org.apache.tomcat.util.digester.R public class DigesterFactory { /** - * A resolver for the resources packaged in servlet-api.jar + * Mapping of well-known public IDs used by the Servlet API to the matching + * local resource. */ - public static final LocalResolver SERVLET_API_RESOLVER; + public static final Map<String,String> SERVLET_API_PUBLIC_IDS; + /** + * Mapping of well-known system IDs used by the Servlet API to the matching + * local resource. + */ + public static final Map<String,String> SERVLET_API_SYSTEM_IDS; static { Map<String, String> publicIds = new HashMap<>(); @@ -89,7 +97,8 @@ public class DigesterFactory { addSelf(systemIds, "javaee_web_services_1_4.xsd"); addSelf(systemIds, "javaee_web_services_client_1_4.xsd"); - SERVLET_API_RESOLVER = new LocalResolver(publicIds, systemIds); + SERVLET_API_PUBLIC_IDS = Collections.unmodifiableMap(publicIds); + SERVLET_API_SYSTEM_IDS = Collections.unmodifiableMap(systemIds); } private static void addSelf(Map<String, String> ids, String id) { @@ -107,15 +116,19 @@ public class DigesterFactory { * @param xmlValidation turn on/off xml validation * @param xmlNamespaceAware turn on/off namespace validation * @param rule an instance of <code>RuleSet</code> used for parsing the xml. + * @param blockExternal turn on/off the blocking of external resources */ public static Digester newDigester(boolean xmlValidation, boolean xmlNamespaceAware, - RuleSet rule) { + RuleSet rule, + boolean blockExternal) { Digester digester = new Digester(); digester.setNamespaceAware(xmlNamespaceAware); digester.setValidating(xmlValidation); digester.setUseContextClassLoader(true); - digester.setEntityResolver(SERVLET_API_RESOLVER); + EntityResolver2 resolver = new LocalResolver(SERVLET_API_PUBLIC_IDS, + SERVLET_API_SYSTEM_IDS, blockExternal); + digester.setEntityResolver(resolver); if (rule != null) { digester.addRuleSet(rule); } Modified: tomcat/trunk/java/org/apache/tomcat/util/descriptor/LocalResolver.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/descriptor/LocalResolver.java?rev=1549528&r1=1549527&r2=1549528&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/descriptor/LocalResolver.java (original) +++ tomcat/trunk/java/org/apache/tomcat/util/descriptor/LocalResolver.java Mon Dec 9 10:01:16 2013 @@ -16,6 +16,7 @@ */ package org.apache.tomcat.util.descriptor; +import java.io.FileNotFoundException; import java.io.IOException; import java.net.MalformedURLException; import java.net.URI; @@ -23,6 +24,7 @@ import java.net.URISyntaxException; import java.net.URL; import java.util.Map; +import org.apache.tomcat.util.res.StringManager; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.ext.EntityResolver2; @@ -32,22 +34,30 @@ import org.xml.sax.ext.EntityResolver2; */ public class LocalResolver implements EntityResolver2 { + private static final StringManager sm = + StringManager.getManager(Constants.PACKAGE_NAME); + private final Map<String,String> publicIds; private final Map<String,String> systemIds; - + private final boolean blockExternal; /** * Constructor providing mappings of public and system identifiers to local * resources. Each map contains a mapping from a well-known identifier to a * URL for a local resource path. * - * @param publicIds mapping of public identifiers to local resources - * @param systemIds mapping of system identifiers to local resources + * @param publicIds mapping of well-known public identifiers to local + * resources + * @param systemIds mapping of well-known system identifiers to local + * resources + * @param blockExternal are external resources blocked that are not + * well-known */ public LocalResolver(Map<String,String> publicIds, - Map<String,String> systemIds) { + Map<String,String> systemIds, boolean blockExternal) { this.publicIds = publicIds; this.systemIds = systemIds; + this.blockExternal = blockExternal; } @@ -60,63 +70,77 @@ public class LocalResolver implements En @Override public InputSource resolveEntity(String name, String publicId, - String baseURI, String systemId) throws SAXException, IOException { - - String resolved = resolve(publicId, systemId, baseURI); - if (resolved == null) { - return null; - } + String base, String systemId) throws SAXException, IOException { - InputSource is = new InputSource(resolved); - is.setPublicId(publicId); - return is; - } - - - @Override - public InputSource getExternalSubset(String name, String baseURI) - throws SAXException, IOException { - return null; - } - - - private String resolve(String publicId, String systemId, String baseURI) { - // try resolving using the publicId + // First try resolving using the publicId String resolved = publicIds.get(publicId); if (resolved != null) { - return resolved; + InputSource is = new InputSource(resolved); + is.setPublicId(publicId); + return is; } - // try resolving using the systemId + // If there is no systemId, can't try anything else if (systemId == null) { - return null; + throw new FileNotFoundException(sm.getString("localResolver.unresolvedEntity", + name, publicId, systemId, base)); } - systemId = resolve(baseURI, systemId); + // Try resolving with the supplied systemId resolved = systemIds.get(systemId); if (resolved != null) { - return resolved; + InputSource is = new InputSource(resolved); + is.setPublicId(publicId); + return is; } - // fall back to the supplied systemId - return systemId; - } - - - private static String resolve(String baseURI, String systemId) { + // Resolve the supplied systemId against the base + URI systemUri; try { - if (baseURI == null) { - return systemId; + if (base == null) { + systemUri = new URI(systemId); + } else { + // Can't use URI.resolve() because "jar:..." URLs are not valid + // hierarchical URIs so resolve() does not work. new URL() + // delegates to the jar: stream handler and it manages to figure + // it out. + URI baseUri = new URI(base); + systemUri = new URL(baseUri.toURL(), systemId).toURI(); } - URI systemUri = new URI(systemId); - if (systemUri.isAbsolute()) { - return systemId; - } - return new URL(new URL(baseURI), systemId).toString(); + systemUri = systemUri.normalize(); } catch (URISyntaxException e) { - return systemId; - } catch (MalformedURLException e) { - return systemId; + // May be caused by a | being used instead of a : in an absolute + // file URI on Windows. + if (blockExternal) { + // Absolute paths aren't allowed so block it + throw new MalformedURLException(e.getMessage()); + } else { + // See if the URLHandler can resolve it + return new InputSource(systemId); + } + } + if (systemUri.isAbsolute()) { + // Try the resolved systemId + resolved = systemIds.get(systemUri.toString()); + if (resolved != null) { + InputSource is = new InputSource(resolved); + is.setPublicId(publicId); + return is; + } + if (!blockExternal) { + InputSource is = new InputSource(systemUri.toString()); + is.setPublicId(publicId); + return is; + } } + throw new FileNotFoundException(sm.getString("localResolver.unresolvedEntity", + name, publicId, systemId, base)); + } + + + @Override + public InputSource getExternalSubset(String name, String baseURI) + throws SAXException, IOException { + return null; } -} \ No newline at end of file +} Modified: tomcat/trunk/java/org/apache/tomcat/util/descriptor/LocalStrings.properties URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/descriptor/LocalStrings.properties?rev=1549528&r1=1549527&r2=1549528&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/descriptor/LocalStrings.properties (original) +++ tomcat/trunk/java/org/apache/tomcat/util/descriptor/LocalStrings.properties Mon Dec 9 10:01:16 2013 @@ -13,5 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +localResolver.unresolvedEntity=Could not resolve XML resource [{0}] with public ID [{1}], system ID [{2}] and base URI [{3}] to a known, local entity. + xmlErrorHandler.error=Non-fatal error [{0}] reported processing [{1}]. xmlErrorHandler.warning=Warning [{0}] reported processing [{1}]. Modified: tomcat/trunk/java/org/apache/tomcat/util/descriptor/tagplugin/TagPluginParser.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/descriptor/tagplugin/TagPluginParser.java?rev=1549528&r1=1549527&r2=1549528&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/descriptor/tagplugin/TagPluginParser.java (original) +++ tomcat/trunk/java/org/apache/tomcat/util/descriptor/tagplugin/TagPluginParser.java Mon Dec 9 10:01:16 2013 @@ -42,8 +42,9 @@ public class TagPluginParser { private final Digester digester; private final Map<String, String> plugins = new HashMap<>(); - public TagPluginParser(ServletContext context) { - digester = DigesterFactory.newDigester(false, false, new TagPluginRuleSet()); + public TagPluginParser(ServletContext context, boolean blockExternal) { + digester = DigesterFactory.newDigester( + false, false, new TagPluginRuleSet(), blockExternal); digester.setClassLoader(context.getClassLoader()); } Modified: tomcat/trunk/java/org/apache/tomcat/util/descriptor/tld/TldParser.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/descriptor/tld/TldParser.java?rev=1549528&r1=1549527&r2=1549528&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/descriptor/tld/TldParser.java (original) +++ tomcat/trunk/java/org/apache/tomcat/util/descriptor/tld/TldParser.java Mon Dec 9 10:01:16 2013 @@ -35,12 +35,15 @@ public class TldParser { private static final Log log = LogFactory.getLog(TldParser.class); private final Digester digester; - public TldParser(boolean namespaceAware, boolean validation) { - this(namespaceAware, validation, new TldRuleSet()); + public TldParser(boolean namespaceAware, boolean validation, + boolean blockExternal) { + this(namespaceAware, validation, new TldRuleSet(), blockExternal); } - public TldParser(boolean namespaceAware, boolean validation, RuleSet ruleSet) { - digester = DigesterFactory.newDigester(validation, namespaceAware, ruleSet); + public TldParser(boolean namespaceAware, boolean validation, RuleSet ruleSet, + boolean blockExternal) { + digester = DigesterFactory.newDigester( + validation, namespaceAware, ruleSet, blockExternal); } public TaglibXml parse(TldResourcePath path) throws IOException, SAXException { Modified: tomcat/trunk/java/org/apache/tomcat/util/descriptor/web/WebXmlParser.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/descriptor/web/WebXmlParser.java?rev=1549528&r1=1549527&r2=1549528&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/descriptor/web/WebXmlParser.java (original) +++ tomcat/trunk/java/org/apache/tomcat/util/descriptor/web/WebXmlParser.java Mon Dec 9 10:01:16 2013 @@ -55,15 +55,16 @@ public class WebXmlParser { private final WebRuleSet webFragmentRuleSet; - public WebXmlParser(boolean namespaceAware, boolean validation) { + public WebXmlParser(boolean namespaceAware, boolean validation, + boolean blockExternal) { webRuleSet = new WebRuleSet(false); webDigester = DigesterFactory.newDigester(validation, - namespaceAware, webRuleSet); + namespaceAware, webRuleSet, blockExternal); webDigester.getParser(); webFragmentRuleSet = new WebRuleSet(true); webFragmentDigester = DigesterFactory.newDigester(validation, - namespaceAware, webFragmentRuleSet); + namespaceAware, webFragmentRuleSet, blockExternal); webFragmentDigester.getParser(); } Modified: tomcat/trunk/test/javax/servlet/resources/TestSchemaValidation.java URL: http://svn.apache.org/viewvc/tomcat/trunk/test/javax/servlet/resources/TestSchemaValidation.java?rev=1549528&r1=1549527&r2=1549528&view=diff ============================================================================== --- tomcat/trunk/test/javax/servlet/resources/TestSchemaValidation.java (original) +++ tomcat/trunk/test/javax/servlet/resources/TestSchemaValidation.java Mon Dec 9 10:01:16 2013 @@ -31,8 +31,8 @@ public class TestSchemaValidation { @Test public void testWebapp() throws Exception { - Digester digester = - DigesterFactory.newDigester(true, true, new WebRuleSet(false)); + Digester digester = DigesterFactory.newDigester( + true, true, new WebRuleSet(false), true); digester.push(new WebXml()); WebXml desc = (WebXml) digester.parse( new File("test/webapp/WEB-INF/web.xml")); @@ -41,8 +41,8 @@ public class TestSchemaValidation { @Test public void testWebapp_2_2() throws Exception { - Digester digester = - DigesterFactory.newDigester(true, true, new WebRuleSet(false)); + Digester digester = DigesterFactory.newDigester( + true, true, new WebRuleSet(false), true); digester.push(new WebXml()); WebXml desc = (WebXml) digester.parse( new File("test/webapp-2.2/WEB-INF/web.xml")); @@ -52,8 +52,8 @@ public class TestSchemaValidation { @Test public void testWebapp_2_3() throws Exception { - Digester digester = - DigesterFactory.newDigester(true, true, new WebRuleSet(false)); + Digester digester = DigesterFactory.newDigester( + true, true, new WebRuleSet(false), true); digester.push(new WebXml()); WebXml desc = (WebXml) digester.parse( new File("test/webapp-2.3/WEB-INF/web.xml")); @@ -63,8 +63,8 @@ public class TestSchemaValidation { @Test public void testWebapp_2_4() throws Exception { - Digester digester = - DigesterFactory.newDigester(true, true, new WebRuleSet(false)); + Digester digester = DigesterFactory.newDigester( + true, true, new WebRuleSet(false), true); digester.push(new WebXml()); WebXml desc = (WebXml) digester.parse( new File("test/webapp-2.4/WEB-INF/web.xml")); @@ -73,8 +73,8 @@ public class TestSchemaValidation { @Test public void testWebapp_2_5() throws Exception { - Digester digester = - DigesterFactory.newDigester(true, true, new WebRuleSet(false)); + Digester digester = DigesterFactory.newDigester( + true, true, new WebRuleSet(false), true); digester.push(new WebXml()); WebXml desc = (WebXml) digester.parse( new File("test/webapp-2.5/WEB-INF/web.xml")); @@ -83,8 +83,8 @@ public class TestSchemaValidation { @Test public void testWebapp_3_0() throws Exception { - Digester digester = - DigesterFactory.newDigester(true, true, new WebRuleSet(false)); + Digester digester = DigesterFactory.newDigester( + true, true, new WebRuleSet(false), true); digester.push(new WebXml()); WebXml desc = (WebXml) digester.parse( new File("test/webapp-3.0/WEB-INF/web.xml")); @@ -93,8 +93,8 @@ public class TestSchemaValidation { @Test public void testWebapp_3_1() throws Exception { - Digester digester = - DigesterFactory.newDigester(true, true, new WebRuleSet(false)); + Digester digester = DigesterFactory.newDigester( + true, true, new WebRuleSet(false), true); digester.push(new WebXml()); WebXml desc = (WebXml) digester.parse( new File("test/webapp-3.1/WEB-INF/web.xml")); Modified: tomcat/trunk/test/org/apache/catalina/core/TesterContext.java URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/catalina/core/TesterContext.java?rev=1549528&r1=1549527&r2=1549528&view=diff ============================================================================== --- tomcat/trunk/test/org/apache/catalina/core/TesterContext.java (original) +++ tomcat/trunk/test/org/apache/catalina/core/TesterContext.java Mon Dec 9 10:01:16 2013 @@ -643,6 +643,16 @@ public class TesterContext implements Co } @Override + public boolean getXmlBlockExternal() { + return false; + } + + @Override + public void setXmlBlockExternal(boolean xmlBlockExternal) { + // NO-OP + } + + @Override public boolean getTldValidation(){ return false; } Modified: tomcat/trunk/test/org/apache/jasper/servlet/TestTldScanner.java URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/jasper/servlet/TestTldScanner.java?rev=1549528&r1=1549527&r2=1549528&view=diff ============================================================================== --- tomcat/trunk/test/org/apache/jasper/servlet/TestTldScanner.java (original) +++ tomcat/trunk/test/org/apache/jasper/servlet/TestTldScanner.java Mon Dec 9 10:01:16 2013 @@ -39,7 +39,8 @@ public class TestTldScanner extends Tomc Context context = tomcat.addWebapp(null, "/test", appDir.getAbsolutePath()); tomcat.start(); - TldScanner scanner = new TldScanner(context.getServletContext(), true, true); + TldScanner scanner = + new TldScanner(context.getServletContext(), true, true, true); scanner.scan(); Assert.assertEquals(5, scanner.getUriTldResourcePathMap().size()); Assert.assertEquals(1, scanner.getListeners().size()); Modified: tomcat/trunk/test/org/apache/tomcat/util/descriptor/TestLocalResolver.java URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/tomcat/util/descriptor/TestLocalResolver.java?rev=1549528&r1=1549527&r2=1549528&view=diff ============================================================================== --- tomcat/trunk/test/org/apache/tomcat/util/descriptor/TestLocalResolver.java (original) +++ tomcat/trunk/test/org/apache/tomcat/util/descriptor/TestLocalResolver.java Mon Dec 9 10:01:16 2013 @@ -16,6 +16,7 @@ */ package org.apache.tomcat.util.descriptor; +import java.io.FileNotFoundException; import java.io.IOException; import java.util.HashMap; import java.util.Map; @@ -34,7 +35,7 @@ public class TestLocalResolver { private final Map<String, String> publicIds = new HashMap<>(); private final Map<String, String> systemIds = new HashMap<>(); - private LocalResolver resolver = new LocalResolver(publicIds, systemIds); + private LocalResolver resolver = new LocalResolver(publicIds, systemIds, true); private String WEB_22_LOCAL; private String WEB_31_LOCAL; private String WEBCOMMON_31_LOCAL; @@ -53,25 +54,25 @@ public class TestLocalResolver { return ServletContext.class.getResource(id).toExternalForm(); } - @Test - public void unknownNullIdIsNull() throws IOException, SAXException { + @Test(expected = FileNotFoundException.class) + public void unknownNullId() throws IOException, SAXException { Assert.assertNull(resolver.resolveEntity(null, null)); } - @Test - public void unknownPublicIdIsNull() throws IOException, SAXException { + @Test(expected = FileNotFoundException.class) + public void unknownPublicId() throws IOException, SAXException { Assert.assertNull(resolver.resolveEntity("unknown", null)); } - @Test - public void unknownSystemIdIsReturned() throws IOException, SAXException { + @Test(expected = FileNotFoundException.class) + public void unknownSystemId() throws IOException, SAXException { InputSource source = resolver.resolveEntity(null, "unknown"); Assert.assertEquals(null, source.getPublicId()); Assert.assertEquals("unknown", source.getSystemId()); } - @Test - public void unknownSystemIdIsResolvedAgainstBaseURI() + @Test(expected = FileNotFoundException.class) + public void unknownRelativeSystemId() throws IOException, SAXException { InputSource source = resolver.resolveEntity( null, null, "http://example.com/home.html", "unknown"); @@ -121,4 +122,4 @@ public class TestLocalResolver { Assert.assertEquals(null, source.getPublicId()); Assert.assertEquals(WEB_31_LOCAL, source.getSystemId()); } -} \ No newline at end of file +} Modified: tomcat/trunk/test/org/apache/tomcat/util/descriptor/tld/TestTldParser.java URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/tomcat/util/descriptor/tld/TestTldParser.java?rev=1549528&r1=1549527&r2=1549528&view=diff ============================================================================== --- tomcat/trunk/test/org/apache/tomcat/util/descriptor/tld/TestTldParser.java (original) +++ tomcat/trunk/test/org/apache/tomcat/util/descriptor/tld/TestTldParser.java Mon Dec 9 10:01:16 2013 @@ -36,7 +36,7 @@ public class TestTldParser { @Before public void init() { - parser = new TldParser(true, true); + parser = new TldParser(true, true, null, true); } @Test Modified: tomcat/trunk/webapps/docs/config/context.xml URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/config/context.xml?rev=1549528&r1=1549527&r2=1549528&view=diff ============================================================================== --- tomcat/trunk/webapps/docs/config/context.xml (original) +++ tomcat/trunk/webapps/docs/config/context.xml Mon Dec 9 10:01:16 2013 @@ -524,6 +524,16 @@ Context. If not specified, a standard default value will be used.</p> </attribute> + <attribute name="xmlBlockExternal" required="false"> + <p>If the value of this flag is <code>true</code>, the parsing of + <code>web.xml</code>, <code>web-fragment.xml</code>, <code>*.tld</code>, + <code>*.jspx</code>, <code>*.tagx</code> and <code>tagPlugins.xml</code> + files for this web application will not permit external entities to be + loaded. If a <code>SecurityManager</code> is configured then the default + value of this attribute will be <code>true</code>, else the default + value will be <code>false</code>.</p> + </attribute> + <attribute name="xmlNamespaceAware" required="false"> <p>If the value of this flag is <code>true</code>, the parsing of <code>web.xml</code> and <code>web-fragment.xml</code> files for this Modified: tomcat/trunk/webapps/docs/security-howto.xml URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/security-howto.xml?rev=1549528&r1=1549527&r2=1549528&view=diff ============================================================================== --- tomcat/trunk/webapps/docs/security-howto.xml (original) +++ tomcat/trunk/webapps/docs/security-howto.xml Mon Dec 9 10:01:16 2013 @@ -179,6 +179,9 @@ <ul> <li>The default value for the <strong>deployXML</strong> attribute of the <strong>Host</strong> element is changed to <code>false</code>.</li> + <li>The default value for the <strong>xmlBlockExternal</strong> attribute + of the <strong>Context</strong> element is changed to <code>true</code>. + </li> </ul> </section> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org