From f90819793e4da6c0cc3e7c19d29b48710e29d05b Mon Sep 17 00:00:00 2001
From: CentOS Sources
Date: Aug 07 2014 16:38:40 +0000
Subject: import tomcat-7.0.42-8.el7_0
---
diff --git a/SOURCES/tomcat-7.0.42-CVE-2013-4590.patch b/SOURCES/tomcat-7.0.42-CVE-2013-4590.patch
new file mode 100644
index 0000000..2382995
--- /dev/null
+++ b/SOURCES/tomcat-7.0.42-CVE-2013-4590.patch
@@ -0,0 +1,3141 @@
+--- java/org/apache/catalina/Context.java.orig 2014-07-21 17:24:05.516400000 -0400
++++ java/org/apache/catalina/Context.java 2014-07-21 17:46:59.386109000 -0400
+@@ -40,6 +40,7 @@
+ import org.apache.catalina.deploy.NamingResources;
+ import org.apache.catalina.deploy.SecurityConstraint;
+ import org.apache.catalina.util.CharsetMapper;
++import org.apache.tomcat.InstanceManager;
+ import org.apache.tomcat.JarScanner;
+ import org.apache.tomcat.util.http.mapper.Mapper;
+
+@@ -61,7 +62,7 @@
+ *
+ *
+ * @author Craig R. McClanahan
+- * @version $Id: Context.java 1492415 2013-06-12 20:41:33Z markt $
++ * @version $Id: Context.java 1552258 2013-12-19 09:25:18Z markt $
+ */
+
+ public interface Context extends Container {
+@@ -616,70 +617,99 @@
+
+
+ /**
+- * Get the server.xml attribute's xmlNamespaceAware.
+- * @return true if namespace awareness is enabled.
++ * Will the parsing of web.xml and web-fragment.xml files for this Context
++ * be performed by a namespace aware parser?
+ *
++ * @return true if namespace awareness is enabled.
+ */
+ public boolean getXmlNamespaceAware();
+
++
++ /**
++ * Controls whether the parsing of web.xml and web-fragment.xml files for
++ * this Context will be performed by a namespace aware parser.
++ *
++ * @param xmlNamespaceAware true to enable namespace awareness
++ */
++ public void setXmlNamespaceAware(boolean xmlNamespaceAware);
+
++
+ /**
+- * Get the server.xml attribute's xmlValidation.
+- * @return true if validation is enabled.
++ * Will the parsing of web.xml and web-fragment.xml files for this Context
++ * be performed by a validating parser?
+ *
++ * @return true if validation is enabled.
+ */
+ public boolean getXmlValidation();
+
+
+ /**
+- * Set the validation feature of the XML parser used when
+- * parsing xml instances.
+- * @param xmlValidation true to enable xml instance validation
++ * Controls whether the parsing of web.xml and web-fragment.xml files
++ * for this Context will be performed by a validating parser.
++ *
++ * @param xmlValidation true to enable xml validation
+ */
+ public void setXmlValidation(boolean xmlValidation);
+
+
+- /**
+- * Set the namespace aware feature of the XML parser used when
+- * parsing xml instances.
+- * @param xmlNamespaceAware true to enable namespace awareness
++ /**
++ * *.tld files are always parsed using a namespace aware parser.
++ *
++ * @return Always true
++ *
++ * @deprecated This option will be removed in 8.0.x.
+ */
+- public void setXmlNamespaceAware(boolean xmlNamespaceAware);
++ @Deprecated
++ public boolean getTldNamespaceAware();
++
++
+ /**
+- * Get the server.xml attribute's xmlValidation.
+- * @return true if validation is enabled.
++ * *.tld files are always parsed using a namespace aware parser.
++ *
++ * @param tldNamespaceAware ignored
++ *
++ * @deprecated This option will be removed in 8.0.x.
+ */
++ @Deprecated
++ public void setTldNamespaceAware(boolean tldNamespaceAware);
+
+
+ /**
+- * Set the validation feature of the XML parser used when
+- * parsing tlds files.
+- * @param tldValidation true to enable xml instance validation
++ * 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 void setTldValidation(boolean tldValidation);
++ public boolean getXmlBlockExternal();
+
+
+ /**
+- * Get the server.xml attribute's webXmlValidation.
+- * @return true if validation is enabled.
++ * 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 boolean getTldValidation();
++ public void setXmlBlockExternal(boolean xmlBlockExternal);
+
+
+ /**
+- * Get the server.xml <host> attribute's xmlNamespaceAware.
+- * @return true if namespace awareness is enabled.
++ * Will the parsing of *.tld files for this Context be performed by a
++ * validating parser?
++ *
++ * @return true if validation is enabled.
+ */
+- public boolean getTldNamespaceAware();
++ public boolean getTldValidation();
+
+
+ /**
+- * Set the namespace aware feature of the XML parser used when
+- * parsing xml instances.
+- * @param tldNamespaceAware true to enable namespace awareness
++ * Controls whether the parsing of *.tld files for this Context will be
++ * performed by a validating parser.
++ *
++ * @param tldValidation true to enable xml validation
+ */
+- public void setTldNamespaceAware(boolean tldNamespaceAware);
++ public void setTldValidation(boolean tldValidation);
++
+
+ /**
+ * Get the Jar Scanner to be used to scan for JAR resources for this
+@@ -712,6 +742,16 @@
+ */
+ public boolean getLogEffectiveWebXml();
+
++ /**
++ * Get the instance manager associated with this context.
++ */
++ public InstanceManager getInstanceManager();
++
++ /**
++ * Set the instance manager associated with this context.
++ */
++ public void setInstanceManager(InstanceManager instanceManager);
++
+ // --------------------------------------------------------- Public Methods
+
+
+--- java/org/apache/catalina/Globals.java.orig 2014-07-21 17:24:05.521402000 -0400
++++ java/org/apache/catalina/Globals.java 2014-07-21 17:46:59.394034000 -0400
+@@ -14,18 +14,14 @@
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-
+-
+ package org.apache.catalina;
+
+-
+ /**
+ * Global constants that are applicable to multiple packages within Catalina.
+ *
+ * @author Craig R. McClanahan
+- * @version $Id: Globals.java 1301255 2012-03-15 22:47:40Z markt $
++ * @version $Id: Globals.java 1549529 2013-12-09 10:05:56Z markt $
+ */
+-
+ public final class Globals {
+
+ /**
+@@ -310,4 +306,25 @@
+ * the tomcat instance installation path
+ */
+ public static final String CATALINA_BASE_PROP = "catalina.base";
++
++
++ /**
++ * Name of the ServletContext init-param that determines if the JSP engine
++ * should validate *.tld files when parsing them.
++ *
++ * This must be kept in sync with org.apache.jasper.Constants
++ */
++ 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.
++ *
++ * 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";
+ }
+--- java/org/apache/catalina/ant/ValidatorTask.java.orig 2014-07-21 17:24:05.537406000 -0400
++++ java/org/apache/catalina/ant/ValidatorTask.java 2014-07-21 17:46:59.401034000 -0400
+@@ -14,18 +14,16 @@
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-
+-
+ package org.apache.catalina.ant;
+
+-
+ import java.io.BufferedInputStream;
+ 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.catalina.startup.DigesterFactory;
++import org.apache.tomcat.util.descriptor.DigesterFactory;
+ import org.apache.tomcat.util.digester.Digester;
+ import org.apache.tools.ant.BuildException;
+ import org.xml.sax.InputSource;
+@@ -36,7 +34,7 @@
+ * schema validation.
+ *
+ * @author Remy Maucherat
+- * @version $Id: ValidatorTask.java 1001899 2010-09-27 20:24:18Z markt $
++ * @version $Id: ValidatorTask.java 1549529 2013-12-09 10:05:56Z markt $
+ * @since 5.0
+ */
+
+@@ -90,7 +88,10 @@
+ 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 =
+--- java/org/apache/catalina/core/ApplicationContext.java.orig 2014-07-21 17:24:05.543399000 -0400
++++ java/org/apache/catalina/core/ApplicationContext.java 2014-07-22 16:07:21.579832000 -0400
+@@ -5,9 +5,9 @@
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+- *
++ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+- *
++ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@@ -84,7 +84,7 @@
+ *
+ * @author Craig R. McClanahan
+ * @author Remy Maucherat
+- * @version $Id: ApplicationContext.java 1493015 2013-06-14 10:00:57Z markt $
++ * @version $Id: ApplicationContext.java 1549529 2013-12-09 10:05:56Z markt $
+ */
+
+ public class ApplicationContext
+@@ -97,7 +97,7 @@
+
+ static {
+ STRICT_SERVLET_COMPLIANCE = Globals.STRICT_SERVLET_COMPLIANCE;
+-
++
+ String requireSlash = System.getProperty(
+ "org.apache.catalina.core.ApplicationContext.GET_RESOURCE_REQUIRE_SLASH");
+ if (requireSlash == null) {
+@@ -302,7 +302,7 @@
+ }
+ }
+
+-
++
+ /**
+ * Return the main path associated with this context.
+ */
+@@ -310,7 +310,7 @@
+ public String getContextPath() {
+ return context.getPath();
+ }
+-
++
+
+ /**
+ * Return the value of the specified initialization parameter, or
+@@ -320,6 +320,20 @@
+ */
+ @Override
+ public String getInitParameter(final String name) {
++ // 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);
+ }
+
+@@ -330,7 +344,17 @@
+ */
+ @Override
+ public Enumeration getInitParameterNames() {
+- return Collections.enumeration(parameters.keySet());
++ Set names = new HashSet();
++ names.addAll(parameters.keySet());
++ // 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);
+ }
+
+
+@@ -395,7 +419,7 @@
+ Wrapper wrapper = (Wrapper) context.findChild(name);
+ if (wrapper == null)
+ return (null);
+-
++
+ return new ApplicationDispatcher(wrapper, null, null, null, null, name);
+
+ }
+@@ -444,7 +468,7 @@
+ if (normalizedPath == null)
+ return (null);
+
+- pos = normalizedPath.length();
++ pos = normalizedPath.length();
+
+ // Use the thread local URI and mapping data
+ DispatchData dd = dispatchData.get();
+@@ -495,10 +519,10 @@
+ String pathInfo = mappingData.pathInfo.toString();
+
+ mappingData.recycle();
+-
++
+ // Construct a RequestDispatcher to process this request
+ return new ApplicationDispatcher
+- (wrapper, uriCC.toString(), wrapperPath, pathInfo,
++ (wrapper, uriCC.toString(), wrapperPath, pathInfo,
+ queryString, null);
+
+ }
+@@ -523,7 +547,7 @@
+ !path.startsWith("/") && GET_RESOURCE_REQUIRE_SLASH)
+ throw new MalformedURLException(sm.getString(
+ "applicationContext.requestDispatcher.iae", path));
+-
++
+ String normPath = RequestUtil.normalize(path);
+ if (normPath == null)
+ return (null);
+@@ -724,7 +748,7 @@
+ @Override
+ @Deprecated
+ public void log(Exception exception, String message) {
+-
++
+ context.getLogger().error(message, exception);
+
+ }
+@@ -738,7 +762,7 @@
+ */
+ @Override
+ public void log(String message, Throwable throwable) {
+-
++
+ context.getLogger().error(message, throwable);
+
+ }
+@@ -893,11 +917,11 @@
+ @Override
+ public FilterRegistration.Dynamic addFilter(String filterName,
+ String filterClass) throws IllegalStateException {
+-
++
+ return addFilter(filterName, filterClass, null);
+ }
+
+-
++
+ /**
+ * Add filter to context.
+ * @param filterName Name of filter to add
+@@ -915,11 +939,11 @@
+ @Override
+ public FilterRegistration.Dynamic addFilter(String filterName,
+ Filter filter) throws IllegalStateException {
+-
++
+ return addFilter(filterName, null, filter);
+ }
+
+-
++
+ /**
+ * Add filter to context.
+ * @param filterName Name of filter to add
+@@ -937,13 +961,13 @@
+ @Override
+ public FilterRegistration.Dynamic addFilter(String filterName,
+ Class extends Filter> filterClass) throws IllegalStateException {
+-
++
+ return addFilter(filterName, filterClass.getName(), null);
+ }
+
+ private FilterRegistration.Dynamic addFilter(String filterName,
+ String filterClass, Filter filter) throws IllegalStateException {
+-
++
+ if (filterName == null || filterName.equals("")) {
+ throw new IllegalArgumentException(sm.getString(
+ "applicationContext.invalidFilterName", filterName));
+@@ -957,7 +981,7 @@
+ }
+
+ FilterDef filterDef = context.findFilterDef(filterName);
+-
++
+ // Assume a 'complete' FilterRegistration is one that has a class and
+ // a name
+ if (filterDef == null) {
+@@ -977,14 +1001,15 @@
+ filterDef.setFilterClass(filter.getClass().getName());
+ filterDef.setFilter(filter);
+ }
+-
++
+ return new ApplicationFilterRegistration(filterDef, context);
+- }
+-
++ }
++
+ @Override
+ public T createFilter(Class c)
+ throws ServletException {
+ try {
++ @SuppressWarnings("unchecked")
+ T filter = (T) context.getInstanceManager().newInstance(c.getName());
+ return filter;
+ } catch (IllegalAccessException e) {
+@@ -1011,7 +1036,7 @@
+ return new ApplicationFilterRegistration(filterDef, context);
+ }
+
+-
++
+ /**
+ * Add servlet to context.
+ * @param servletName Name of servlet to add
+@@ -1029,7 +1054,7 @@
+ @Override
+ public ServletRegistration.Dynamic addServlet(String servletName,
+ String servletClass) throws IllegalStateException {
+-
++
+ return addServlet(servletName, servletClass, null);
+ }
+
+@@ -1055,7 +1080,7 @@
+ return addServlet(servletName, null, servlet);
+ }
+
+-
++
+ /**
+ * Add servlet to context.
+ * @param servletName Name of servlet to add
+@@ -1080,7 +1105,7 @@
+
+ private ServletRegistration.Dynamic addServlet(String servletName,
+ String servletClass, Servlet servlet) throws IllegalStateException {
+-
++
+ if (servletName == null || servletName.equals("")) {
+ throw new IllegalArgumentException(sm.getString(
+ "applicationContext.invalidServletName", servletName));
+@@ -1092,9 +1117,9 @@
+ sm.getString("applicationContext.addServlet.ise",
+ getContextPath()));
+ }
+-
++
+ Wrapper wrapper = (Wrapper) context.findChild(servletName);
+-
++
+ // Assume a 'complete' ServletRegistration is one that has a class and
+ // a name
+ if (wrapper == null) {
+@@ -1127,6 +1152,7 @@
+ public T createServlet(Class c)
+ throws ServletException {
+ try {
++ @SuppressWarnings("unchecked")
+ T servlet = (T) context.getInstanceManager().newInstance(c.getName());
+ context.dynamicServletCreated(servlet);
+ return servlet;
+@@ -1151,10 +1177,10 @@
+ if (wrapper == null) {
+ return null;
+ }
+-
++
+ return new ApplicationServletRegistration(wrapper, context);
+ }
+-
++
+
+ /**
+ * By default {@link SessionTrackingMode#URL} is always supported, {@link
+@@ -1171,15 +1197,15 @@
+
+ private void populateSessionTrackingModes() {
+ // URL re-writing is always enabled by default
+- defaultSessionTrackingModes = EnumSet.of(SessionTrackingMode.URL);
++ defaultSessionTrackingModes = EnumSet.of(SessionTrackingMode.URL);
+ supportedSessionTrackingModes = EnumSet.of(SessionTrackingMode.URL);
+-
++
+ if (context.getCookies()) {
+ defaultSessionTrackingModes.add(SessionTrackingMode.COOKIE);
+ supportedSessionTrackingModes.add(SessionTrackingMode.COOKIE);
+ }
+
+- // SSL not enabled by default as it can only used on its own
++ // SSL not enabled by default as it can only used on its own
+ // Context > Host > Engine > Service
+ Service s = ((Engine) context.getParent().getParent()).getService();
+ Connector[] connectors = s.findConnectors();
+@@ -1189,7 +1215,7 @@
+ supportedSessionTrackingModes.add(SessionTrackingMode.SSL);
+ break;
+ }
+- }
++ }
+ }
+
+ /**
+@@ -1226,7 +1252,7 @@
+ sm.getString("applicationContext.setSessionTracking.ise",
+ getContextPath()));
+ }
+-
++
+ // Check that only supported tracking modes have been requested
+ for (SessionTrackingMode sessionTrackingMode : sessionTrackingModes) {
+ if (!supportedSessionTrackingModes.contains(sessionTrackingMode)) {
+@@ -1244,7 +1270,7 @@
+ getContextPath()));
+ }
+ }
+-
++
+ this.sessionTrackingModes = sessionTrackingModes;
+ }
+
+@@ -1253,8 +1279,8 @@
+ public boolean setInitParameter(String name, String value) {
+ return parameters.putIfAbsent(name, value) == null;
+ }
+-
+-
++
++
+ @Override
+ public void addListener(Class extends EventListener> listenerClass) {
+ EventListener listener;
+@@ -1271,7 +1297,7 @@
+
+ @Override
+ public void addListener(String className) {
+-
++
+ try {
+ Object obj = context.getInstanceManager().newInstance(className);
+
+@@ -1305,7 +1331,7 @@
+ "applicationContext.addListener.iae.cnfe", className),
+ e);
+ }
+-
++
+ }
+
+
+@@ -1325,7 +1351,7 @@
+ context.addApplicationEventListener(t);
+ match = true;
+ }
+-
++
+ if (t instanceof HttpSessionListener
+ || (t instanceof ServletContextListener &&
+ newServletContextListenerAllowed)) {
+@@ -1334,9 +1360,9 @@
+ context.addApplicationLifecycleListener(t);
+ match = true;
+ }
+-
++
+ if (match) return;
+-
++
+ if (t instanceof ServletContextListener) {
+ throw new IllegalArgumentException(sm.getString(
+ "applicationContext.addListener.iae.sclNotAllowed",
+@@ -1353,8 +1379,9 @@
+ public T createListener(Class c)
+ throws ServletException {
+ try {
++ @SuppressWarnings("unchecked")
+ T listener =
+- (T) context.getInstanceManager().newInstance(c.getName());
++ (T) context.getInstanceManager().newInstance(c);
+ if (listener instanceof ServletContextListener ||
+ listener instanceof ServletContextAttributeListener ||
+ listener instanceof ServletRequestListener ||
+@@ -1375,27 +1402,26 @@
+ throw new ServletException(e);
+ } catch (InstantiationException e) {
+ throw new ServletException(e);
+- } catch (ClassNotFoundException e) {
+- throw new ServletException(e);
+- } }
++ }
++ }
+
+
+ @Override
+ public void declareRoles(String... roleNames) {
+-
++
+ if (!context.getState().equals(LifecycleState.STARTING_PREP)) {
+ //TODO Spec breaking enhancement to ignore this restriction
+ throw new IllegalStateException(
+ sm.getString("applicationContext.addRole.ise",
+ getContextPath()));
+ }
+-
++
+ if (roleNames == null) {
+ throw new IllegalArgumentException(
+ sm.getString("applicationContext.roles.iae",
+ getContextPath()));
+ }
+-
++
+ for (String role : roleNames) {
+ if (role == null || "".equals(role)) {
+ throw new IllegalArgumentException(
+@@ -1424,7 +1450,7 @@
+ new RuntimePermission("getClassLoader"));
+ }
+ }
+-
++
+ return result;
+ }
+
+@@ -1445,7 +1471,7 @@
+ public Map getFilterRegistrations() {
+ Map result =
+ new HashMap();
+-
++
+ FilterDef[] filterDefs = context.findFilterDefs();
+ for (FilterDef filterDef : filterDefs) {
+ result.put(filterDef.getFilterName(),
+@@ -1473,7 +1499,7 @@
+ public Map getServletRegistrations() {
+ Map result =
+ new HashMap();
+-
++
+ Container[] wrappers = context.findChildren();
+ for (Container wrapper : wrappers) {
+ result.put(((Wrapper) wrapper).getName(),
+@@ -1484,12 +1510,12 @@
+ return result;
+ }
+
+-
++
+ // -------------------------------------------------------- Package Methods
+ protected StandardContext getContext() {
+ return this.context;
+ }
+-
++
+ @Deprecated
+ protected Map getReadonlyAttributes() {
+ return this.readOnlyAttributes;
+@@ -1513,10 +1539,10 @@
+ String key = keys.next();
+ removeAttribute(key);
+ }
+-
++
+ }
+-
+-
++
++
+ /**
+ * Return the facade associated with this ApplicationContext.
+ */
+@@ -1541,7 +1567,7 @@
+ protected void setNewServletContextListenerAllowed(boolean allowed) {
+ this.newServletContextListenerAllowed = allowed;
+ }
+-
++
+ /**
+ * List resource paths (recursively), and store all of them in the given
+ * Set.
+@@ -1572,13 +1598,13 @@
+ */
+ private static String getJNDIUri(String hostName, String path) {
+ String result;
+-
++
+ if (path.startsWith("/")) {
+ result = "/" + hostName + path;
+ } else {
+ result = "/" + hostName + "/" + path;
+ }
+-
++
+ return result;
+ }
+
+--- java/org/apache/catalina/core/StandardContext.java.orig 2014-07-21 17:24:05.568403000 -0400
++++ java/org/apache/catalina/core/StandardContext.java 2014-07-22 16:08:44.199113000 -0400
+@@ -126,6 +126,7 @@
+ import org.apache.tomcat.InstanceManager;
+ import org.apache.tomcat.JarScanner;
+ import org.apache.tomcat.util.ExceptionUtils;
++import org.apache.tomcat.util.descriptor.XmlIdentifiers;
+ import org.apache.tomcat.util.modeler.Registry;
+ import org.apache.tomcat.util.scan.StandardJarScanner;
+
+@@ -136,7 +137,7 @@
+ *
+ * @author Craig R. McClanahan
+ * @author Remy Maucherat
+- * @version $Id: StandardContext.java 1493073 2013-06-14 13:51:13Z markt $
++ * @version $Id: StandardContext.java 1549529 2013-12-09 10:05:56Z markt $
+ */
+
+ public class StandardContext extends ContainerBase
+@@ -524,6 +525,12 @@
+
+
+ /**
++ * Context level override for default {@link StandardHost#isCopyXML()}.
++ */
++ private boolean copyXML = false;
++
++
++ /**
+ * The default context override flag for this web application.
+ */
+ private boolean override = false;
+@@ -691,6 +698,13 @@
+ protected int cacheMaxSize = 10240; // 10 MB
+
+
++
++ /**
++ * Attribute used to turn on/off the use of external entities.
++ */
++ private boolean xmlBlockExternal = Globals.IS_SECURITY_ENABLED;
++
++
+ /**
+ * Cache object max size in KB.
+ */
+@@ -726,7 +740,8 @@
+
+
+ /**
+- * Attribute value used to turn on/off XML validation
++ * Attribute value used to turn on/off XML validation for web.xml and
++ * web-fragment.xml files.
+ */
+ private boolean webXmlValidation = Globals.STRICT_SERVLET_COMPLIANCE;
+
+@@ -748,12 +763,6 @@
+
+
+ /**
+- * Attribute value used to turn on/off TLD XML namespace validation
+- */
+- private boolean tldNamespaceAware = Globals.STRICT_SERVLET_COMPLIANCE;
+-
+-
+- /**
+ * Should we save the configuration.
+ */
+ private boolean saveConfig = true;
+@@ -1055,11 +1064,13 @@
+ }
+
+
++ @Override
+ public InstanceManager getInstanceManager() {
+ return instanceManager;
+ }
+
+
++ @Override
+ public void setInstanceManager(InstanceManager instanceManager) {
+ this.instanceManager = instanceManager;
+ }
+@@ -2463,6 +2474,17 @@
+
+ }
+
++
++ public boolean getCopyXML() {
++ return copyXML;
++ }
++
++
++ public void setCopyXML(boolean copyXML) {
++ this.copyXML = copyXML;
++ }
++
++
+ /**
+ * Return the Java class name of the Wrapper implementation used
+ * for servlets registered in this Context.
+@@ -4861,7 +4883,7 @@
+ ExceptionUtils.handleThrowable(t);
+ getLogger().error
+ (sm.getString("standardContext.applicationListener",
+- listeners[i]), t);
++ listeners[i].getClassName()), t);
+ ok = false;
+ }
+ }
+@@ -5233,8 +5255,7 @@
+ }
+ if (ok) {
+ if (!resourcesStart()) {
+- log.error( "Error in resourceStart()");
+- ok = false;
++ throw new LifecycleException("Error in resourceStart()");
+ }
+ }
+
+@@ -5822,17 +5843,10 @@
+ */
+ @Override
+ public boolean isServlet22() {
+-
+- if (this.publicId == null)
+- return (false);
+- if (this.publicId.equals
+- (org.apache.catalina.startup.Constants.WebDtdPublicId_22))
+- return (true);
+- else
+- return (false);
+-
++ return XmlIdentifiers.WEB_22_PUBLIC.equals(publicId);
+ }
+
++
+ @Override
+ public Set addServletSecurity(
+ ApplicationServletRegistration registration,
+@@ -5928,7 +5942,7 @@
+ if (getResources() == null)
+ return oldContextClassLoader;
+
+- if (getLoader().getClassLoader() != null) {
++ if (getLoader() != null && getLoader().getClassLoader() != null) {
+ Thread.currentThread().setContextClassLoader
+ (getLoader().getClassLoader());
+ }
+@@ -6580,72 +6594,67 @@
+
+ }
+
+- /**
+- * Set the validation feature of the XML parser used when
+- * parsing xml instances.
+- * @param webXmlValidation true to enable xml instance validation
+- */
++
++ @Override
++ public boolean getXmlNamespaceAware(){
++ return webXmlNamespaceAware;
++ }
++
++
++ @Override
++ public void setXmlNamespaceAware(boolean webXmlNamespaceAware){
++ this.webXmlNamespaceAware = webXmlNamespaceAware;
++ }
++
++
+ @Override
+ public void setXmlValidation(boolean webXmlValidation){
+-
+ this.webXmlValidation = webXmlValidation;
+-
+ }
+
+- /**
+- * Get the server.xml attribute's xmlValidation.
+- * @return true if validation is enabled.
+- *
+- */
++
+ @Override
+ public boolean getXmlValidation(){
+ return webXmlValidation;
+ }
+
+
+- /**
+- * Get the server.xml attribute's xmlNamespaceAware.
+- * @return true if namespace awarenes is enabled.
+- */
+ @Override
+- public boolean getXmlNamespaceAware(){
+- return webXmlNamespaceAware;
++ public boolean getTldNamespaceAware(){
++ return true;
+ }
+
+
+- /**
+- * Set the namespace aware feature of the XML parser used when
+- * parsing xml instances.
+- * @param webXmlNamespaceAware true to enable namespace awareness
+- */
+ @Override
+- public void setXmlNamespaceAware(boolean webXmlNamespaceAware){
+- this.webXmlNamespaceAware= webXmlNamespaceAware;
++ public void setTldNamespaceAware(boolean tldNamespaceAware){
++ // NO-OP;
+ }
+
+
+- /**
+- * Set the validation feature of the XML parser used when
+- * parsing tlds files.
+- * @param tldValidation true to enable xml instance validation
+- */
++ @Override
++ public void setXmlBlockExternal(boolean xmlBlockExternal) {
++ this.xmlBlockExternal = xmlBlockExternal;
++ }
++
++
++ @Override
++ public boolean getXmlBlockExternal() {
++ return xmlBlockExternal;
++ }
++
++
+ @Override
+ public void setTldValidation(boolean tldValidation){
+-
+ this.tldValidation = tldValidation;
+-
+ }
+
+- /**
+- * Get the server.xml attribute's webXmlValidation.
+- * @return true if validation is enabled.
+- *
+- */
++
+ @Override
+ public boolean getTldValidation(){
+ return tldValidation;
+ }
+
++
+ /**
+ * Sets the process TLDs attribute.
+ *
+@@ -6655,6 +6664,7 @@
+ processTlds = newProcessTlds;
+ }
+
++
+ /**
+ * Returns the processTlds attribute value.
+ */
+@@ -6662,26 +6672,6 @@
+ return processTlds;
+ }
+
+- /**
+- * Get the server.xml <host> attribute's xmlNamespaceAware.
+- * @return true if namespace awarenes is enabled.
+- */
+- @Override
+- public boolean getTldNamespaceAware(){
+- return tldNamespaceAware;
+- }
+-
+-
+- /**
+- * Set the namespace aware feature of the XML parser used when
+- * parsing xml instances.
+- * @param tldNamespaceAware true to enable namespace awareness
+- */
+- @Override
+- public void setTldNamespaceAware(boolean tldNamespaceAware){
+- this.tldNamespaceAware= tldNamespaceAware;
+- }
+-
+
+ /**
+ * Support for "stateManageable" JSR77
+--- java/org/apache/catalina/startup/ContextConfig.java.orig 2014-07-21 17:24:05.574403000 -0400
++++ java/org/apache/catalina/startup/ContextConfig.java 2014-07-21 17:46:59.422037000 -0400
+@@ -95,6 +95,8 @@
+ import org.apache.tomcat.util.bcel.classfile.ElementValue;
+ import org.apache.tomcat.util.bcel.classfile.ElementValuePair;
+ import org.apache.tomcat.util.bcel.classfile.JavaClass;
++import org.apache.tomcat.util.descriptor.DigesterFactory;
++import org.apache.tomcat.util.descriptor.XmlErrorHandler;
+ import org.apache.tomcat.util.digester.Digester;
+ import org.apache.tomcat.util.digester.RuleSet;
+ import org.apache.tomcat.util.res.StringManager;
+@@ -109,7 +111,7 @@
+ *
+ * @author Craig R. McClanahan
+ * @author Jean-Francois Arcand
+- * @version $Id: ContextConfig.java 1488152 2013-05-31 11:07:18Z kkolinko $
++ * @version $Id: ContextConfig.java 1549529 2013-12-09 10:05:56Z markt $
+ */
+ public class ContextConfig implements LifecycleListener {
+
+@@ -514,14 +516,16 @@
+ public void createWebXmlDigester(boolean namespaceAware,
+ boolean validation) {
+
++ boolean blockExternal = context.getXmlBlockExternal();
++
+ 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();
+ }
+
+@@ -710,11 +714,11 @@
+ String pathName = cn.getBaseName();
+
+ boolean unpackWARs = true;
+- if (host instanceof StandardHost &&
+- context instanceof StandardContext) {
+- unpackWARs = ((StandardHost) host).isUnpackWARs() &&
+- ((StandardContext) context).getUnpackWAR() &&
+- (docBase.startsWith(canonicalAppBase.getPath()));
++ if (host instanceof StandardHost) {
++ unpackWARs = ((StandardHost) host).isUnpackWARs();
++ if (unpackWARs && context instanceof StandardContext) {
++ unpackWARs = ((StandardContext) context).getUnpackWAR();
++ }
+ }
+
+ if (docBase.toLowerCase(Locale.ENGLISH).endsWith(".war") && !file.isDirectory() && unpackWARs) {
+@@ -838,14 +842,6 @@
+
+ createWebXmlDigester(context.getXmlNamespaceAware(),
+ context.getXmlValidation());
+-
+- try {
+- fixDocBase();
+- } catch (IOException e) {
+- log.error(sm.getString(
+- "contextConfig.fixDocBase", context.getName()), e);
+- }
+-
+ }
+
+
+@@ -854,8 +850,14 @@
+ */
+ protected synchronized void beforeStart() {
+
+- antiLocking();
++ try {
++ fixDocBase();
++ } catch (IOException e) {
++ log.error(sm.getString(
++ "contextConfig.fixDocBase", context.getName()), e);
++ }
+
++ antiLocking();
+ }
+
+
+@@ -1131,7 +1133,7 @@
+ for (int j = 0; j < roles.length; j++) {
+ if (!"*".equals(roles[j]) &&
+ !context.findSecurityRole(roles[j])) {
+- log.info(sm.getString("contextConfig.role.auth", roles[j]));
++ log.warn(sm.getString("contextConfig.role.auth", roles[j]));
+ context.addSecurityRole(roles[j]);
+ }
+ }
+@@ -1143,14 +1145,14 @@
+ Wrapper wrapper = (Wrapper) wrappers[i];
+ String runAs = wrapper.getRunAs();
+ if ((runAs != null) && !context.findSecurityRole(runAs)) {
+- log.info(sm.getString("contextConfig.role.runas", runAs));
++ log.warn(sm.getString("contextConfig.role.runas", runAs));
+ context.addSecurityRole(runAs);
+ }
+ String names[] = wrapper.findSecurityReferences();
+ for (int j = 0; j < names.length; j++) {
+ String link = wrapper.findSecurityReference(names[j]);
+ if ((link != null) && !context.findSecurityRole(link)) {
+- log.info(sm.getString("contextConfig.role.link", link));
++ log.warn(sm.getString("contextConfig.role.link", link));
+ context.addSecurityRole(link);
+ }
+ }
+@@ -1258,7 +1260,7 @@
+ // Step 1. Identify all the JARs packaged with the application
+ // If the JARs have a web-fragment.xml it will be parsed at this
+ // point.
+- Map fragments = processJarsForWebFragments();
++ Map fragments = processJarsForWebFragments(webXml);
+
+ // Step 2. Order the fragments.
+ Set orderedFragments = null;
+@@ -1546,7 +1548,7 @@
+ URL url = fragment.getURL();
+ Jar jar = null;
+ InputStream is = null;
+- ServletContainerInitializer sci = null;
++ List detectedScis = null;
+ try {
+ if ("jar".equals(url.getProtocol())) {
+ jar = JarFactory.newInstance(url);
+@@ -1559,7 +1561,7 @@
+ }
+ }
+ if (is != null) {
+- sci = getServletContainerInitializer(is);
++ detectedScis = getServletContainerInitializers(is);
+ }
+ } catch (IOException ioe) {
+ log.error(sm.getString(
+@@ -1580,42 +1582,44 @@
+ }
+ }
+
+- if (sci == null) {
++ if (detectedScis == null) {
+ continue;
+ }
+
+- initializerClassMap.put(sci, new HashSet>());
++ for (ServletContainerInitializer sci : detectedScis) {
++ initializerClassMap.put(sci, new HashSet>());
+
+- HandlesTypes ht = null;
+- try {
+- ht = sci.getClass().getAnnotation(HandlesTypes.class);
+- } catch (Exception e) {
+- if (log.isDebugEnabled()) {
+- log.info(sm.getString("contextConfig.sci.debug", url), e);
+- } else {
+- log.info(sm.getString("contextConfig.sci.info", url));
++ HandlesTypes ht = null;
++ try {
++ ht = sci.getClass().getAnnotation(HandlesTypes.class);
++ } catch (Exception e) {
++ if (log.isDebugEnabled()) {
++ log.info(sm.getString("contextConfig.sci.debug", url),
++ e);
++ } else {
++ log.info(sm.getString("contextConfig.sci.info", url));
++ }
+ }
+- }
+- if (ht != null) {
+- Class>[] types = ht.value();
+- if (types != null) {
+- for (Class> type : types) {
+- if (type.isAnnotation()) {
+- handlesTypesAnnotations = true;
+- } else {
+- handlesTypesNonAnnotations = true;
+- }
+- Set scis =
+- typeInitializerMap.get(type);
+- if (scis == null) {
+- scis = new HashSet();
+- typeInitializerMap.put(type, scis);
++ if (ht != null) {
++ Class>[] types = ht.value();
++ if (types != null) {
++ for (Class> type : types) {
++ if (type.isAnnotation()) {
++ handlesTypesAnnotations = true;
++ } else {
++ handlesTypesNonAnnotations = true;
++ }
++ Set scis = typeInitializerMap
++ .get(type);
++ if (scis == null) {
++ scis = new HashSet();
++ typeInitializerMap.put(type, scis);
++ }
++ scis.add(sci);
+ }
+- scis.add(sci);
+ }
+ }
+ }
+-
+ }
+ }
+
+@@ -1627,19 +1631,28 @@
+ * @return The class name
+ * @throws IOException
+ */
+- protected ServletContainerInitializer getServletContainerInitializer(
++ protected List getServletContainerInitializers(
+ InputStream is) throws IOException {
+
+- String className = null;
++ List initializers = new ArrayList();
+
+ if (is != null) {
+ String line = null;
+ try {
+- BufferedReader br =
+- new BufferedReader(new InputStreamReader(is, "UTF-8"));
+- line = br.readLine();
+- if (line != null && line.trim().length() > 0) {
+- className = line.trim();
++ BufferedReader br = new BufferedReader(new InputStreamReader(
++ is, "UTF-8"));
++ while ((line = br.readLine()) != null) {
++ line = line.trim();
++ if (line.length() > 0) {
++ int i = line.indexOf('#');
++ if (i > -1) {
++ if (i == 0) {
++ continue;
++ }
++ line = line.substring(0, i).trim();
++ }
++ initializers.add(getServletContainerInitializer(line));
++ }
+ }
+ } catch (UnsupportedEncodingException e) {
+ // Should never happen with UTF-8
+@@ -1647,11 +1660,16 @@
+ }
+ }
+
++ return initializers;
++ }
++
++ protected ServletContainerInitializer getServletContainerInitializer(
++ String className) throws IOException {
+ ServletContainerInitializer sci = null;
+ try {
+- Class> clazz = Class.forName(className,true,
+- context.getLoader().getClassLoader());
+- sci = (ServletContainerInitializer) clazz.newInstance();
++ Class> clazz = Class.forName(className, true, context.getLoader()
++ .getClassLoader());
++ sci = (ServletContainerInitializer) clazz.newInstance();
+ } catch (ClassNotFoundException e) {
+ log.error(sm.getString("contextConfig.invalidSci", className), e);
+ throw new IOException(e);
+@@ -1923,10 +1941,21 @@
+ *
+ * @return A map of JAR name to processed web fragment (if any)
+ */
+- protected Map processJarsForWebFragments() {
++ protected Map processJarsForWebFragments(WebXml application) {
+
+ JarScanner jarScanner = context.getJarScanner();
+- FragmentJarScannerCallback callback = new FragmentJarScannerCallback();
++
++ boolean parseRequired = true;
++ Set absoluteOrder = application.getAbsoluteOrdering();
++ if (absoluteOrder != null && absoluteOrder.isEmpty() &&
++ !context.getXmlValidation()) {
++ // Skip parsing when there is an empty absolute ordering and
++ // validation is not enabled
++ parseRequired = false;
++ }
++
++ FragmentJarScannerCallback callback =
++ new FragmentJarScannerCallback(parseRequired);
+
+ jarScanner.scan(context.getServletContext(),
+ context.getLoader().getClassLoader(), callback,
+@@ -2282,6 +2311,12 @@
+ } catch (IOException e) {
+ log.debug(sm.getString("contextConfig.invalidSciHandlesTypes",
+ className), e);
++ } finally {
++ try {
++ is.close();
++ } catch (IOException e) {
++ // ignore
++ }
+ }
+ }
+ }
+@@ -2650,7 +2685,12 @@
+ private static final String FRAGMENT_LOCATION =
+ "META-INF/web-fragment.xml";
+ private Map fragments = new HashMap();
++ private final boolean parseRequired;
+
++ public FragmentJarScannerCallback(boolean parseRequired) {
++ this.parseRequired = parseRequired;
++ }
++
+ @Override
+ public void scan(JarURLConnection jarConn) throws IOException {
+
+@@ -2662,15 +2702,18 @@
+
+ try {
+ jar = JarFactory.newInstance(url);
+- is = jar.getInputStream(FRAGMENT_LOCATION);
++ if (parseRequired || context.getXmlValidation()) {
++ is = jar.getInputStream(FRAGMENT_LOCATION);
++ }
+
+ if (is == null) {
+- // If there is no web.xml, normal JAR no impact on
+- // distributable
++ // If there is no web-fragment.xml to process there is no
++ // impact on distributable
+ fragment.setDistributable(true);
+ } else {
+ InputSource source = new InputSource(
+- resourceURL.toString() + "!/" + FRAGMENT_LOCATION);
++ "jar:" + resourceURL.toString() + "!/" +
++ FRAGMENT_LOCATION);
+ source.setByteStream(is);
+ parseWebXml(source, fragment, true);
+ }
+--- java/org/apache/catalina/startup/FailedContext.java.orig 2014-07-21 17:24:05.579400000 -0400
++++ java/org/apache/catalina/startup/FailedContext.java 2014-07-21 17:46:59.429034000 -0400
+@@ -59,6 +59,7 @@
+ import org.apache.catalina.util.CharsetMapper;
+ import org.apache.catalina.util.LifecycleMBeanBase;
+ import org.apache.juli.logging.Log;
++import org.apache.tomcat.InstanceManager;
+ import org.apache.tomcat.JarScanner;
+ import org.apache.tomcat.util.http.mapper.Mapper;
+ import org.apache.tomcat.util.res.StringManager;
+@@ -427,10 +428,15 @@
+ @Override
+ public void setTldValidation(boolean tldValidation) { /* NO-OP */ }
+ @Override
++ public boolean getXmlBlockExternal() { return true; }
++ @Override
++ public void setXmlBlockExternal(boolean xmlBlockExternal) { /* NO-OP */ }
++
++ @Override
+ public boolean getTldValidation() { return false; }
+
+ @Override
+- public boolean getTldNamespaceAware() { return false; }
++ public boolean getTldNamespaceAware() { return true; }
+ @Override
+ public void setTldNamespaceAware(boolean tldNamespaceAware) { /* NO-OP */ }
+
+@@ -685,4 +691,10 @@
+
+ @Override
+ public Map findPreDestroyMethods() { return null; }
++
++ @Override
++ public InstanceManager getInstanceManager() { return null; }
++
++ @Override
++ public void setInstanceManager(InstanceManager instanceManager) { /* NO-OP */ }
+ }
+\ No newline at end of file
+--- java/org/apache/catalina/startup/TldConfig.java.orig 2014-07-21 17:24:05.583404000 -0400
++++ java/org/apache/catalina/startup/TldConfig.java 2014-07-24 12:20:22.130289000 -0400
+@@ -40,6 +40,8 @@
+ import org.apache.tomcat.JarScanner;
+ import org.apache.tomcat.JarScannerCallback;
+ import org.apache.tomcat.util.ExceptionUtils;
++import org.apache.tomcat.util.descriptor.DigesterFactory;
++import org.apache.tomcat.util.descriptor.XmlErrorHandler;
+ import org.apache.tomcat.util.digester.Digester;
+ import org.apache.tomcat.util.res.StringManager;
+ import org.apache.tomcat.util.scan.Jar;
+@@ -83,38 +85,23 @@
+ * Create (if necessary) and return a Digester configured to process the
+ * tld.
+ */
+- private static Digester createTldDigester(boolean namespaceAware,
+- boolean validation) {
+-
+- Digester digester = null;
+- if (!namespaceAware && !validation) {
+- if (tldDigesters[0] == null) {
+- tldDigesters[0] = DigesterFactory.newDigester(validation,
+- namespaceAware, new TldRuleSet());
+- tldDigesters[0].getParser();
+- }
+- digester = tldDigesters[0];
+- } else if (!namespaceAware && validation) {
+- if (tldDigesters[1] == null) {
+- tldDigesters[1] = DigesterFactory.newDigester(validation,
+- namespaceAware, new TldRuleSet());
+- tldDigesters[1].getParser();
+- }
+- digester = tldDigesters[1];
+- } else if (namespaceAware && !validation) {
+- if (tldDigesters[2] == null) {
+- tldDigesters[2] = DigesterFactory.newDigester(validation,
+- namespaceAware, new TldRuleSet());
+- tldDigesters[2].getParser();
+- }
+- digester = tldDigesters[2];
+- } else {
+- if (tldDigesters[3] == null) {
+- tldDigesters[3] = DigesterFactory.newDigester(validation,
+- namespaceAware, new TldRuleSet());
+- tldDigesters[3].getParser();
+- }
+- digester = tldDigesters[3];
++ private static synchronized Digester createTldDigester(boolean validation,
++ boolean blockExternal) {
++
++ Digester digester;
++ int cacheIndex = 0;
++ if (validation) {
++ cacheIndex += 1;
++ }
++ if (blockExternal) {
++ cacheIndex += 2;
++ }
++ digester = tldDigesters[cacheIndex];
++ if (digester == null) {
++ digester = DigesterFactory.newDigester(validation,
++ true, new TldRuleSet(), blockExternal);
++ digester.getParser();
++ tldDigesters[cacheIndex] = digester;
+ }
+ return digester;
+ }
+@@ -155,7 +142,10 @@
+ }
+ StringTokenizer tokenizer = new StringTokenizer(jarNames, ",");
+ while (tokenizer.hasMoreElements()) {
+- noTldJars.add(tokenizer.nextToken());
++ String token = tokenizer.nextToken().trim();
++ if (token.length() > 0) {
++ noTldJars.add(token);
++ }
+ }
+ }
+ }
+@@ -354,10 +344,15 @@
+ try {
+ stream = context.getServletContext().getResourceAsStream(
+ resourcePath);
+- XmlErrorHandler handler = tldScanStream(stream);
+- handler.logFindings(log, resourcePath);
+- taglibUris.add(descriptor.getTaglibURI());
+- webxmlTaglibUris.add(descriptor.getTaglibURI());
++ if (stream != null) {
++ XmlErrorHandler handler = tldScanStream(stream);
++ handler.logFindings(log, resourcePath);
++ taglibUris.add(descriptor.getTaglibURI());
++ webxmlTaglibUris.add(descriptor.getTaglibURI());
++ } else {
++ log.warn(sm.getString("tldConfig.webxmlFailPathDoesNotExist", resourcePath,
++ descriptor.getTaglibURI()));
++ }
+ } catch (IOException ioe) {
+ log.warn(sm.getString("tldConfig.webxmlFail", resourcePath,
+ descriptor.getTaglibURI()), ioe);
+@@ -580,8 +575,8 @@
+
+ private void init() {
+ if (tldDigester == null){
+- tldDigester = createTldDigester(context.getTldNamespaceAware(),
+- context.getTldValidation());
++ tldDigester = createTldDigester(context.getTldValidation(),
++ context.getXmlBlockExternal());
+ }
+ }
+
+--- java/org/apache/jasper/Constants.java.orig 2014-07-21 17:24:05.588400000 -0400
++++ java/org/apache/jasper/Constants.java 2014-07-21 17:46:59.443034000 -0400
+@@ -14,14 +14,12 @@
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-
+ package org.apache.jasper;
+
+ import java.util.Arrays;
+ import java.util.Collections;
+ import java.util.List;
+
+-
+ /**
+ * Some constants and other global data that are used by the compiler and the runtime.
+ *
+@@ -233,4 +231,23 @@
+ */
+ public static final String TLD_JAR_SKIP_PROP=
+ "org.apache.catalina.startup.TldConfig.jarsToSkip";
++
++
++ /**
++ * Name of the ServletContext init-param that determines if the XML parsers
++ * used for *.tld files will be validating or not.
++ *
++ * This must be kept in sync with org.apache.catalina.Globals
++ */
++ 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.
++ *
++ * 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";
+ }
+--- java/org/apache/jasper/JspC.java.orig 2014-07-21 17:24:05.593406000 -0400
++++ java/org/apache/jasper/JspC.java 2014-07-21 17:46:59.450034000 -0400
+@@ -126,6 +126,8 @@
+ protected static final String SWITCH_ENCODING = "-javaEncoding";
+ 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;
+@@ -156,6 +158,8 @@
+ protected URLClassLoader loader = null;
+ 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;
+@@ -363,6 +367,10 @@
+ smapSuppressed = false;
+ } else if (tok.equals(SWITCH_DUMP_SMAP)) {
+ 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 +
+@@ -842,8 +850,20 @@
+ }
+ }
+
+- public void setValidateXml( boolean b ) {
+- org.apache.jasper.xmlparser.ParserUtils.validating=b;
++ public void setValidateTld( boolean b ) {
++ this.validateTld = b;
++ }
++
++ public boolean isValidateTld() {
++ return validateTld;
++ }
++
++ public void setBlockExternal( boolean b ) {
++ this.blockExternal = b;
++ }
++
++ public boolean isBlockExternal() {
++ return blockExternal;
+ }
+
+ public void setListErrors( boolean b ) {
+@@ -1257,8 +1277,6 @@
+
+ /**
+ * Executes the compilation.
+- *
+- * @throws JasperException If an error occurs
+ */
+ @Override
+ public void execute() {
+@@ -1426,6 +1444,13 @@
+ } catch (MalformedURLException me) {
+ System.out.println("**" + me);
+ }
++ if (isValidateTld()) {
++ context.setInitParameter(Constants.XML_VALIDATION_TLD_INIT_PARAM, "true");
++ }
++ if (isBlockExternal()) {
++ context.setInitParameter(Constants.XML_BLOCK_EXTERNAL_INIT_PARAM, "true");
++ }
++
+ rctxt = new JspRuntimeContext(context, this);
+ jspConfig = new JspConfig(context);
+ tagPluginManager = new TagPluginManager(context);
+--- java/org/apache/jasper/compiler/ImplicitTagLibraryInfo.java.orig 2014-07-21 17:24:05.597404000 -0400
++++ java/org/apache/jasper/compiler/ImplicitTagLibraryInfo.java 2014-07-21 17:46:59.457040000 -0400
+@@ -14,7 +14,6 @@
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-
+ package org.apache.jasper.compiler;
+
+ import java.io.InputStream;
+@@ -24,11 +23,13 @@
+ 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;
+ import javax.servlet.jsp.tagext.TagLibraryInfo;
+
++import org.apache.jasper.Constants;
+ import org.apache.jasper.JasperException;
+ import org.apache.jasper.JspCompilationContext;
+ import org.apache.jasper.util.ExceptionUtils;
+@@ -124,7 +125,21 @@
+ pi.addDependant(path, ctxt.getLastModified(path));
+ }
+
+- ParserUtils pu = new ParserUtils();
++ ServletContext servletContext = ctxt.getServletContext();
++ boolean validate = Boolean.parseBoolean(
++ servletContext.getInitParameter(
++ Constants.XML_VALIDATION_TLD_INIT_PARAM));
++ 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);
++ }
++
++ ParserUtils pu = new ParserUtils(validate, blockExternal);
+ TreeNode tld = pu.parseXMLDocument(uri, in);
+
+ if (tld.findAttribute("version") != null) {
+--- java/org/apache/jasper/compiler/JspConfig.java.orig 2014-07-21 17:24:05.605401000 -0400
++++ java/org/apache/jasper/compiler/JspConfig.java 2014-07-21 17:46:59.469055000 -0400
+@@ -22,6 +22,7 @@
+
+ import javax.servlet.ServletContext;
+
++import org.apache.jasper.Constants;
+ import org.apache.jasper.JasperException;
+ import org.apache.jasper.xmlparser.ParserUtils;
+ import org.apache.jasper.xmlparser.TreeNode;
+@@ -77,9 +78,20 @@
+ try {
+ webXml = new WebXml(ctxt);
+
++ boolean validate = Boolean.parseBoolean(
++ ctxt.getInitParameter(Constants.XML_VALIDATION_TLD_INIT_PARAM));
++ 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);
++ }
++
+ TreeNode webApp = null;
+ if (webXml.getInputSource() != null) {
+- ParserUtils pu = new ParserUtils();
++ ParserUtils pu = new ParserUtils(validate, blockExternal);
+ webApp = pu.parseXMLDocument(webXml.getSystemId(),
+ webXml.getInputSource());
+ }
+--- java/org/apache/jasper/compiler/JspDocumentParser.java.orig 2014-07-21 17:24:05.610399000 -0400
++++ java/org/apache/jasper/compiler/JspDocumentParser.java 2014-07-21 17:46:59.476041000 -0400
+@@ -5,9 +5,9 @@
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+- *
++ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+- *
++ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@@ -30,17 +30,20 @@
+ 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.xml.sax.Attributes;
+ import org.xml.sax.InputSource;
+ import org.xml.sax.Locator;
+ import org.xml.sax.SAXException;
+ import org.xml.sax.SAXParseException;
+ import org.xml.sax.XMLReader;
+-import org.xml.sax.ext.LexicalHandler;
++import org.xml.sax.ext.DefaultHandler2;
++import org.xml.sax.ext.EntityResolver2;
+ import org.xml.sax.helpers.AttributesImpl;
+-import org.xml.sax.helpers.DefaultHandler;
+
+ /**
+ * Class implementing a parser for a JSP document, that is, a JSP page in XML
+@@ -51,8 +54,8 @@
+ */
+
+ class JspDocumentParser
+- extends DefaultHandler
+- implements LexicalHandler, TagConstants {
++ extends DefaultHandler2
++ implements TagConstants {
+
+ private static final String LEXICAL_HANDLER_PROPERTY =
+ "http://xml.org/sax/properties/lexical-handler";
+@@ -71,7 +74,7 @@
+ * Outermost (in the nesting hierarchy) node whose body is declared to be
+ * scriptless. If a node's body is declared to be scriptless, all its
+ * nested nodes must be scriptless, too.
+- */
++ */
+ private Node scriptlessBodyNode;
+
+ private Locator locator;
+@@ -92,6 +95,7 @@
+ private boolean inDTD;
+
+ private boolean isValidating;
++ private final EntityResolver2 entityResolver;
+
+ private ErrorDispatcher err;
+ private boolean isTagFile;
+@@ -120,6 +124,20 @@
+ 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);
+ }
+
+ /*
+@@ -162,6 +180,8 @@
+ jspDocParser.isTop = false;
+ }
+
++ jspDocParser.isValidating = false;
++
+ // Parse the input
+ SAXParser saxParser = getSAXParser(false, jspDocParser);
+ InputStream inStream = null;
+@@ -238,11 +258,34 @@
+ }
+ }
+
++
++ @Override
++ public InputSource getExternalSubset(String name, String baseURI)
++ throws SAXException, IOException {
++ return entityResolver.getExternalSubset(name, baseURI);
++ }
++
++
++
++ @Override
++ public InputSource resolveEntity(String publicId, String systemId)
++ throws SAXException, IOException {
++ return entityResolver.resolveEntity(publicId, systemId);
++ }
++
++
++ @Override
++ public InputSource resolveEntity(String name, String publicId, String baseURI, String systemId)
++ throws SAXException, IOException {
++ return entityResolver.resolveEntity(name, publicId, baseURI, systemId);
++ }
++
++
+ /*
+ * Receives notification of the start of an element.
+ *
+ * This method assigns the given tag attributes to one of 3 buckets:
+- *
++ *
+ * - "xmlns" attributes that represent (standard or custom) tag libraries.
+ * - "xmlns" attributes that do not represent tag libraries.
+ * - all remaining attributes.
+@@ -272,11 +315,8 @@
+ return;
+ }
+
+- String currentPrefix = getPrefix(current.getQName());
+-
+ // jsp:text must not have any subelements
+- if (JSP_URI.equals(uri) && TEXT_ACTION.equals(current.getLocalName())
+- && "jsp".equals(currentPrefix)) {
++ if (current instanceof Node.JspText) {
+ throw new SAXParseException(
+ Localizer.getMessage("jsp.error.text.has_subelement"),
+ locator);
+@@ -288,7 +328,7 @@
+ if (attrs != null) {
+ /*
+ * Notice that due to a bug in the underlying SAX parser, the
+- * attributes must be enumerated in descending order.
++ * attributes must be enumerated in descending order.
+ */
+ boolean isTaglib = false;
+ for (int i = attrs.getLength() - 1; i >= 0; i--) {
+@@ -437,7 +477,7 @@
+ * invoke this method with chunks of it. This is a problem when we try
+ * to determine if the text contains only whitespaces, or when we are
+ * looking for an EL expression string. Therefore it is necessary to
+- * buffer and concatenate the chunks and process the concatenated text
++ * buffer and concatenate the chunks and process the concatenated text
+ * later (at beginTag and endTag)
+ *
+ * @param buf The characters
+@@ -670,7 +710,7 @@
+ if (!(child instanceof Node.NamedAttribute)) {
+ throw new SAXParseException(Localizer.getMessage(
+ "jasper.error.emptybodycontent.nonempty",
+- current.qName), locator);
++ current.qName), locator);
+ }
+ }
+ }
+@@ -785,7 +825,7 @@
+ }
+
+ /*
+- * Receives notification of the start of a Namespace mapping.
++ * Receives notification of the start of a Namespace mapping.
+ */
+ @Override
+ public void startPrefixMapping(String prefix, String uri)
+@@ -795,7 +835,7 @@
+ if (directivesOnly && !(JSP_URI.equals(uri))) {
+ return;
+ }
+-
++
+ try {
+ taglibInfo = getTaglibInfo(prefix, uri);
+ } catch (JasperException je) {
+@@ -816,7 +856,7 @@
+ }
+
+ /*
+- * Receives notification of the end of a Namespace mapping.
++ * Receives notification of the end of a Namespace mapping.
+ */
+ @Override
+ public void endPrefixMapping(String prefix) throws SAXException {
+@@ -1425,17 +1465,25 @@
+ throws Exception {
+
+ SAXParserFactory factory = SAXParserFactory.newInstance();
+- factory.setNamespaceAware(true);
+
++ factory.setNamespaceAware(true);
+ // Preserve xmlns attributes
+ factory.setFeature(
+ "http://xml.org/sax/features/namespace-prefixes",
+ true);
++
+ factory.setValidating(validating);
+- //factory.setFeature(
+- // "http://xml.org/sax/features/validation",
+- // validating);
+-
++ if (validating) {
++ // Enable DTD validation
++ factory.setFeature(
++ "http://xml.org/sax/features/validation",
++ true);
++ // Enable schema validation
++ factory.setFeature(
++ "http://apache.org/xml/features/validation/schema",
++ true);
++ }
++
+ // Configure the parser
+ SAXParser saxParser = factory.newSAXParser();
+ XMLReader xmlReader = saxParser.getXMLReader();
+--- java/org/apache/jasper/compiler/TagLibraryInfoImpl.java.orig 2014-07-21 17:24:05.614400000 -0400
++++ java/org/apache/jasper/compiler/TagLibraryInfoImpl.java 2014-07-21 17:46:59.483050000 -0400
+@@ -31,6 +31,7 @@
+ import java.util.Map;
+ import java.util.Vector;
+
++import javax.servlet.ServletContext;
+ import javax.servlet.jsp.tagext.FunctionInfo;
+ import javax.servlet.jsp.tagext.PageData;
+ import javax.servlet.jsp.tagext.TagAttributeInfo;
+@@ -43,6 +44,7 @@
+ import javax.servlet.jsp.tagext.ValidationMessage;
+ import javax.servlet.jsp.tagext.VariableInfo;
+
++import org.apache.jasper.Constants;
+ import org.apache.jasper.JasperException;
+ import org.apache.jasper.JspCompilationContext;
+ import org.apache.jasper.util.ExceptionUtils;
+@@ -212,8 +214,20 @@
+ Vector tagFileVector = new Vector();
+ Hashtable functionTable = new Hashtable();
+
++ ServletContext servletContext = ctxt.getServletContext();
++ boolean validate = Boolean.parseBoolean(servletContext.getInitParameter(
++ Constants.XML_VALIDATION_TLD_INIT_PARAM));
++ 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);
++ }
++
+ // Create an iterator over the child elements of our element
+- ParserUtils pu = new ParserUtils();
++ ParserUtils pu = new ParserUtils(validate, blockExternal);
+ TreeNode tld = pu.parseXMLDocument(uri, in);
+
+ // Check to see if the root element contains a 'version'
+--- java/org/apache/jasper/compiler/TagPluginManager.java.orig 2014-07-21 17:24:05.619399000 -0400
++++ java/org/apache/jasper/compiler/TagPluginManager.java 2014-07-21 17:46:59.492036000 -0400
+@@ -5,9 +5,9 @@
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+- *
++ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+- *
++ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@@ -25,6 +25,7 @@
+
+ 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;
+@@ -45,7 +46,6 @@
+ private boolean initialized = false;
+ private HashMap tagPlugins = null;
+ private ServletContext ctxt;
+- private PageInfo pageInfo;
+
+ public TagPluginManager(ServletContext ctxt) {
+ this.ctxt = ctxt;
+@@ -59,19 +59,9 @@
+ return;
+ }
+
+- this.pageInfo = pageInfo;
+-
+- page.visit(new Node.Visitor() {
+- @Override
+- public void visit(Node.CustomTag n)
+- throws JasperException {
+- invokePlugin(n);
+- visitBody(n);
+- }
+- });
+-
++ page.visit(new NodeVisitor(this, pageInfo));
+ }
+-
++
+ private void init(ErrorDispatcher err) throws JasperException {
+ if (initialized)
+ return;
+@@ -130,8 +120,18 @@
+ private void loadTagPlugins(ErrorDispatcher err, InputStream is)
+ throws JasperException {
+
+- TreeNode root =
+- (new ParserUtils()).parseXMLDocument(TAG_PLUGINS_XML, is);
++ 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);
++ }
++
++ ParserUtils pu = new ParserUtils(false, blockExternal);
++
++ TreeNode root = pu.parseXMLDocument(TAG_PLUGINS_XML, is);
+ if (root == null) {
+ return;
+ }
+@@ -175,12 +175,12 @@
+ }
+
+ /**
+- * Invoke tag plugin for the given custom tag, if a plugin exists for
++ * Invoke tag plugin for the given custom tag, if a plugin exists for
+ * the custom tag's tag handler.
+ *
+ * The given custom tag node will be manipulated by the plugin.
+ */
+- private void invokePlugin(Node.CustomTag n) {
++ private void invokePlugin(Node.CustomTag n, PageInfo pageInfo) {
+ TagPlugin tagPlugin = tagPlugins.get(n.getTagHandlerClass().getName());
+ if (tagPlugin == null) {
+ return;
+@@ -191,8 +191,24 @@
+ tagPlugin.doTag(tagPluginContext);
+ }
+
+- static class TagPluginContextImpl implements TagPluginContext {
+- private Node.CustomTag node;
++ private static class NodeVisitor extends Node.Visitor {
++ private final TagPluginManager manager;
++ private final PageInfo pageInfo;
++
++ public NodeVisitor(TagPluginManager manager, PageInfo pageInfo) {
++ this.manager = manager;
++ this.pageInfo = pageInfo;
++ }
++
++ @Override
++ public void visit(Node.CustomTag n) throws JasperException {
++ manager.invokePlugin(n, pageInfo);
++ visitBody(n);
++ }
++ }
++
++ private static class TagPluginContextImpl implements TagPluginContext {
++ private final Node.CustomTag node;
+ private Node.Nodes curNodes;
+ private PageInfo pageInfo;
+ private HashMap pluginAttributes;
+@@ -291,7 +307,7 @@
+
+ @Override
+ public void generateBody() {
+- // Since we'll generate the body anyway, this is really a nop,
++ // Since we'll generate the body anyway, this is really a nop,
+ // except for the fact that it lets us put the Java sources the
+ // plugins produce in the correct order (w.r.t the body).
+ curNodes = node.getAtETag();
+--- java/org/apache/jasper/compiler/TldLocationsCache.java.orig 2014-07-21 17:24:05.623404000 -0400
++++ java/org/apache/jasper/compiler/TldLocationsCache.java 2014-07-21 17:46:59.500034000 -0400
+@@ -286,9 +286,23 @@
+ return;
+ }
+
++ boolean validate = Boolean.parseBoolean(
++ ctxt.getInitParameter(
++ Constants.XML_VALIDATION_TLD_INIT_PARAM));
++ 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);
++ }
++
+ // Parse the web application deployment descriptor
++ ParserUtils pu = new ParserUtils(validate, blockExternal);
++
+ TreeNode webtld = null;
+- webtld = new ParserUtils().parseXMLDocument(webXml.getSystemId(),
++ webtld = pu.parseXMLDocument(webXml.getSystemId(),
+ webXml.getInputSource());
+
+ // Allow taglib to be an element of the root or jsp-config (JSP2.0)
+@@ -491,8 +505,20 @@
+ // Parse the tag library descriptor at the specified resource path
+ String uri = null;
+
+- TreeNode tld =
+- new ParserUtils().parseXMLDocument(resourcePath, stream);
++ boolean validate = Boolean.parseBoolean(
++ ctxt.getInitParameter(
++ Constants.XML_VALIDATION_TLD_INIT_PARAM));
++ 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);
++ }
++
++ ParserUtils pu = new ParserUtils(validate, blockExternal);
++ TreeNode tld = pu.parseXMLDocument(resourcePath, stream);
+ TreeNode uriNode = tld.findChild("uri");
+ if (uriNode != null) {
+ String body = uriNode.getBody();
+--- java/org/apache/jasper/xmlparser/ParserUtils.java.orig 2014-07-21 17:24:05.628407000 -0400
++++ java/org/apache/jasper/xmlparser/ParserUtils.java 2014-07-21 17:46:59.508034000 -0400
+@@ -14,7 +14,6 @@
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-
+ package org.apache.jasper.xmlparser;
+
+ import java.io.IOException;
+@@ -27,8 +26,9 @@
+ import org.apache.jasper.Constants;
+ import org.apache.jasper.JasperException;
+ import org.apache.jasper.compiler.Localizer;
+-import org.apache.juli.logging.Log;
+-import org.apache.juli.logging.LogFactory;
++import org.apache.tomcat.util.descriptor.DigesterFactory;
++import org.apache.tomcat.util.descriptor.LocalResolver;
++import org.apache.tomcat.util.descriptor.XmlErrorHandler;
+ import org.w3c.dom.Comment;
+ import org.w3c.dom.Document;
+ import org.w3c.dom.NamedNodeMap;
+@@ -48,24 +48,38 @@
+ * use a separate class loader for the parser to be used.
+ *
+ * @author Craig R. McClanahan
+- * @version $Id: ParserUtils.java 1301227 2012-03-15 21:59:06Z markt $
++ * @version $Id: ParserUtils.java 1549529 2013-12-09 10:05:56Z markt $
+ */
+-
+ public class ParserUtils {
+
+ /**
+ * An error handler for use when parsing XML documents.
+ */
+- static ErrorHandler errorHandler = new MyErrorHandler();
++ static ErrorHandler errorHandler = new XmlErrorHandler();
+
+ /**
+ * An entity resolver for use when parsing XML documents.
+ */
+- static EntityResolver entityResolver = new MyEntityResolver();
+-
+- // Turn off for JSP 2.0 until switch over to using xschema.
+- public static boolean validating = false;
+-
++ static EntityResolver entityResolver;
++
++ private final EntityResolver entityResolverInstance;
++
++ private final boolean validating;
++
++ public ParserUtils(boolean validating) {
++ this(validating, Constants.IS_SECURITY_ENABLED);
++ }
++
++ public ParserUtils(boolean validating, boolean blockExternal) {
++ this.validating = validating;
++ if (entityResolver == null) {
++ this.entityResolverInstance = new LocalResolver(
++ DigesterFactory.SERVLET_API_PUBLIC_IDS,
++ DigesterFactory.SERVLET_API_SYSTEM_IDS, blockExternal);
++ } else {
++ this.entityResolverInstance = entityResolver;
++ }
++ }
+
+ // --------------------------------------------------------- Public Methods
+
+@@ -91,7 +105,7 @@
+ factory.setNamespaceAware(true);
+ factory.setValidating(validating);
+ DocumentBuilder builder = factory.newDocumentBuilder();
+- builder.setEntityResolver(entityResolver);
++ builder.setEntityResolver(entityResolverInstance);
+ builder.setErrorHandler(errorHandler);
+ document = builder.parse(is);
+ } catch (ParserConfigurationException ex) {
+@@ -196,56 +210,3 @@
+ return (treeNode);
+ }
+ }
+-
+-
+-// ------------------------------------------------------------ Private Classes
+-
+-class MyEntityResolver implements EntityResolver {
+-
+- @Override
+- public InputSource resolveEntity(String publicId, String systemId)
+- throws SAXException {
+- for (int i = 0; i < Constants.CACHED_DTD_PUBLIC_IDS.size(); i++) {
+- String cachedDtdPublicId = Constants.CACHED_DTD_PUBLIC_IDS.get(i);
+- if (cachedDtdPublicId.equals(publicId)) {
+- String resourcePath =
+- Constants.CACHED_DTD_RESOURCE_PATHS.get(i);
+- InputStream input = this.getClass().getResourceAsStream(
+- resourcePath);
+- if (input == null) {
+- throw new SAXException(Localizer.getMessage(
+- "jsp.error.internal.filenotfound", resourcePath));
+- }
+- InputSource isrc = new InputSource(input);
+- return isrc;
+- }
+- }
+- Log log = LogFactory.getLog(MyEntityResolver.class);
+- if (log.isDebugEnabled())
+- log.debug("Resolve entity failed" + publicId + " " + systemId);
+- log.error(Localizer.getMessage("jsp.error.parse.xml.invalidPublicId",
+- publicId));
+- return null;
+- }
+-}
+-
+-class MyErrorHandler implements ErrorHandler {
+-
+- @Override
+- public void warning(SAXParseException ex) throws SAXException {
+- Log log = LogFactory.getLog(MyErrorHandler.class);
+- if (log.isDebugEnabled())
+- log.debug("ParserUtils: warning ", ex);
+- // We ignore warnings
+- }
+-
+- @Override
+- public void error(SAXParseException ex) throws SAXException {
+- throw ex;
+- }
+-
+- @Override
+- public void fatalError(SAXParseException ex) throws SAXException {
+- throw ex;
+- }
+-}
+--- webapps/docs/changelog.xml.orig 2014-07-22 17:42:18.576034000 -0400
++++ webapps/docs/changelog.xml 2014-07-22 18:48:34.775453000 -0400
+@@ -58,6 +58,12 @@
+
+
+
++
++ 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 when a security manager is used. The block is implemented via
++ a custom resolver to enable the logging of any blocked entities. (markt)
++
+
+ CVE-2014-0099, Fix overflow when parsing long values from
+ byte array. (markt) Patch applied by Red Hat Jun 16 2014
+--- webapps/docs/config/context.xml.orig 2014-07-21 17:24:05.643402000 -0400
++++ webapps/docs/config/context.xml 2014-07-21 17:46:59.530037000 -0400
+@@ -448,6 +448,14 @@
+ useful for portlet specification implementations) set this attribute to
+ /
in the global CATALINA_BASE/conf/context.xml
+ file.
++ Note: Once one web application using
++ sessionCookiePath="/"
obtains a session, all
++ subsequent sessions for any other web application in the same host also
++ configured with sessionCookiePath="/"
will always
++ use the same session ID. This holds even if the session is invalidated
++ and a new one created. This makes session fixation protection more
++ difficult and requires custom, Tomcat specific code to change the
++ session ID shared by the multiple applications.
+
+
+
+@@ -493,18 +501,6 @@
+ of the flag is false
.
+
+
+-
+- If the value of this flag is true
, the TLD files
+- XML validation will be namespace-aware. If you turn this flag on,
+- you should probably also turn tldValidation
on. If the
+- org.apache.catalina.STRICT_SERVLET_COMPLIANCE
+- system property is set to
+- true
, the default value of this attribute will be
+- true
, else the default value will be false
.
+- Setting this attribute to true
will incur a performance
+- penalty.
+-
+-
+
+ If the value of this flag is true
, the TLD files
+ will be XML validated on context startup. If the
+@@ -528,11 +524,26 @@
+ Context. If not specified, a standard default value will be used.
+
+
++
++ If the value of this flag is true
, the parsing of
++ web.xml
, web-fragment.xml
, *.tld
,
++ *.jspx
, *.tagx
and tagPlugins.xml
++ files for this web application will not permit external entities to be
++ loaded. If a SecurityManager
is configured then the default
++ value of this attribute will be true
, else the default
++ value will be false
.
++
++
+
+- If the value of this flag is true
, the validation of
+- XML files will be namespace-aware. If you turn this flag on,
+- you should probably also turn xmlValidation
on. If
+- the org.apache.catalina.STRICT_SERVLET_COMPLIANCE
++
If the value of this flag is true
, the parsing of
++ web.xml
and web-fragment.xml
files for this
++ web application will be namespace-aware. Note that *.tld
,
++ *.jspx
and *.tagx
files are always parsed
++ using a namespace-aware parser and that the tagPlugins.xml
++ file (if any) is never parsed using a namespace-aware parser. Note also
++ that if you turn this flag on, you should probably also turn
++ xmlValidation
on. If the
++ org.apache.catalina.STRICT_SERVLET_COMPLIANCE
+ system property is set to
+ true
, the default value of this attribute will be
+ true
, else the default value will be false
.
+@@ -541,8 +552,9 @@
+
+
+
+- If the value of this flag is true
, the XML files
+- will be validated on context startup. If the
++
If the value of this flag is true
, the parsing of
++ web.xml
and web-fragment.xml
files for this
++ web application will use a validating parser. If the
+ org.apache.catalina.STRICT_SERVLET_COMPLIANCE
+ system property is set to
+ true
, the default value of this attribute will be
+@@ -706,7 +718,10 @@
+ is likely to result in instability. As such, enabling this should be
+ viewed as an option of last resort in a development environment and is
+ not recommended in a production environment. If not specified, the
+- default value of false
will be used.
++ default value of false
will be used. If this feature is
++ enabled, web applications may take up to two seconds longer to stop as
++ executor threads are given up to two seconds to stop gracefully before
++ Thread.stop()
is called on any remaining threads.
+
+
+
+@@ -717,6 +732,22 @@
+ not specified, the default value of false
will be used.
+
+
++
++ Set to true
if you want a context XML descriptor
++ embedded inside the application (located at
++ /META-INF/context.xml
) to be copied to the owning
++ Host's xmlBase
when the application
++ is deployed. On subsequent starts, the copied context XML descriptor
++ will be used in preference to any context XML descriptor embedded inside
++ the application even if the descriptor embedded inside the application
++ is more recent. The flag's value defaults to false
. Note if
++ the deployXML attribute of the owning
++ Host is false
or if the
++ copyXML attribute of the owning
++ Host is true
, this attribute will
++ have no effect.
++
++
+
+ If true
, any attempt by an application to modify the
+ provided JNDI context with a call to bind(), unbind(),
+--- webapps/docs/security-howto.xml.orig 2014-07-21 17:24:05.649404000 -0400
++++ webapps/docs/security-howto.xml 2014-07-21 17:46:59.538035000 -0400
+@@ -72,10 +72,74 @@
+
+
+
+- Tomcat ships with a number of web applications by default.
+- Vulnerabilities have been discovered in these applications in the past.
+- Applications that are not required should be removed so the system will not
+- be at risk if another vulnerability is discovered.
++
++
++ Tomcat ships with a number of web applications that are enabled by
++ default. Vulnerabilities have been discovered in these applications in the
++ past. Applications that are not required should be removed so the system
++ will not be at risk if another vulnerability is discovered.
++
++
++
++ The ROOT web application presents a very low security risk but it does
++ include the version of Tomcat that is being used. The ROOT web application
++ should normally be removed from a publicly accessible Tomcat instance, not
++ for security reasons, but so that a more appropriate default page is shown
++ to users.
++
++
++
++ The documentation web application presents a very low security risk but
++ it does identify the version of Tomcat that is being used. It should
++ normally be removed from a publicly accessible Tomcat instance.
++
++
++
++ The examples web application should always be removed from any security
++ sensitive installation. While the examples web application does not
++ contain any known vulnerabilities, it is known to contain features
++ (particularly the cookie examples that display the contents of all
++ received and allow new cookies to be set) that may be used by an attacker
++ in conjunction with a vulnerability in another application deployed on the
++ Tomcat instance to obtain additional information that would otherwise be
++ unavailable.
++
++
++
++ The Manager application allows the remote deployment of web
++ applications and is frequently targeted by attackers due to the widespread
++ use of weak passwords and publicly accessible Tomcat instances with the
++ Manager application enabled. The Manager application is not accessible by
++ default as no users are configured with the necessary access. If the
++ Manager application is enabled then guidance in the section
++ Securing Management Applications section should be
++ followed.
++
++
++
++ The Host Manager application allows the creation and management of
++ virtual hosts - including the enabling of the Manager application for a
++ virtual host. The Host Manager application is not accessible by default
++ as no users are configured with the necessary access. If the Host Manager
++ application is enabled then guidance in the section Securing
++ Management Applications section should be followed.
++
++
++
++ When deploying a web application that provides management functions for
++ the Tomcat instance, the following guidelines should be followed:
++
++ Ensure that any users permitted to access the management application
++ have strong passwords.
++ Do not remove the use of the LockOutRealm
++ which prevents brute force attacks against user passwords.
++ Uncomment the RemoteAddrValve
++ in /META-INF/context.xml
which limits access to
++ localhost. If remote access is required, limit it to specific IP
++ addresses using this valve.
++
++
+
+
+
+@@ -109,6 +173,16 @@
+ manager should be introduced at the start of the development cycle as it can
+ be time-consuming to track down and fix issues caused by enabling a security
+ manager for a mature application.
++
++ Enabling the security manager changes the defaults for the following
++ settings:
++
++ - The default value for the deployXML attribute of the
++ Host element is changed to
false
.
++ - The default value for the xmlBlockExternal attribute
++ of the Context element is changed to
true
.
++
++
+
+
+
+@@ -229,9 +303,11 @@
+
+
+ In a hosted environment where web applications may not be trusted, set
+- the deployXML attribute to false
to ignore any
+- context.xml packaged with the web application that may try to assign
+- increased privileges to the web application.
++ the deployXML attribute to false
to ignore
++ any context.xml packaged with the web application that may try to assign
++ increased privileges to the web application. Note that if the security
++ manager is enabled that the deployXML attribute will
++ default to false
.
+
+
+
+--- java/org/apache/catalina/core/DefaultInstanceManager.java.orig 2014-07-22 16:56:51.460868000 -0400
++++ java/org/apache/catalina/core/DefaultInstanceManager.java 2014-07-22 16:59:03.496296000 -0400
+@@ -55,7 +55,7 @@
+ import org.apache.tomcat.util.res.StringManager;
+
+ /**
+- * @version $Id: DefaultInstanceManager.java 1437338 2013-01-23 11:02:35Z markt $
++ * @version $Id: DefaultInstanceManager.java 1514663 2013-08-16 11:51:28Z markt $
+ */
+ public class DefaultInstanceManager implements InstanceManager {
+
+@@ -133,6 +133,11 @@
+ }
+
+ @Override
++ public Object newInstance(Class> clazz) throws IllegalAccessException, InvocationTargetException, NamingException, InstantiationException {
++ return newInstance(clazz.newInstance(), clazz);
++ }
++
++ @Override
+ public Object newInstance(String className) throws IllegalAccessException, InvocationTargetException, NamingException, InstantiationException, ClassNotFoundException {
+ Class> clazz = loadClassMaybePrivileged(className, classLoader);
+ return newInstance(clazz.newInstance(), clazz);
+--- java/org/apache/tomcat/InstanceManager.java.orig 2014-07-22 16:57:21.347937000 -0400
++++ java/org/apache/tomcat/InstanceManager.java 2014-07-22 17:00:47.400650000 -0400
+@@ -21,10 +21,14 @@
+ import javax.naming.NamingException;
+
+ /**
+- * @version $Id: InstanceManager.java 1200164 2011-11-10 05:46:02Z kkolinko $
++ * @version $Id: InstanceManager.java 1514663 2013-08-16 11:51:28Z markt $
+ */
+ public interface InstanceManager {
+
++ public Object newInstance(Class> clazz)
++ throws IllegalAccessException, InvocationTargetException, NamingException,
++ InstantiationException;
++
+ public Object newInstance(String className)
+ throws IllegalAccessException, InvocationTargetException, NamingException,
+ InstantiationException, ClassNotFoundException;
+--- java/org/apache/jasper/EmbeddedServletOptions.java.orig 2014-07-22 17:08:09.862127000 -0400
++++ java/org/apache/jasper/EmbeddedServletOptions.java 2014-07-22 17:08:43.749244000 -0400
+@@ -30,7 +30,6 @@
+ import org.apache.jasper.compiler.Localizer;
+ import org.apache.jasper.compiler.TagPluginManager;
+ import org.apache.jasper.compiler.TldLocationsCache;
+-import org.apache.jasper.xmlparser.ParserUtils;
+ import org.apache.juli.logging.Log;
+ import org.apache.juli.logging.LogFactory;
+
+@@ -456,11 +455,7 @@
+ String v=config.getInitParameter( k );
+ setProperty( k, v);
+ }
+-
+- // quick hack
+- String validating=config.getInitParameter( "validating");
+- if( "false".equals( validating )) ParserUtils.validating=false;
+-
++
+ String keepgen = config.getInitParameter("keepgenerated");
+ if (keepgen != null) {
+ if (keepgen.equalsIgnoreCase("true")) {
+--- java/org/apache/tomcat/util/descriptor/DigesterFactory.java.orig 2014-07-21 17:24:05.654400000 -0400
++++ java/org/apache/tomcat/util/descriptor/DigesterFactory.java 2014-07-21 17:46:59.547034000 -0400
+@@ -0,0 +1,135 @@
++/*
++ * Licensed to the Apache Software Foundation (ASF) under one or more
++ * contributor license agreements. See the NOTICE file distributed with
++ * this work for additional information regarding copyright ownership.
++ * The ASF licenses this file to You under the Apache License, Version 2.0
++ * (the "License"); you may not use this file except in compliance with
++ * the License. You may obtain a copy of the License at
++ *
++ * http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS,
++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++ * See the License for the specific language governing permissions and
++ * limitations under the License.
++ */
++package org.apache.tomcat.util.descriptor;
++
++import java.net.URL;
++import java.util.Collections;
++import java.util.HashMap;
++import java.util.Map;
++
++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
++ * details.
++ */
++public class DigesterFactory {
++
++ /**
++ * Mapping of well-known public IDs used by the Servlet API to the matching
++ * local resource.
++ */
++ public static final Map SERVLET_API_PUBLIC_IDS;
++
++ /**
++ * Mapping of well-known system IDs used by the Servlet API to the matching
++ * local resource.
++ */
++ public static final Map SERVLET_API_SYSTEM_IDS;
++
++ static {
++ Map publicIds = new HashMap();
++ Map systemIds = new HashMap();
++
++ // W3C
++ publicIds.put(XmlIdentifiers.XSD_10_PUBLIC, idFor("XMLSchema.dtd"));
++ publicIds.put(XmlIdentifiers.DATATYPES_PUBLIC, idFor("datatypes.dtd"));
++ systemIds.put(XmlIdentifiers.XML_2001_XSD, idFor("xml.xsd"));
++
++ // from J2EE 1.2
++ publicIds.put(XmlIdentifiers.WEB_22_PUBLIC, idFor("web-app_2_2.dtd"));
++ publicIds.put(XmlIdentifiers.TLD_11_PUBLIC, idFor("web-jsptaglibrary_1_1.dtd"));
++
++ // from J2EE 1.3
++ publicIds.put(XmlIdentifiers.WEB_23_PUBLIC, idFor("web-app_2_3.dtd"));
++ publicIds.put(XmlIdentifiers.TLD_12_PUBLIC, idFor("web-jsptaglibrary_1_2.dtd"));
++
++ // from J2EE 1.4
++ systemIds.put("http://www.ibm.com/webservices/xsd/j2ee_web_services_1_1.xsd",
++ idFor("j2ee_web_services_1_1.xsd"));
++ systemIds.put("http://www.ibm.com/webservices/xsd/j2ee_web_services_client_1_1.xsd",
++ idFor("j2ee_web_services_client_1_1.xsd"));
++ systemIds.put(XmlIdentifiers.WEB_24_XSD, idFor("web-app_2_4.xsd"));
++ systemIds.put(XmlIdentifiers.TLD_20_XSD, idFor("web-jsptaglibrary_2_0.xsd"));
++ addSelf(systemIds, "j2ee_1_4.xsd");
++ addSelf(systemIds, "jsp_2_0.xsd");
++
++ // from JavaEE 5
++ systemIds.put(XmlIdentifiers.WEB_25_XSD, idFor("web-app_2_5.xsd"));
++ systemIds.put(XmlIdentifiers.TLD_21_XSD, idFor("web-jsptaglibrary_2_1.xsd"));
++ addSelf(systemIds, "javaee_5.xsd");
++ addSelf(systemIds, "jsp_2_1.xsd");
++ addSelf(systemIds, "javaee_web_services_1_2.xsd");
++ addSelf(systemIds, "javaee_web_services_client_1_2.xsd");
++
++ // from JavaEE 6
++ systemIds.put(XmlIdentifiers.WEB_30_XSD, idFor("web-app_3_0.xsd"));
++ systemIds.put(XmlIdentifiers.WEB_FRAGMENT_30_XSD, idFor("web-fragment_3_0.xsd"));
++ addSelf(systemIds, "web-common_3_0.xsd");
++ addSelf(systemIds, "javaee_6.xsd");
++ addSelf(systemIds, "jsp_2_2.xsd");
++ addSelf(systemIds, "javaee_web_services_1_3.xsd");
++ addSelf(systemIds, "javaee_web_services_client_1_3.xsd");
++
++ SERVLET_API_PUBLIC_IDS = Collections.unmodifiableMap(publicIds);
++ SERVLET_API_SYSTEM_IDS = Collections.unmodifiableMap(systemIds);
++ }
++
++ private static void addSelf(Map ids, String id) {
++ String systemId = idFor(id);
++ ids.put(systemId, systemId);
++ ids.put(id, systemId);
++ }
++
++ private static String idFor(String url) {
++ URL id = ServletContext.class.getResource("resources/" + url);
++ if (id == null) {
++ id = ServletContext.class.getResource("jsp/resources/" + url);
++ }
++ return id.toExternalForm();
++ }
++
++
++ /**
++ * Create a Digester
parser.
++ * @param xmlValidation turn on/off xml validation
++ * @param xmlNamespaceAware turn on/off namespace validation
++ * @param rule an instance of RuleSet
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,
++ boolean blockExternal) {
++ Digester digester = new Digester();
++ digester.setNamespaceAware(xmlNamespaceAware);
++ digester.setValidating(xmlValidation);
++ digester.setUseContextClassLoader(true);
++ EntityResolver2 resolver = new LocalResolver(SERVLET_API_PUBLIC_IDS,
++ SERVLET_API_SYSTEM_IDS, blockExternal);
++ digester.setEntityResolver(resolver);
++ if (rule != null) {
++ digester.addRuleSet(rule);
++ }
++
++ return digester;
++ }
++}
+--- java/org/apache/tomcat/util/descriptor/LocalResolver.java.orig 2014-07-21 17:24:05.658412000 -0400
++++ java/org/apache/tomcat/util/descriptor/LocalResolver.java 2014-07-21 17:46:59.555034000 -0400
+@@ -0,0 +1,146 @@
++/*
++ * Licensed to the Apache Software Foundation (ASF) under one or more
++ * contributor license agreements. See the NOTICE file distributed with
++ * this work for additional information regarding copyright ownership.
++ * The ASF licenses this file to You under the Apache License, Version 2.0
++ * (the "License"); you may not use this file except in compliance with
++ * the License. You may obtain a copy of the License at
++ *
++ * http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS,
++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++ * See the License for the specific language governing permissions and
++ * limitations under the License.
++ */
++package org.apache.tomcat.util.descriptor;
++
++import java.io.FileNotFoundException;
++import java.io.IOException;
++import java.net.MalformedURLException;
++import java.net.URI;
++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;
++
++/**
++ * A resolver for locally cached XML resources.
++ */
++public class LocalResolver implements EntityResolver2 {
++
++ private static final StringManager sm =
++ StringManager.getManager(Constants.PACKAGE_NAME);
++
++ private final Map publicIds;
++ private final Map 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 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 publicIds,
++ Map systemIds, boolean blockExternal) {
++ this.publicIds = publicIds;
++ this.systemIds = systemIds;
++ this.blockExternal = blockExternal;
++ }
++
++
++ @Override
++ public InputSource resolveEntity(String publicId, String systemId)
++ throws SAXException, IOException {
++ return resolveEntity(null, publicId, null, systemId);
++ }
++
++
++ @Override
++ public InputSource resolveEntity(String name, String publicId,
++ String base, String systemId) throws SAXException, IOException {
++
++ // First try resolving using the publicId
++ String resolved = publicIds.get(publicId);
++ if (resolved != null) {
++ InputSource is = new InputSource(resolved);
++ is.setPublicId(publicId);
++ return is;
++ }
++
++ // If there is no systemId, can't try anything else
++ if (systemId == null) {
++ throw new FileNotFoundException(sm.getString("localResolver.unresolvedEntity",
++ name, publicId, systemId, base));
++ }
++
++ // Try resolving with the supplied systemId
++ resolved = systemIds.get(systemId);
++ if (resolved != null) {
++ InputSource is = new InputSource(resolved);
++ is.setPublicId(publicId);
++ return is;
++ }
++
++ // Resolve the supplied systemId against the base
++ URI systemUri;
++ try {
++ 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();
++ }
++ systemUri = systemUri.normalize();
++ } catch (URISyntaxException e) {
++ // 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;
++ }
++}
+--- java/org/apache/tomcat/util/descriptor/LocalStrings.properties.orig 2014-07-21 17:24:05.663406000 -0400
++++ java/org/apache/tomcat/util/descriptor/LocalStrings.properties 2014-07-21 17:46:59.562036000 -0400
+@@ -0,0 +1,19 @@
++# Licensed to the Apache Software Foundation (ASF) under one or more
++# contributor license agreements. See the NOTICE file distributed with
++# this work for additional information regarding copyright ownership.
++# The ASF licenses this file to You under the Apache License, Version 2.0
++# (the "License"); you may not use this file except in compliance with
++# the License. You may obtain a copy of the License at
++#
++# http://www.apache.org/licenses/LICENSE-2.0
++#
++# Unless required by applicable law or agreed to in writing, software
++# distributed under the License is distributed on an "AS IS" BASIS,
++# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++# 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}].
+--- java/org/apache/tomcat/util/descriptor/Constants.java.orig 2014-07-21 17:24:05.668398000 -0400
++++ java/org/apache/tomcat/util/descriptor/Constants.java 2014-07-21 17:46:59.569034000 -0400
+@@ -0,0 +1,24 @@
++/*
++ * Licensed to the Apache Software Foundation (ASF) under one or more
++ * contributor license agreements. See the NOTICE file distributed with
++ * this work for additional information regarding copyright ownership.
++ * The ASF licenses this file to You under the Apache License, Version 2.0
++ * (the "License"); you may not use this file except in compliance with
++ * the License. You may obtain a copy of the License at
++ *
++ * http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS,
++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++ * See the License for the specific language governing permissions and
++ * limitations under the License.
++ */
++package org.apache.tomcat.util.descriptor;
++
++public class Constants {
++
++ public static final String PACKAGE_NAME =
++ Constants.class.getPackage().getName();
++
++}
+--- java/org/apache/tomcat/util/descriptor/LocalStrings_es.properties.orig 2014-07-21 17:24:05.672404000 -0400
++++ java/org/apache/tomcat/util/descriptor/LocalStrings_es.properties 2014-07-21 17:46:59.574035000 -0400
+@@ -0,0 +1,17 @@
++# Licensed to the Apache Software Foundation (ASF) under one or more
++# contributor license agreements. See the NOTICE file distributed with
++# this work for additional information regarding copyright ownership.
++# The ASF licenses this file to You under the Apache License, Version 2.0
++# (the "License"); you may not use this file except in compliance with
++# the License. You may obtain a copy of the License at
++#
++# http://www.apache.org/licenses/LICENSE-2.0
++#
++# Unless required by applicable law or agreed to in writing, software
++# distributed under the License is distributed on an "AS IS" BASIS,
++# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++# See the License for the specific language governing permissions and
++# limitations under the License.
++
++xmlErrorHandler.error = Error no fatal [{0}] reportado por el proceso [{1}].
++xmlErrorHandler.warning = Aviso [{0}] reportado por el proceso [{1}].
+--- java/org/apache/tomcat/util/descriptor/XmlIdentifiers.java.orig 2014-07-21 17:24:05.677400000 -0400
++++ java/org/apache/tomcat/util/descriptor/XmlIdentifiers.java 2014-07-21 17:46:59.580036000 -0400
+@@ -0,0 +1,77 @@
++/*
++ * Licensed to the Apache Software Foundation (ASF) under one or more
++ * contributor license agreements. See the NOTICE file distributed with
++ * this work for additional information regarding copyright ownership.
++ * The ASF licenses this file to You under the Apache License, Version 2.0
++ * (the "License"); you may not use this file except in compliance with
++ * the License. You may obtain a copy of the License at
++ *
++ * http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS,
++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++ * See the License for the specific language governing permissions and
++ * limitations under the License.
++ */
++package org.apache.tomcat.util.descriptor;
++
++/**
++ * Defines constants for well-known Public and System identifiers documented by
++ * the Servlet and JSP specifications.
++ */
++public final class XmlIdentifiers {
++
++ // from W3C
++ public static final String XML_2001_XSD = "http://www.w3.org/2001/xml.xsd";
++ public static final String DATATYPES_PUBLIC = "datatypes";
++ public static final String XSD_10_PUBLIC =
++ "-//W3C//DTD XMLSCHEMA 200102//EN";
++
++ // from J2EE 1.2
++ public static final String WEB_22_PUBLIC =
++ "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN";
++ public static final String WEB_22_SYSTEM =
++ "http://java.sun.com/dtd/web-app_2_2.dtd";
++ public static final String TLD_11_PUBLIC =
++ "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN";
++ public static final String TLD_11_SYSTEM =
++ "http://java.sun.com/dtd/web-jsptaglibrary_1_1.dtd";
++
++ // from J2EE 1.3
++ public static final String WEB_23_PUBLIC =
++ "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN";
++ public static final String WEB_23_SYSTEM =
++ "http://java.sun.com/dtd/web-app_2_3.dtd";
++ public static final String TLD_12_PUBLIC =
++ "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN";
++ public static final String TLD_12_SYSTEM =
++ "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd";
++
++ // from J2EE 1.4
++ public static final String WEB_24_XSD =
++ "http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd";
++ public static final String TLD_20_XSD =
++ "http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd";
++ public static final String WEBSERVICES_11_XSD =
++ "http://www.ibm.com/webservices/xsd/j2ee_web_services_1_1.xsd";
++
++ // from JavaEE 5
++ public static final String WEB_25_XSD =
++ "http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd";
++ public static final String TLD_21_XSD =
++ "http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd";
++ public static final String WEBSERVICES_12_XSD =
++ "http://java.sun.com/xml/ns/javaee/javaee_web_services_1_2.xsd";
++
++ // from JavaEE 6
++ public static final String WEB_30_XSD =
++ "http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd";
++ public static final String WEB_FRAGMENT_30_XSD =
++ "http://java.sun.com/xml/ns/javaee/web-fragment_3_0.xsd";
++ public static final String WEBSERVICES_13_XSD =
++ "http://java.sun.com/xml/ns/javaee/javaee_web_services_1_3.xsd";
++
++ private XmlIdentifiers() {
++ }
++}
+\ No newline at end of file
+--- java/org/apache/tomcat/util/descriptor/XmlErrorHandler.java.orig 2014-07-21 17:24:05.683398000 -0400
++++ java/org/apache/tomcat/util/descriptor/XmlErrorHandler.java 2014-07-21 17:46:59.586038000 -0400
+@@ -0,0 +1,75 @@
++/*
++ * Licensed to the Apache Software Foundation (ASF) under one or more
++ * contributor license agreements. See the NOTICE file distributed with
++ * this work for additional information regarding copyright ownership.
++ * The ASF licenses this file to You under the Apache License, Version 2.0
++ * (the "License"); you may not use this file except in compliance with
++ * the License. You may obtain a copy of the License at
++ *
++ * http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS,
++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++ * See the License for the specific language governing permissions and
++ * limitations under the License.
++ */
++package org.apache.tomcat.util.descriptor;
++
++import java.util.HashSet;
++import java.util.Set;
++
++import org.apache.juli.logging.Log;
++import org.apache.tomcat.util.res.StringManager;
++import org.xml.sax.ErrorHandler;
++import org.xml.sax.SAXException;
++import org.xml.sax.SAXParseException;
++
++public class XmlErrorHandler implements ErrorHandler {
++
++ private static final StringManager sm =
++ StringManager.getManager(Constants.PACKAGE_NAME);
++
++ private final Set errors = new HashSet();
++
++ private final Set warnings = new HashSet();
++
++ @Override
++ public void error(SAXParseException exception) throws SAXException {
++ // Collect non-fatal errors
++ errors.add(exception);
++ }
++
++ @Override
++ public void fatalError(SAXParseException exception) throws SAXException {
++ // Re-throw fatal errors
++ throw exception;
++ }
++
++ @Override
++ public void warning(SAXParseException exception) throws SAXException {
++ // Collect warnings
++ warnings.add(exception);
++ }
++
++ public Set getErrors() {
++ // Internal use only - don't worry about immutability
++ return errors;
++ }
++
++ public Set getWarnings() {
++ // Internal use only - don't worry about immutability
++ return warnings;
++ }
++
++ public void logFindings(Log log, String source) {
++ for (SAXParseException e : getWarnings()) {
++ log.warn(sm.getString(
++ "xmlErrorHandler.warning", e.getMessage(), source));
++ }
++ for (SAXParseException e : getErrors()) {
++ log.warn(sm.getString(
++ "xmlErrorHandler.error", e.getMessage(), source));
++ }
++ }
++}
diff --git a/SOURCES/tomcat-7.0.42-CVE-2014-0119.patch b/SOURCES/tomcat-7.0.42-CVE-2014-0119.patch
new file mode 100644
index 0000000..84e93a2
--- /dev/null
+++ b/SOURCES/tomcat-7.0.42-CVE-2014-0119.patch
@@ -0,0 +1,678 @@
+--- java/org/apache/catalina/security/SecurityClassLoad.java.orig 2014-07-24 18:29:38.830023000 -0400
++++ java/org/apache/catalina/security/SecurityClassLoad.java 2014-07-24 18:31:18.655356000 -0400
+@@ -25,9 +25,7 @@
+ *
+ * @author Glenn L. Nielsen
+ * @author Jean-Francois Arcand
+- * @version $Id: SecurityClassLoad.java 1410548 2012-11-16 19:38:51Z markt $
+ */
+-
+ public final class SecurityClassLoad {
+
+ public static void securityClassLoad(ClassLoader loader)
+@@ -41,6 +39,7 @@
+ loadCoyotePackage(loader);
+ loadLoaderPackage(loader);
+ loadRealmPackage(loader);
++ loadServletsPackage(loader);
+ loadSessionPackage(loader);
+ loadUtilPackage(loader);
+ loadValvesPackage(loader);
+@@ -76,12 +75,6 @@
+ "AsyncContextImpl$1");
+ loader.loadClass
+ (basePackage +
+- "AsyncContextImpl$PrivilegedGetTccl");
+- loader.loadClass
+- (basePackage +
+- "AsyncContextImpl$PrivilegedSetTccl");
+- loader.loadClass
+- (basePackage +
+ "AsyncListenerWrapper");
+ loader.loadClass
+ (basePackage +
+@@ -124,14 +117,24 @@
+ }
+
+
++ private static final void loadServletsPackage(ClassLoader loader)
++ throws Exception {
++ final String basePackage = "org.apache.catalina.servlets.";
++ // Avoid a possible memory leak in the DefaultServlet when running with
++ // a security manager. The DefaultServlet needs to load an XML parser
++ // when running under a security manager. We want this to be loaded by
++ // the container rather than a web application to prevent a memory leak
++ // via web application class loader.
++ loader.loadClass(basePackage + "DefaultServlet");
++ }
++
++
+ private static final void loadSessionPackage(ClassLoader loader)
+ throws Exception {
+ final String basePackage = "org.apache.catalina.session.";
+ loader.loadClass
+ (basePackage + "StandardSession");
+ loader.loadClass
+- (basePackage + "StandardSession$PrivilegedSetTccl");
+- loader.loadClass
+ (basePackage + "StandardSession$1");
+ loader.loadClass
+ (basePackage + "StandardManager$PrivilegedDoUnload");
+@@ -280,10 +283,9 @@
+ loader.loadClass(basePackage +
+ "util.net.NioBlockingSelector$BlockPoller$3");
+ loader.loadClass(basePackage + "util.net.SSLSupport$CipherData");
+- loader.loadClass
+- (basePackage + "util.net.JIoEndpoint$PrivilegedSetTccl");
+- loader.loadClass
+- (basePackage + "util.net.AprEndpoint$PrivilegedSetTccl");
++ // security
++ loader.loadClass(basePackage + "util.security.PrivilegedGetTccl");
++ loader.loadClass(basePackage + "util.security.PrivilegedSetTccl");
+ }
+ }
+
+--- java/org/apache/catalina/servlets/DefaultServlet.java.orig 2014-07-24 18:29:38.875020000 -0400
++++ java/org/apache/catalina/servlets/DefaultServlet.java 2014-07-24 18:31:18.695352000 -0400
+@@ -14,8 +14,6 @@
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-
+-
+ package org.apache.catalina.servlets;
+
+
+@@ -34,6 +32,7 @@
+ import java.io.Reader;
+ import java.io.StringReader;
+ import java.io.StringWriter;
++import java.security.AccessController;
+ import java.util.ArrayList;
+ import java.util.Iterator;
+ import java.util.Locale;
+@@ -76,11 +75,14 @@
+ import org.apache.naming.resources.Resource;
+ import org.apache.naming.resources.ResourceAttributes;
+ import org.apache.tomcat.util.res.StringManager;
+-
++import org.apache.tomcat.util.security.PrivilegedGetTccl;
++import org.apache.tomcat.util.security.PrivilegedSetTccl;
+ import org.w3c.dom.Document;
+ import org.xml.sax.InputSource;
+ import org.xml.sax.SAXException;
+ import org.xml.sax.ext.EntityResolver2;
++
++
+ /**
+ * The default resource-serving servlet for most web applications,
+ * used to serve static resources such as HTML pages and images.
+@@ -122,9 +124,7 @@
+ *
+ * @author Craig R. McClanahan
+ * @author Remy Maucherat
+- * @version $Id: DefaultServlet.java 1301255 2012-03-15 22:47:40Z markt $
+ */
+-
+ public class DefaultServlet
+ extends HttpServlet {
+
+@@ -132,10 +132,10 @@
+
+ private static final DocumentBuilderFactory factory;
+
+- private static final SecureEntityResolver secureEntityResolver =
+- new SecureEntityResolver();
+- // ----------------------------------------------------- Instance Variables
++ private static final SecureEntityResolver secureEntityResolver;
++
+
++ // ----------------------------------------------------- Instance Variables
+
+ /**
+ * The debugging detail level for this servlet.
+@@ -225,6 +225,11 @@
+ */
+ protected static final ArrayList FULL = new ArrayList();
+
++ /**
++ * Flag to determine if server information is presented.
++ */
++ protected boolean showServerInfo = true;
++
+
+ // ----------------------------------------------------- Static Initializer
+
+@@ -239,9 +244,16 @@
+ urlEncoder.addSafeCharacter('.');
+ urlEncoder.addSafeCharacter('*');
+ urlEncoder.addSafeCharacter('/');
+- factory = DocumentBuilderFactory.newInstance();
+- factory.setNamespaceAware(true);
+- factory.setValidating(false);
++
++ if (Globals.IS_SECURITY_ENABLED) {
++ factory = DocumentBuilderFactory.newInstance();
++ factory.setNamespaceAware(true);
++ factory.setValidating(false);
++ secureEntityResolver = new SecureEntityResolver();
++ } else {
++ factory = null;
++ secureEntityResolver = null;
++ }
+ }
+
+
+@@ -270,6 +282,7 @@
+ protected static final int BUFFER_SIZE = 4096;
+
+
++
+ // --------------------------------------------------------- Public Methods
+
+
+@@ -345,6 +358,9 @@
+ throw new UnavailableException("No resources");
+ }
+
++ if (getServletConfig().getInitParameter("showServerInfo") != null) {
++ showServerInfo = Boolean.parseBoolean(getServletConfig().getInitParameter("showServerInfo"));
++ }
+ }
+
+
+@@ -1251,7 +1267,6 @@
+ }
+
+
+-
+ /**
+ * Decide which way to render. HTML or XML.
+ */
+@@ -1259,13 +1274,15 @@
+ throws IOException, ServletException {
+
+ Source xsltSource = findXsltInputStream(cacheEntry.context);
+- if (xsltSource ==null) {
++
++ if (xsltSource == null) {
+ return renderHtml(contextPath, cacheEntry);
+ }
+ return renderXml(contextPath, cacheEntry, xsltSource);
+
+ }
+
++
+ /**
+ * Return an InputStream to an HTML representation of the contents
+ * of this directory.
+@@ -1362,11 +1379,27 @@
+ sb.append("]]>");
+ }
+
+-
+ sb.append("");
+
+-
++ // Prevent possible memory leak. Ensure Transformer and
++ // TransformerFactory are not loaded from the web application.
++ ClassLoader original;
++ if (Globals.IS_SECURITY_ENABLED) {
++ PrivilegedGetTccl pa = new PrivilegedGetTccl();
++ original = AccessController.doPrivileged(pa);
++ } else {
++ original = Thread.currentThread().getContextClassLoader();
++ }
+ try {
++ if (Globals.IS_SECURITY_ENABLED) {
++ PrivilegedSetTccl pa =
++ new PrivilegedSetTccl(DefaultServlet.class.getClassLoader());
++ AccessController.doPrivileged(pa);
++ } else {
++ Thread.currentThread().setContextClassLoader(
++ DefaultServlet.class.getClassLoader());
++ }
++
+ TransformerFactory tFactory = TransformerFactory.newInstance();
+ Source xmlSource = new StreamSource(new StringReader(sb.toString()));
+ Transformer transformer = tFactory.newTransformer(xsltSource);
+@@ -1379,6 +1412,13 @@
+ return (new ByteArrayInputStream(stream.toByteArray()));
+ } catch (TransformerException e) {
+ throw new ServletException("XSL transformer error", e);
++ } finally {
++ if (Globals.IS_SECURITY_ENABLED) {
++ PrivilegedSetTccl pa = new PrivilegedSetTccl(original);
++ AccessController.doPrivileged(pa);
++ } else {
++ Thread.currentThread().setContextClassLoader(original);
++ }
+ }
+ }
+
+@@ -1530,7 +1570,9 @@
+ sb.append("
");
+ }
+
+- sb.append("").append(ServerInfo.getServerInfo()).append("
");
++ if (showServerInfo) {
++ sb.append("").append(ServerInfo.getServerInfo()).append("
");
++ }
+ sb.append("