# HG changeset patch # User joehw # Date 1381487702 -3600 # Node ID aeaabc10209ed10fa019a243046c3813124e2075 # Parent 00f1d7d220a94e723a522d1affc3b98c21027be2 8014530: Better digital signature processing Reviewed-by: alanb, dfuchs, mullan, lancea diff -r 00f1d7d220a9 -r aeaabc10209e src/com/sun/org/apache/xalan/internal/XalanConstants.java --- a/src/com/sun/org/apache/xalan/internal/XalanConstants.java Thu Oct 10 16:45:02 2013 +0100 +++ b/src/com/sun/org/apache/xalan/internal/XalanConstants.java Fri Oct 11 11:35:02 2013 +0100 @@ -40,6 +40,116 @@ // // Constants + //Xerces security manager + public static final String SECURITY_MANAGER = + "http://apache.org/xml/properties/security-manager"; + + // + // Implementation limits: API properties + // + /** Oracle JAXP property prefix ("http://www.oracle.com/xml/jaxp/properties/"). */ + public static final String ORACLE_JAXP_PROPERTY_PREFIX = + "http://www.oracle.com/xml/jaxp/properties/"; + /** + * JDK entity expansion limit; Note that the existing system property + * "entityExpansionLimit" with no prefix is still observed + */ + public static final String JDK_ENTITY_EXPANSION_LIMIT = + ORACLE_JAXP_PROPERTY_PREFIX + "entityExpansionLimit"; + + /** + * JDK element attribute limit; Note that the existing system property + * "elementAttributeLimit" with no prefix is still observed + */ + public static final String JDK_ELEMENT_ATTRIBUTE_LIMIT = + ORACLE_JAXP_PROPERTY_PREFIX + "elementAttributeLimit"; + + /** + * JDK maxOccur limit; Note that the existing system property + * "maxOccurLimit" with no prefix is still observed + */ + public static final String JDK_MAX_OCCUR_LIMIT = + ORACLE_JAXP_PROPERTY_PREFIX + "maxOccurLimit"; + + /** + * JDK total entity size limit + */ + public static final String JDK_TOTAL_ENTITY_SIZE_LIMIT = + ORACLE_JAXP_PROPERTY_PREFIX + "totalEntitySizeLimit"; + + /** + * JDK maximum general entity size limit + */ + public static final String JDK_GENEAL_ENTITY_SIZE_LIMIT = + ORACLE_JAXP_PROPERTY_PREFIX + "maxGeneralEntitySizeLimit"; + /** + * JDK maximum parameter entity size limit + */ + public static final String JDK_PARAMETER_ENTITY_SIZE_LIMIT = + ORACLE_JAXP_PROPERTY_PREFIX + "maxParameterEntitySizeLimit"; + /** + * JDK maximum XML name limit + */ + public static final String JDK_XML_NAME_LIMIT = + ORACLE_JAXP_PROPERTY_PREFIX + "maxXMLNameLimit"; + /** + * JDK property indicating whether the parser shall print out entity + * count information + * Value: a string "yes" means print, "no" or any other string means not. + */ + public static final String JDK_ENTITY_COUNT_INFO = + ORACLE_JAXP_PROPERTY_PREFIX + "getEntityCountInfo"; + + // + // Implementation limits: corresponding System Properties of the above + // API properties + // + /** + * JDK entity expansion limit; Note that the existing system property + * "entityExpansionLimit" with no prefix is still observed + */ + public static final String SP_ENTITY_EXPANSION_LIMIT = "jdk.xml.entityExpansionLimit"; + + /** + * JDK element attribute limit; Note that the existing system property + * "elementAttributeLimit" with no prefix is still observed + */ + public static final String SP_ELEMENT_ATTRIBUTE_LIMIT = "jdk.xml.elementAttributeLimit"; + + /** + * JDK maxOccur limit; Note that the existing system property + * "maxOccurLimit" with no prefix is still observed + */ + public static final String SP_MAX_OCCUR_LIMIT = "jdk.xml.maxOccurLimit"; + + /** + * JDK total entity size limit + */ + public static final String SP_TOTAL_ENTITY_SIZE_LIMIT = "jdk.xml.totalEntitySizeLimit"; + + /** + * JDK maximum general entity size limit + */ + public static final String SP_GENEAL_ENTITY_SIZE_LIMIT = "jdk.xml.maxGeneralEntitySizeLimit"; + /** + * JDK maximum parameter entity size limit + */ + public static final String SP_PARAMETER_ENTITY_SIZE_LIMIT = "jdk.xml.maxParameterEntitySizeLimit"; + /** + * JDK maximum XML name limit + */ + public static final String SP_XML_NAME_LIMIT = "jdk.xml.maxXMLNameLimit"; + + //legacy System Properties + public final static String ENTITY_EXPANSION_LIMIT = "entityExpansionLimit"; + public static final String ELEMENT_ATTRIBUTE_LIMIT = "elementAttributeLimit" ; + public final static String MAX_OCCUR_LIMIT = "maxOccurLimit"; + + /** + * A string "yes" that can be used for properties such as getEntityCountInfo + */ + public static final String JDK_YES = "yes"; + // // Oracle Feature: /** diff -r 00f1d7d220a9 -r aeaabc10209e src/com/sun/org/apache/xalan/internal/utils/SecuritySupport.java --- a/src/com/sun/org/apache/xalan/internal/utils/SecuritySupport.java Thu Oct 10 16:45:02 2013 +0100 +++ b/src/com/sun/org/apache/xalan/internal/utils/SecuritySupport.java Fri Oct 11 11:35:02 2013 +0100 @@ -26,6 +26,7 @@ import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; +import java.io.IOException; import java.io.InputStream; import java.security.AccessController; @@ -36,6 +37,7 @@ import java.util.Locale; import java.util.MissingResourceException; import java.util.ResourceBundle; +import java.util.Properties; /** * This class is duplicated for each subpackage so keep it in sync. It is @@ -200,6 +202,54 @@ })).longValue(); } + /** + * Read from $java.home/lib/jaxp.properties for the specified property + * The program + * + * @param propertyId the Id of the property + * @return the value of the property + */ + static String readJAXPProperty(String propertyId) { + String value = null; + InputStream is = null; + try { + if (firstTime) { + synchronized (cacheProps) { + if (firstTime) { + String configFile = getSystemProperty("java.home") + File.separator + + "lib" + File.separator + "jaxp.properties"; + File f = new File(configFile); + if (getFileExists(f)) { + is = getFileInputStream(f); + cacheProps.load(is); + } + firstTime = false; + } + } + } + value = cacheProps.getProperty(propertyId); + + } + catch (Exception ex) {} + finally { + if (is != null) { + try { + is.close(); + } catch (IOException ex) {} + } + } + return value; + } + + /** + * Cache for properties in java.home/lib/jaxp.properties + */ + static final Properties cacheProps = new Properties(); + + /** + * Flag indicating if the program has tried reading java.home/lib/jaxp.properties + */ + static volatile boolean firstTime = true; private SecuritySupport() { } diff -r 00f1d7d220a9 -r aeaabc10209e src/com/sun/org/apache/xalan/internal/utils/XMLSecurityManager.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/com/sun/org/apache/xalan/internal/utils/XMLSecurityManager.java Fri Oct 11 11:35:02 2013 +0100 @@ -0,0 +1,449 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common Development + * and Distribution License("CDDL") (collectively, the "License"). You + * may not use this file except in compliance with the License. You can + * obtain a copy of the License at + * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html + * or packager/legal/LICENSE.txt. See the License for the specific + * language governing permissions and limitations under the License. + * + * When distributing the software, include this License Header Notice in each + * file and include the License file at packager/legal/LICENSE.txt. + * + * GPL Classpath Exception: + * Oracle designates this particular file as subject to the "Classpath" + * exception as provided by Oracle in the GPL Version 2 section of the License + * file that accompanied this code. + * + * Modifications: + * If applicable, add the following below the License Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyright [year] [name of copyright owner]" + * + * Contributor(s): + * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to + * its licensees as provided above. However, if you add GPL Version 2 code + * and therefore, elected the GPL Version 2 license, then the option applies + * only if the new code is made subject to such option by the copyright + * holder. + */ +package com.sun.org.apache.xalan.internal.utils; + +import com.sun.org.apache.xalan.internal.XalanConstants; + + +/** + * This class is not the same as that in Xerces. It is used to manage the + * state of corresponding Xerces properties and pass the values over to + * the Xerces Security Manager. + * + * @author Joe Wang Oracle Corp. + * + */ +public final class XMLSecurityManager { + + /** + * States of the settings of a property, in the order: default value, value + * set by FEATURE_SECURE_PROCESSING, jaxp.properties file, jaxp system + * properties, and jaxp api properties + */ + public static enum State { + //this order reflects the overriding order + + DEFAULT("default"), FSP("FEATURE_SECURE_PROCESSING"), + JAXPDOTPROPERTIES("jaxp.properties"), SYSTEMPROPERTY("system property"), + APIPROPERTY("property"); + + final String literal; + State(String literal) { + this.literal = literal; + } + + String literal() { + return literal; + } + } + + /** + * Limits managed by the security manager + */ + public static enum Limit { + + ENTITY_EXPANSION_LIMIT(XalanConstants.JDK_ENTITY_EXPANSION_LIMIT, + XalanConstants.SP_ENTITY_EXPANSION_LIMIT, 0, 64000), + MAX_OCCUR_NODE_LIMIT(XalanConstants.JDK_MAX_OCCUR_LIMIT, + XalanConstants.SP_MAX_OCCUR_LIMIT, 0, 5000), + ELEMENT_ATTRIBUTE_LIMIT(XalanConstants.JDK_ELEMENT_ATTRIBUTE_LIMIT, + XalanConstants.SP_ELEMENT_ATTRIBUTE_LIMIT, 0, 10000), + TOTAL_ENTITY_SIZE_LIMIT(XalanConstants.JDK_TOTAL_ENTITY_SIZE_LIMIT, + XalanConstants.SP_TOTAL_ENTITY_SIZE_LIMIT, 0, 50000000), + GENEAL_ENTITY_SIZE_LIMIT(XalanConstants.JDK_GENEAL_ENTITY_SIZE_LIMIT, + XalanConstants.SP_GENEAL_ENTITY_SIZE_LIMIT, 0, 0), + PARAMETER_ENTITY_SIZE_LIMIT(XalanConstants.JDK_PARAMETER_ENTITY_SIZE_LIMIT, + XalanConstants.SP_PARAMETER_ENTITY_SIZE_LIMIT, 0, 1000000); + + final String apiProperty; + final String systemProperty; + final int defaultValue; + final int secureValue; + + Limit(String apiProperty, String systemProperty, int value, int secureValue) { + this.apiProperty = apiProperty; + this.systemProperty = systemProperty; + this.defaultValue = value; + this.secureValue = secureValue; + } + + public boolean equalsAPIPropertyName(String propertyName) { + return (propertyName == null) ? false : apiProperty.equals(propertyName); + } + + public boolean equalsSystemPropertyName(String propertyName) { + return (propertyName == null) ? false : systemProperty.equals(propertyName); + } + + public String apiProperty() { + return apiProperty; + } + + String systemProperty() { + return systemProperty; + } + + int defaultValue() { + return defaultValue; + } + + int secureValue() { + return secureValue; + } + } + + /** + * Map old property names with the new ones + */ + public static enum NameMap { + + ENTITY_EXPANSION_LIMIT(XalanConstants.SP_ENTITY_EXPANSION_LIMIT, + XalanConstants.ENTITY_EXPANSION_LIMIT), + MAX_OCCUR_NODE_LIMIT(XalanConstants.SP_MAX_OCCUR_LIMIT, + XalanConstants.MAX_OCCUR_LIMIT), + ELEMENT_ATTRIBUTE_LIMIT(XalanConstants.SP_ELEMENT_ATTRIBUTE_LIMIT, + XalanConstants.ELEMENT_ATTRIBUTE_LIMIT); + final String newName; + final String oldName; + + NameMap(String newName, String oldName) { + this.newName = newName; + this.oldName = oldName; + } + + String getOldName(String newName) { + if (newName.equals(this.newName)) { + return oldName; + } + return null; + } + } + /** + * Values of the properties + */ + private final int[] values; + /** + * States of the settings for each property + */ + private State[] states; + /** + * States that determine if properties are set explicitly + */ + private boolean[] isSet; + + + /** + * Index of the special entityCountInfo property + */ + private int indexEntityCountInfo = 10000; + private String printEntityCountInfo = ""; + + /** + * Default constructor. Establishes default values for known security + * vulnerabilities. + */ + public XMLSecurityManager() { + this(false); + } + + /** + * Instantiate Security Manager in accordance with the status of + * secure processing + * @param secureProcessing + */ + public XMLSecurityManager(boolean secureProcessing) { + values = new int[Limit.values().length]; + states = new State[Limit.values().length]; + isSet = new boolean[Limit.values().length]; + for (Limit limit : Limit.values()) { + if (secureProcessing) { + values[limit.ordinal()] = limit.secureValue(); + states[limit.ordinal()] = State.FSP; + } else { + values[limit.ordinal()] = limit.defaultValue(); + states[limit.ordinal()] = State.DEFAULT; + } + } + //read system properties or jaxp.properties + readSystemProperties(); + } + + /** + * Setting FEATURE_SECURE_PROCESSING explicitly + */ + public void setSecureProcessing(boolean secure) { + for (Limit limit : Limit.values()) { + if (secure) { + setLimit(limit.ordinal(), State.FSP, limit.secureValue()); + } else { + setLimit(limit.ordinal(), State.FSP, limit.defaultValue()); + } + } + } + + /** + * Set limit by property name and state + * @param propertyName property name + * @param state the state of the property + * @param value the value of the property + * @return true if the property is managed by the security manager; false + * if otherwise. + */ + public boolean setLimit(String propertyName, State state, Object value) { + int index = getIndex(propertyName); + if (index > -1) { + setLimit(index, state, value); + return true; + } + return false; + } + + /** + * Set the value for a specific limit. + * + * @param limit the limit + * @param state the state of the property + * @param value the value of the property + */ + public void setLimit(Limit limit, State state, int value) { + setLimit(limit.ordinal(), state, value); + } + + /** + * Set the value of a property by its index + * + * @param index the index of the property + * @param state the state of the property + * @param value the value of the property + */ + public void setLimit(int index, State state, Object value) { + if (index == indexEntityCountInfo) { + //if it's explicitly set, it's treated as yes no matter the value + printEntityCountInfo = (String)value; + } else { + int temp = 0; + try { + temp = Integer.parseInt((String) value); + if (temp < 0) { + temp = 0; + } + } catch (NumberFormatException e) {} + setLimit(index, state, temp); } + } + + /** + * Set the value of a property by its index + * + * @param index the index of the property + * @param state the state of the property + * @param value the value of the property + */ + public void setLimit(int index, State state, int value) { + if (index == indexEntityCountInfo) { + //if it's explicitly set, it's treated as yes no matter the value + printEntityCountInfo = XalanConstants.JDK_YES; + } else { + //only update if it shall override + if (state.compareTo(states[index]) >= 0) { + values[index] = value; + states[index] = state; + isSet[index] = true; + } + } + } + + + /** + * Return the value of the specified property. + * + * @param propertyName the property name + * @return the value of the property as a string. If a property is managed + * by this manager, its value shall not be null. + */ + public String getLimitAsString(String propertyName) { + int index = getIndex(propertyName); + if (index > -1) { + return getLimitValueByIndex(index); + } + + return null; + } + + /** + * Return the value of a property by its ordinal + * + * @param limit the property + * @return value of a property + */ + public String getLimitValueAsString(Limit limit) { + return Integer.toString(values[limit.ordinal()]); + } + + /** + * Return the value of the specified property + * + * @param limit the property + * @return the value of the property + */ + public int getLimit(Limit limit) { + return values[limit.ordinal()]; + } + + /** + * Return the value of a property by its ordinal + * + * @param index the index of a property + * @return value of a property + */ + public int getLimitByIndex(int index) { + return values[index]; + } + /** + * Return the value of a property by its index + * + * @param index the index of a property + * @return limit of a property as a string + */ + public String getLimitValueByIndex(int index) { + if (index == indexEntityCountInfo) { + return printEntityCountInfo; + } + + return Integer.toString(values[index]); + } + /** + * Return the state of the limit property + * + * @param limit the limit + * @return the state of the limit property + */ + public State getState(Limit limit) { + return states[limit.ordinal()]; + } + + /** + * Return the state of the limit property + * + * @param limit the limit + * @return the state of the limit property + */ + public String getStateLiteral(Limit limit) { + return states[limit.ordinal()].literal(); + } + + /** + * Get the index by property name + * + * @param propertyName property name + * @return the index of the property if found; return -1 if not + */ + public int getIndex(String propertyName) { + for (Limit limit : Limit.values()) { + if (limit.equalsAPIPropertyName(propertyName)) { + //internally, ordinal is used as index + return limit.ordinal(); + } + } + //special property to return entity count info + if (propertyName.equals(XalanConstants.JDK_ENTITY_COUNT_INFO)) { + return indexEntityCountInfo; + } + return -1; + } + + /** + * Indicate if a property is set explicitly + * @param index + * @return + */ + public boolean isSet(int index) { + return isSet[index]; + } + + public boolean printEntityCountInfo() { + return printEntityCountInfo.equals(XalanConstants.JDK_YES); + } + /** + * Read from system properties, or those in jaxp.properties + */ + private void readSystemProperties() { + + for (Limit limit : Limit.values()) { + if (!getSystemProperty(limit, limit.systemProperty())) { + //if system property is not found, try the older form if any + for (NameMap nameMap : NameMap.values()) { + String oldName = nameMap.getOldName(limit.systemProperty()); + if (oldName != null) { + getSystemProperty(limit, oldName); + } + } + } + } + + } + + /** + * Read from system properties, or those in jaxp.properties + * + * @param property the type of the property + * @param sysPropertyName the name of system property + */ + private boolean getSystemProperty(Limit limit, String sysPropertyName) { + try { + String value = SecuritySupport.getSystemProperty(sysPropertyName); + if (value != null && !value.equals("")) { + values[limit.ordinal()] = Integer.parseInt(value); + states[limit.ordinal()] = State.SYSTEMPROPERTY; + return true; + } + + value = SecuritySupport.readJAXPProperty(sysPropertyName); + if (value != null && !value.equals("")) { + values[limit.ordinal()] = Integer.parseInt(value); + states[limit.ordinal()] = State.JAXPDOTPROPERTIES; + return true; + } + } catch (NumberFormatException e) { + //invalid setting + throw new NumberFormatException("Invalid setting for system property: " + limit.systemProperty()); + } + return false; + } +} diff -r 00f1d7d220a9 -r aeaabc10209e src/com/sun/org/apache/xalan/internal/xsltc/compiler/Parser.java --- a/src/com/sun/org/apache/xalan/internal/xsltc/compiler/Parser.java Thu Oct 10 16:45:02 2013 +0100 +++ b/src/com/sun/org/apache/xalan/internal/xsltc/compiler/Parser.java Fri Oct 11 11:35:02 2013 +0100 @@ -40,12 +40,14 @@ import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; +import com.sun.org.apache.xalan.internal.XalanConstants; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodType; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.TypeCheckError; import com.sun.org.apache.xalan.internal.utils.FactoryImpl; import com.sun.org.apache.xalan.internal.utils.ObjectFactory; +import com.sun.org.apache.xalan.internal.utils.XMLSecurityManager; import org.xml.sax.Attributes; import org.xml.sax.helpers.AttributesImpl; import org.xml.sax.ContentHandler; @@ -476,6 +478,20 @@ } final SAXParser parser = factory.newSAXParser(); final XMLReader reader = parser.getXMLReader(); + try { + XMLSecurityManager securityManager = + (XMLSecurityManager)_xsltc.getProperty(XalanConstants.SECURITY_MANAGER); + for (XMLSecurityManager.Limit limit : XMLSecurityManager.Limit.values()) { + reader.setProperty(limit.apiProperty(), securityManager.getLimitValueAsString(limit)); + } + if (securityManager.printEntityCountInfo()) { + parser.setProperty(XalanConstants.JDK_ENTITY_COUNT_INFO, XalanConstants.JDK_YES); + } + } catch (SAXException se) { + System.err.println("Warning: " + reader.getClass().getName() + ": " + + se.getMessage()); + } + return(parse(reader, input)); } catch (ParserConfigurationException e) { diff -r 00f1d7d220a9 -r aeaabc10209e src/com/sun/org/apache/xalan/internal/xsltc/compiler/XSLTC.java --- a/src/com/sun/org/apache/xalan/internal/xsltc/compiler/XSLTC.java Thu Oct 10 16:45:02 2013 +0100 +++ b/src/com/sun/org/apache/xalan/internal/xsltc/compiler/XSLTC.java Fri Oct 11 11:35:02 2013 +0100 @@ -41,12 +41,13 @@ import java.util.jar.Manifest; import com.sun.org.apache.bcel.internal.classfile.JavaClass; +import com.sun.org.apache.xalan.internal.XalanConstants; import com.sun.org.apache.xalan.internal.utils.SecuritySupport; +import com.sun.org.apache.xalan.internal.utils.XMLSecurityManager; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Util; import com.sun.org.apache.xml.internal.dtm.DTM; -import com.sun.org.apache.xalan.internal.utils.SecuritySupport; import org.xml.sax.InputSource; import org.xml.sax.XMLReader; @@ -105,6 +106,7 @@ public static final int BYTEARRAY_AND_FILE_OUTPUT = 4; public static final int BYTEARRAY_AND_JAR_OUTPUT = 5; + private XMLSecurityManager _xmlSecurityManager; // Compiler options (passed from command line or XSLTC client) private boolean _debug = false; // -x @@ -919,4 +921,24 @@ return newDataOffset; } + + /** + * Return allowed protocols for accessing external stylesheet. + */ + public Object getProperty(String name) { + if (name.equals(XalanConstants.SECURITY_MANAGER)) { + return _xmlSecurityManager; + } + return null; + } + + /** + * Set allowed protocols for accessing external stylesheet. + */ + public void setProperty(String name, Object value) { + if (name.equals(XalanConstants.SECURITY_MANAGER)) { + _xmlSecurityManager = (XMLSecurityManager)value; + } + } + } diff -r 00f1d7d220a9 -r aeaabc10209e src/com/sun/org/apache/xalan/internal/xsltc/trax/TemplatesHandlerImpl.java --- a/src/com/sun/org/apache/xalan/internal/xsltc/trax/TemplatesHandlerImpl.java Thu Oct 10 16:45:02 2013 +0100 +++ b/src/com/sun/org/apache/xalan/internal/xsltc/trax/TemplatesHandlerImpl.java Fri Oct 11 11:35:02 2013 +0100 @@ -29,7 +29,7 @@ import javax.xml.transform.TransformerException; import javax.xml.transform.URIResolver; import javax.xml.transform.sax.TemplatesHandler; - +import com.sun.org.apache.xalan.internal.XalanConstants; import com.sun.org.apache.xalan.internal.xsltc.compiler.CompilerException; import com.sun.org.apache.xalan.internal.xsltc.compiler.Parser; import com.sun.org.apache.xalan.internal.xsltc.compiler.SourceLoader; @@ -98,6 +98,8 @@ XSLTC xsltc = new XSLTC(tfactory.useServicesMechnism()); if (tfactory.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING)) xsltc.setSecureProcessing(true); + xsltc.setProperty(XalanConstants.SECURITY_MANAGER, + tfactory.getAttribute(XalanConstants.SECURITY_MANAGER)); if ("true".equals(tfactory.getAttribute(TransformerFactoryImpl.ENABLE_INLINING))) xsltc.setTemplateInlining(true); diff -r 00f1d7d220a9 -r aeaabc10209e src/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerFactoryImpl.java --- a/src/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerFactoryImpl.java Thu Oct 10 16:45:02 2013 +0100 +++ b/src/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerFactoryImpl.java Fri Oct 11 11:35:02 2013 +0100 @@ -74,6 +74,7 @@ import com.sun.org.apache.xalan.internal.utils.ObjectFactory; import com.sun.org.apache.xalan.internal.utils.FactoryImpl; import com.sun.org.apache.xalan.internal.utils.SecuritySupport; +import com.sun.org.apache.xalan.internal.utils.XMLSecurityManager; import org.xml.sax.InputSource; import org.xml.sax.XMLFilter; @@ -224,6 +225,8 @@ */ private boolean _useServicesMechanism; + private XMLSecurityManager _xmlSecurityManager; + /** * javax.xml.transform.sax.TransformerFactory implementation. */ @@ -242,6 +245,9 @@ _isSecureMode = true; _isNotSecureProcessing = false; } + + //Parser's security manager + _xmlSecurityManager = new XMLSecurityManager(true); } /** @@ -300,6 +306,8 @@ return Boolean.TRUE; else return Boolean.FALSE; + } else if (name.equals(XalanConstants.SECURITY_MANAGER)) { + return _xmlSecurityManager; } // Throw an exception for all other attributes @@ -444,6 +452,7 @@ throw new TransformerConfigurationException(err.toString()); } _isNotSecureProcessing = !value; + _xmlSecurityManager.setSecureProcessing(value); // all done processing feature return; } @@ -799,6 +808,7 @@ xsltc.setTemplateInlining(false); if (!_isNotSecureProcessing) xsltc.setSecureProcessing(true); + xsltc.setProperty(XalanConstants.SECURITY_MANAGER, _xmlSecurityManager); xsltc.init(); // Set a document loader (for xsl:include/import) if defined diff -r 00f1d7d220a9 -r aeaabc10209e src/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerImpl.java --- a/src/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerImpl.java Thu Oct 10 16:45:02 2013 +0100 +++ b/src/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerImpl.java Fri Oct 11 11:35:02 2013 +0100 @@ -23,7 +23,9 @@ package com.sun.org.apache.xalan.internal.xsltc.trax; +import com.sun.org.apache.xalan.internal.XalanConstants; import com.sun.org.apache.xalan.internal.utils.FactoryImpl; +import com.sun.org.apache.xalan.internal.utils.XMLSecurityManager; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; @@ -41,6 +43,7 @@ import java.util.Vector; import java.lang.reflect.Constructor; +import javax.xml.XMLConstants; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; @@ -208,6 +211,7 @@ */ private boolean _useServicesMechanism; + private XMLSecurityManager _securityManager; /** * A hashtable to store parameters for the identity transform. These * are not needed during the transformation, but we must keep track of @@ -260,8 +264,10 @@ _indentNumber = indentNumber; _tfactory = tfactory; _useServicesMechanism = _tfactory.useServicesMechnism(); + _securityManager = (XMLSecurityManager)_tfactory.getAttribute(XalanConstants.SECURITY_MANAGER); _readerManager = XMLReaderManager.getInstance(_useServicesMechanism); _readerManager.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, _isSecureProcessing); + _readerManager.setProperty(XalanConstants.SECURITY_MANAGER, _securityManager); //_isIncremental = tfactory._incremental; } diff -r 00f1d7d220a9 -r aeaabc10209e src/com/sun/org/apache/xalan/internal/xsltc/trax/Util.java --- a/src/com/sun/org/apache/xalan/internal/xsltc/trax/Util.java Thu Oct 10 16:45:02 2013 +0100 +++ b/src/com/sun/org/apache/xalan/internal/xsltc/trax/Util.java Fri Oct 11 11:35:02 2013 +0100 @@ -23,6 +23,7 @@ package com.sun.org.apache.xalan.internal.xsltc.trax; +import com.sun.org.apache.xalan.internal.XalanConstants; import java.io.InputStream; import java.io.Reader; @@ -43,6 +44,7 @@ import javax.xml.transform.stream.StreamSource; import com.sun.org.apache.xalan.internal.utils.FactoryImpl; +import com.sun.org.apache.xalan.internal.utils.XMLSecurityManager; import com.sun.org.apache.xalan.internal.xsltc.compiler.XSLTC; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg; @@ -143,6 +145,22 @@ reader.setFeature ("http://xml.org/sax/features/namespace-prefixes",false); + try { + XMLSecurityManager securityManager = + (XMLSecurityManager)xsltc.getProperty(XalanConstants.SECURITY_MANAGER); + if (securityManager != null) { + for (XMLSecurityManager.Limit limit : XMLSecurityManager.Limit.values()) { + reader.setProperty(limit.apiProperty(), + securityManager.getLimitValueAsString(limit)); + } + if (securityManager.printEntityCountInfo()) { + reader.setProperty(XalanConstants.JDK_ENTITY_COUNT_INFO, XalanConstants.JDK_YES); + } + } + } catch (SAXException se) { + System.err.println("Warning: " + reader.getClass().getName() + ": " + + se.getMessage()); + } xsltc.setXMLReader(reader); }catch (SAXNotRecognizedException snre ) { throw new TransformerConfigurationException diff -r 00f1d7d220a9 -r aeaabc10209e src/com/sun/org/apache/xerces/internal/dom/DOMConfigurationImpl.java --- a/src/com/sun/org/apache/xerces/internal/dom/DOMConfigurationImpl.java Thu Oct 10 16:45:02 2013 +0100 +++ b/src/com/sun/org/apache/xerces/internal/dom/DOMConfigurationImpl.java Fri Oct 11 11:35:02 2013 +0100 @@ -56,11 +56,13 @@ import com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource; import com.sun.org.apache.xerces.internal.xni.parser.XMLParserConfiguration; import com.sun.org.apache.xerces.internal.utils.ObjectFactory; +import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager; import org.w3c.dom.DOMException; import org.w3c.dom.ls.LSResourceResolver; + /** * Xerces implementation of DOMConfiguration that maintains a table of recognized parameters. * @@ -158,6 +160,9 @@ protected static final String SCHEMA_DV_FACTORY = Constants.XERCES_PROPERTY_PREFIX + Constants.SCHEMA_DV_FACTORY_PROPERTY; + /** Property identifier: Security manager. */ + private static final String SECURITY_MANAGER = Constants.SECURITY_MANAGER; + // // Data // @@ -276,7 +281,8 @@ JAXP_SCHEMA_SOURCE, JAXP_SCHEMA_LANGUAGE, DTD_VALIDATOR_FACTORY_PROPERTY, - SCHEMA_DV_FACTORY + SCHEMA_DV_FACTORY, + SECURITY_MANAGER, }; addRecognizedProperties(recognizedProperties); @@ -310,6 +316,8 @@ fValidationManager = createValidationManager(); setProperty(VALIDATION_MANAGER, fValidationManager); + setProperty(SECURITY_MANAGER, new XMLSecurityManager(true)); + // add message formatters if (fErrorReporter.getMessageFormatter(XMLMessageFormatter.XML_DOMAIN) == null) { diff -r 00f1d7d220a9 -r aeaabc10209e src/com/sun/org/apache/xerces/internal/impl/Constants.java --- a/src/com/sun/org/apache/xerces/internal/impl/Constants.java Thu Oct 10 16:45:02 2013 +0100 +++ b/src/com/sun/org/apache/xerces/internal/impl/Constants.java Fri Oct 11 11:35:02 2013 +0100 @@ -158,8 +158,110 @@ /** JAXP schemaSource language: when used internally may include DTD namespace (DOM) */ public static final String SCHEMA_LANGUAGE = "schemaLanguage"; - public static final String SYSTEM_PROPERTY_ELEMENT_ATTRIBUTE_LIMIT = "elementAttributeLimit" ; + /** Oracle JAXP property prefix ("http://www.oracle.com/xml/jaxp/properties/"). */ + public static final String ORACLE_JAXP_PROPERTY_PREFIX = + "http://www.oracle.com/xml/jaxp/properties/"; + + // + // Implementation limits: corresponding System Properties of the above + // API properties + // + /** + * JDK entity expansion limit; Note that the existing system property + * "entityExpansionLimit" with no prefix is still observed + */ + public static final String JDK_ENTITY_EXPANSION_LIMIT = + ORACLE_JAXP_PROPERTY_PREFIX + "entityExpansionLimit"; + + /** + * JDK element attribute limit; Note that the existing system property + * "elementAttributeLimit" with no prefix is still observed + */ + public static final String JDK_ELEMENT_ATTRIBUTE_LIMIT = + ORACLE_JAXP_PROPERTY_PREFIX + "elementAttributeLimit"; + + /** + * JDK maxOccur limit; Note that the existing system property + * "maxOccurLimit" with no prefix is still observed + */ + public static final String JDK_MAX_OCCUR_LIMIT = + ORACLE_JAXP_PROPERTY_PREFIX + "maxOccurLimit"; + + /** + * JDK total entity size limit + */ + public static final String JDK_TOTAL_ENTITY_SIZE_LIMIT = + ORACLE_JAXP_PROPERTY_PREFIX + "totalEntitySizeLimit"; + /** + * JDK maximum general entity size limit + */ + public static final String JDK_GENEAL_ENTITY_SIZE_LIMIT = + ORACLE_JAXP_PROPERTY_PREFIX + "maxGeneralEntitySizeLimit"; + /** + * JDK maximum parameter entity size limit + */ + public static final String JDK_PARAMETER_ENTITY_SIZE_LIMIT = + ORACLE_JAXP_PROPERTY_PREFIX + "maxParameterEntitySizeLimit"; + /** + * JDK maximum XML name limit + */ + public static final String JDK_XML_NAME_LIMIT = + ORACLE_JAXP_PROPERTY_PREFIX + "maxXMLNameLimit"; + /** + * JDK property to allow printing out information from the limit analyzer + */ + public static final String JDK_ENTITY_COUNT_INFO = + ORACLE_JAXP_PROPERTY_PREFIX + "getEntityCountInfo"; + + // + // Implementation limits: API properties + // + /** + * JDK entity expansion limit; Note that the existing system property + * "entityExpansionLimit" with no prefix is still observed + */ + public static final String SP_ENTITY_EXPANSION_LIMIT = "jdk.xml.entityExpansionLimit"; + + /** + * JDK element attribute limit; Note that the existing system property + * "elementAttributeLimit" with no prefix is still observed + */ + public static final String SP_ELEMENT_ATTRIBUTE_LIMIT = "jdk.xml.elementAttributeLimit"; + + /** + * JDK maxOccur limit; Note that the existing system property + * "maxOccurLimit" with no prefix is still observed + */ + public static final String SP_MAX_OCCUR_LIMIT = "jdk.xml.maxOccurLimit"; + + /** + * JDK total entity size limit + */ + public static final String SP_TOTAL_ENTITY_SIZE_LIMIT = "jdk.xml.totalEntitySizeLimit"; + + /** + * JDK maximum general entity size limit + */ + public static final String SP_GENEAL_ENTITY_SIZE_LIMIT = "jdk.xml.maxGeneralEntitySizeLimit"; + /** + * JDK maximum parameter entity size limit + */ + public static final String SP_PARAMETER_ENTITY_SIZE_LIMIT = "jdk.xml.maxParameterEntitySizeLimit"; + /** + * JDK maximum XML name limit + */ + public static final String SP_XML_NAME_LIMIT = "jdk.xml.maxXMLNameLimit"; + + //legacy System Properties + public final static String ENTITY_EXPANSION_LIMIT = "entityExpansionLimit"; + public static final String ELEMENT_ATTRIBUTE_LIMIT = "elementAttributeLimit" ; + public final static String MAX_OCCUR_LIMIT = "maxOccurLimit"; + + /** + * A string "yes" that can be used for properties such as getEntityCountInfo + */ + public static final String JDK_YES = "yes"; // // DOM features // @@ -395,7 +497,7 @@ public static final String LOCALE_PROPERTY = "locale"; /** property identifier: security manager. */ - protected static final String SECURITY_MANAGER = + public static final String SECURITY_MANAGER = Constants.XERCES_PROPERTY_PREFIX + Constants.SECURITY_MANAGER_PROPERTY; @@ -463,9 +565,6 @@ */ public final static String ATTRIBUTE_DECLARED = "ATTRIBUTE_DECLARED"; - public final static String ENTITY_EXPANSION_LIMIT = "entityExpansionLimit"; - - public final static String MAX_OCCUR_LIMIT = "maxOccurLimit"; /** * {@link org.w3c.dom.TypeInfo} associated with current element/attribute diff -r 00f1d7d220a9 -r aeaabc10209e src/com/sun/org/apache/xerces/internal/impl/PropertyManager.java --- a/src/com/sun/org/apache/xerces/internal/impl/PropertyManager.java Thu Oct 10 16:45:02 2013 +0100 +++ b/src/com/sun/org/apache/xerces/internal/impl/PropertyManager.java Fri Oct 11 11:35:02 2013 +0100 @@ -25,6 +25,7 @@ package com.sun.org.apache.xerces.internal.impl; +import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager; import java.util.HashMap; import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLOutputFactory; @@ -50,9 +51,13 @@ private static final String STRING_INTERNING = "http://xml.org/sax/features/string-interning"; + /** Property identifier: Security manager. */ + private static final String SECURITY_MANAGER = Constants.SECURITY_MANAGER; HashMap supportedProps = new HashMap(); + private XMLSecurityManager fSecurityManager; + public static final int CONTEXT_READER = 1; public static final int CONTEXT_WRITER = 2; @@ -77,6 +82,7 @@ HashMap properties = propertyManager.getProperties(); supportedProps.putAll(properties); + fSecurityManager = (XMLSecurityManager)getProperty(SECURITY_MANAGER); } private HashMap getProperties(){ @@ -117,6 +123,9 @@ supportedProps.put(Constants.XERCES_FEATURE_PREFIX + Constants.WARN_ON_DUPLICATE_ATTDEF_FEATURE, new Boolean(false)); supportedProps.put(Constants.XERCES_FEATURE_PREFIX + Constants.WARN_ON_DUPLICATE_ENTITYDEF_FEATURE, new Boolean(false)); supportedProps.put(Constants.XERCES_FEATURE_PREFIX + Constants.WARN_ON_UNDECLARED_ELEMDEF_FEATURE, new Boolean(false)); + + fSecurityManager = new XMLSecurityManager(true); + supportedProps.put(SECURITY_MANAGER, fSecurityManager); } private void initWriterProps(){ @@ -132,7 +141,8 @@ * } */ public boolean containsProperty(String property){ - return supportedProps.containsKey(property) ; + return supportedProps.containsKey(property) || + (fSecurityManager != null && fSecurityManager.getIndex(property) > -1) ; } public Object getProperty(String property){ diff -r 00f1d7d220a9 -r aeaabc10209e src/com/sun/org/apache/xerces/internal/impl/XML11NSDocumentScannerImpl.java --- a/src/com/sun/org/apache/xerces/internal/impl/XML11NSDocumentScannerImpl.java Thu Oct 10 16:45:02 2013 +0100 +++ b/src/com/sun/org/apache/xerces/internal/impl/XML11NSDocumentScannerImpl.java Fri Oct 11 11:35:02 2013 +0100 @@ -108,6 +108,7 @@ * @author Elena Litani, IBM * @author Michael Glavassevich, IBM * @author Sunitha Reddy, Sun Microsystems + * @version $Id: XML11NSDocumentScannerImpl.java,v 1.6 2010-11-01 04:39:40 joehw Exp $ */ public class XML11NSDocumentScannerImpl extends XML11DocumentScannerImpl { @@ -236,7 +237,8 @@ // attributes scanAttribute(fAttributes); - if (fSecurityManager != null && fAttributes.getLength() > fElementAttributeLimit){ + if (fSecurityManager != null && (!fSecurityManager.isNoLimit(fElementAttributeLimit)) && + fAttributes.getLength() > fElementAttributeLimit){ fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN, "ElementAttributeLimit", new Object[]{rawname, new Integer(fElementAttributeLimit) }, diff -r 00f1d7d220a9 -r aeaabc10209e src/com/sun/org/apache/xerces/internal/impl/XMLDTDScannerImpl.java --- a/src/com/sun/org/apache/xerces/internal/impl/XMLDTDScannerImpl.java Thu Oct 10 16:45:02 2013 +0100 +++ b/src/com/sun/org/apache/xerces/internal/impl/XMLDTDScannerImpl.java Fri Oct 11 11:35:02 2013 +0100 @@ -44,6 +44,8 @@ import com.sun.org.apache.xerces.internal.impl.XMLErrorReporter; import com.sun.org.apache.xerces.internal.impl.XMLEntityHandler; import com.sun.org.apache.xerces.internal.impl.Constants; +import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager; +import com.sun.xml.internal.stream.Entity; /** * This class is responsible for scanning the declarations found @@ -66,7 +68,7 @@ * @author Glenn Marcy, IBM * @author Eric Ye, IBM * - * @version $Id: XMLDTDScannerImpl.java,v 1.7 2007/09/26 12:52:40 ndw Exp $ + * @version $Id: XMLDTDScannerImpl.java,v 1.8 2010-11-01 04:39:41 joehw Exp $ */ public class XMLDTDScannerImpl extends XMLScanner @@ -1545,7 +1547,7 @@ // internal entity if (systemId == null) { - scanEntityValue(fLiteral, fLiteral2); + scanEntityValue(name, isPEDecl, fLiteral, fLiteral2); // since we need it's value anyway, let's snag it so it doesn't get corrupted // if a new load takes place before we store the entity values fStringBuffer.clear(); @@ -1610,7 +1612,7 @@ * the use of scanCharReferenceValue), and fStringBuffer2, anything in them * at the time of calling is lost. */ - protected final void scanEntityValue(XMLString value, + protected final void scanEntityValue(String entityName, boolean isPEDecl, XMLString value, XMLString nonNormalizedValue) throws IOException, XNIException { int quote = fEntityScanner.scanChar(); @@ -1622,10 +1624,20 @@ XMLString literal = fString; XMLString literal2 = fString; + int countChar = 0; + if (fLimitAnalyzer == null && fSecurityManager != null) { + fLimitAnalyzer = fSecurityManager.getLimitAnalyzer(); + fLimitAnalyzer.startEntity(entityName); + } + if (fEntityScanner.scanLiteral(quote, fString) != quote) { fStringBuffer.clear(); fStringBuffer2.clear(); do { + if (isPEDecl && fLimitAnalyzer != null) { + checkLimit("%" + entityName, fString.length + countChar); + } + countChar = 0; fStringBuffer.append(fString); fStringBuffer2.append(fString); if (fEntityScanner.skipChar('&')) { @@ -1685,6 +1697,7 @@ } } else { + countChar++; int c = fEntityScanner.peekChar(); if (XMLChar.isHighSurrogate(c)) { scanSurrogates(fStringBuffer2); @@ -1708,9 +1721,17 @@ fStringBuffer2.append(fString); literal = fStringBuffer; literal2 = fStringBuffer2; + } else { + if (isPEDecl) { + checkLimit("%" + entityName, literal); + } } value.setValues(literal); nonNormalizedValue.setValues(literal2); + if (fLimitAnalyzer != null) { + fLimitAnalyzer.endEntity(XMLSecurityManager.Limit.PARAMETER_ENTITY_SIZE_LIMIT, entityName); + } + if (!fEntityScanner.skipChar(quote)) { reportFatalError("CloseQuoteMissingInDecl", null); } @@ -2126,6 +2147,43 @@ //new SymbolTable()); } + /** + * Add the count of the content buffer and check if the accumulated + * value exceeds the limit + * @param entityName entity name + * @param buffer content buffer + */ + private void checkLimit(String entityName, XMLString buffer) { + checkLimit(entityName, buffer.length); + } + + /** + * Add the count and check limit + * @param entityName entity name + * @param len length of the buffer + */ + private void checkLimit(String entityName, int len) { + if (fLimitAnalyzer == null) { + fLimitAnalyzer = fSecurityManager.getLimitAnalyzer(); + } + fLimitAnalyzer.addValue(XMLSecurityManager.Limit.PARAMETER_ENTITY_SIZE_LIMIT, entityName, len); + if (fSecurityManager.isOverLimit(XMLSecurityManager.Limit.PARAMETER_ENTITY_SIZE_LIMIT)) { + fSecurityManager.debugPrint(); + reportFatalError("MaxEntitySizeLimit", new Object[]{entityName, + fLimitAnalyzer.getValue(XMLSecurityManager.Limit.PARAMETER_ENTITY_SIZE_LIMIT), + fSecurityManager.getLimit(XMLSecurityManager.Limit.PARAMETER_ENTITY_SIZE_LIMIT), + fSecurityManager.getStateLiteral(XMLSecurityManager.Limit.PARAMETER_ENTITY_SIZE_LIMIT)}); + } + if (fSecurityManager.isOverLimit(XMLSecurityManager.Limit.TOTAL_ENTITY_SIZE_LIMIT)) { + fSecurityManager.debugPrint(); + reportFatalError("TotalEntitySizeLimit", + new Object[]{fLimitAnalyzer.getTotalValue(XMLSecurityManager.Limit.TOTAL_ENTITY_SIZE_LIMIT), + fSecurityManager.getLimit(XMLSecurityManager.Limit.TOTAL_ENTITY_SIZE_LIMIT), + fSecurityManager.getStateLiteral(XMLSecurityManager.Limit.TOTAL_ENTITY_SIZE_LIMIT)}); + } + + } + public DTDGrammar getGrammar(){ return nvGrammarInfo; } diff -r 00f1d7d220a9 -r aeaabc10209e src/com/sun/org/apache/xerces/internal/impl/XMLDocumentFragmentScannerImpl.java --- a/src/com/sun/org/apache/xerces/internal/impl/XMLDocumentFragmentScannerImpl.java Thu Oct 10 16:45:02 2013 +0100 +++ b/src/com/sun/org/apache/xerces/internal/impl/XMLDocumentFragmentScannerImpl.java Fri Oct 11 11:35:02 2013 +0100 @@ -51,7 +51,10 @@ import com.sun.org.apache.xerces.internal.impl.Constants; import com.sun.org.apache.xerces.internal.impl.XMLEntityHandler; import com.sun.org.apache.xerces.internal.util.NamespaceSupport; +import com.sun.org.apache.xerces.internal.utils.XMLLimitAnalyzer; import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager; +import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager.Limit; +import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager.State; import com.sun.org.apache.xerces.internal.xni.NamespaceContext; import javax.xml.stream.XMLStreamConstants; import javax.xml.stream.events.XMLEvent; @@ -194,7 +197,7 @@ }; protected static final char [] cdata = {'[','C','D','A','T','A','['}; - protected static final char [] xmlDecl = {'<','?','x','m','l'}; + static final char [] xmlDecl = {'<','?','x','m','l'}; protected static final char [] endTag = {'<','/'}; // debugging @@ -351,7 +354,6 @@ protected boolean foundBuiltInRefs = false; - protected XMLSecurityManager fSecurityManager = null; //skip element algorithm static final short MAX_DEPTH_LIMIT = 5 ; @@ -550,10 +552,11 @@ fReportCdataEvent = componentManager.getFeature(Constants.STAX_REPORT_CDATA_EVENT, true); fSecurityManager = (XMLSecurityManager)componentManager.getProperty(Constants.SECURITY_MANAGER, null); + fLimitAnalyzer = fSecurityManager.getLimitAnalyzer(); + fElementAttributeLimit = (fSecurityManager != null)? fSecurityManager.getLimit(XMLSecurityManager.Limit.ELEMENT_ATTRIBUTE_LIMIT):0; - fNotifyBuiltInRefs = componentManager.getFeature(NOTIFY_BUILTIN_REFS, false); Object resolver = componentManager.getProperty(ENTITY_RESOLVER, null); @@ -638,6 +641,8 @@ dtdGrammarUtil = null; + fSecurityManager = (XMLSecurityManager)propertyManager.getProperty(Constants.SECURITY_MANAGER); + fLimitAnalyzer = fSecurityManager.getLimitAnalyzer(); } // reset(XMLComponentManager) /** @@ -914,7 +919,6 @@ // scan decl super.scanXMLDeclOrTextDecl(scanningTextDecl, fStrings); - fMarkupDepth--; // pseudo-attribute values @@ -1281,7 +1285,8 @@ fAddDefaultAttr = true; do { scanAttribute(fAttributes); - if (fSecurityManager != null && fAttributes.getLength() > fElementAttributeLimit){ + if (fSecurityManager != null && !fSecurityManager.isNoLimit(fElementAttributeLimit) && + fAttributes.getLength() > fElementAttributeLimit){ fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN, "ElementAttributeLimit", new Object[]{rawname, new Integer(fAttributes.getLength()) }, @@ -2785,6 +2790,8 @@ if(DEBUG){ System.out.println("NOT USING THE BUFFER, STRING = " + fTempString.toString()); } + //check limit before returning event + checkLimit(fContentBuffer); if(dtdGrammarUtil!= null && dtdGrammarUtil.isIgnorableWhiteSpace(fContentBuffer)){ if(DEBUG)System.out.println("Return SPACE EVENT"); return XMLEvent.SPACE; @@ -2883,6 +2890,8 @@ fLastSectionWasCharacterData = true ; continue; }else{ + //check limit before returning event + checkLimit(fContentBuffer); if(dtdGrammarUtil!= null && dtdGrammarUtil.isIgnorableWhiteSpace(fContentBuffer)){ if(DEBUG)System.out.println("Return SPACE EVENT"); return XMLEvent.SPACE; @@ -3093,6 +3102,30 @@ } //while loop }//next + /** + * Add the count of the content buffer and check if the accumulated + * value exceeds the limit + * @param buffer content buffer + */ + protected void checkLimit(XMLStringBuffer buffer) { + if (fLimitAnalyzer.isTracking(fCurrentEntityName)) { + fLimitAnalyzer.addValue(Limit.GENEAL_ENTITY_SIZE_LIMIT, fCurrentEntityName, buffer.length); + if (fSecurityManager.isOverLimit(Limit.GENEAL_ENTITY_SIZE_LIMIT)) { + fSecurityManager.debugPrint(); + reportFatalError("MaxEntitySizeLimit", new Object[]{fCurrentEntityName, + fLimitAnalyzer.getValue(Limit.GENEAL_ENTITY_SIZE_LIMIT), + fSecurityManager.getLimit(Limit.GENEAL_ENTITY_SIZE_LIMIT), + fSecurityManager.getStateLiteral(Limit.GENEAL_ENTITY_SIZE_LIMIT)}); + } + if (fSecurityManager.isOverLimit(Limit.TOTAL_ENTITY_SIZE_LIMIT)) { + fSecurityManager.debugPrint(); + reportFatalError("TotalEntitySizeLimit", + new Object[]{fLimitAnalyzer.getTotalValue(Limit.TOTAL_ENTITY_SIZE_LIMIT), + fSecurityManager.getLimit(Limit.TOTAL_ENTITY_SIZE_LIMIT), + fSecurityManager.getStateLiteral(Limit.TOTAL_ENTITY_SIZE_LIMIT)}); + } + } + } // // Protected methods diff -r 00f1d7d220a9 -r aeaabc10209e src/com/sun/org/apache/xerces/internal/impl/XMLEntityManager.java --- a/src/com/sun/org/apache/xerces/internal/impl/XMLEntityManager.java Thu Oct 10 16:45:02 2013 +0100 +++ b/src/com/sun/org/apache/xerces/internal/impl/XMLEntityManager.java Fri Oct 11 11:35:02 2013 +0100 @@ -18,7 +18,7 @@ * limitations under the License. */ -package com.sun.org.apache.xerces.internal.impl ; +package com.sun.org.apache.xerces.internal.impl; import com.sun.xml.internal.stream.StaxEntityResolverWrapper; import com.sun.xml.internal.stream.StaxXMLInputSource; @@ -64,6 +64,7 @@ import com.sun.org.apache.xerces.internal.impl.validation.ValidationManager; import com.sun.org.apache.xerces.internal.util.URI; +import com.sun.org.apache.xerces.internal.utils.XMLLimitAnalyzer; import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager; @@ -320,10 +321,13 @@ */ protected int fBufferSize = DEFAULT_BUFFER_SIZE; - // stores defaults for entity expansion limit if it has - // been set on the configuration. + /** Security Manager */ protected XMLSecurityManager fSecurityManager = null; + protected XMLLimitAnalyzer fLimitAnalyzer = null; + + protected int entityExpansionIndex; + /** * True if the document entity is standalone. This should really * only be set by the document source (e.g. XMLDocumentScanner). @@ -348,10 +352,6 @@ /** XML 1.1 entity scanner. */ protected XMLEntityScanner fXML11EntityScanner; - /** entity expansion limit (contains useful data if and only if - fSecurityManager is non-null) */ - protected int fEntityExpansionLimit = 0; - /** count of entities expanded: */ protected int fEntityExpansionCount = 0; @@ -826,6 +826,9 @@ fCurrentEntity.setEncodingExternallySpecified(encodingExternallySpecified); fEntityScanner.setCurrentEntity(fCurrentEntity); fResourceIdentifier.setValues(publicId, literalSystemId, baseSystemId, expandedSystemId); + if (fLimitAnalyzer != null) { + fLimitAnalyzer.startEntity(name); + } return encoding; } //setupCurrentEntity(String, XMLInputSource, boolean, boolean): String @@ -1275,10 +1278,13 @@ //expansions exceeds the entity expansion limit, parser will throw fatal error. // Note that this represents the nesting level of open entities. fEntityExpansionCount++; - if( fSecurityManager != null && fEntityExpansionCount > fEntityExpansionLimit ){ - fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN, - "EntityExpansionLimitExceeded", - new Object[]{new Integer(fEntityExpansionLimit) }, + if(fLimitAnalyzer != null) { + fLimitAnalyzer.addValue(entityExpansionIndex, name, 1); + } + if( fSecurityManager != null && fSecurityManager.isOverLimit(entityExpansionIndex)){ + fSecurityManager.debugPrint(); + fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,"EntityExpansionLimitExceeded", + new Object[]{fSecurityManager.getLimitValueByIndex(entityExpansionIndex)}, XMLErrorReporter.SEVERITY_FATAL_ERROR ); // is there anything better to do than reset the counter? // at least one can envision debugging applications where this might @@ -1342,6 +1348,12 @@ if(fCurrentEntity != null){ //close the reader try{ + if (fLimitAnalyzer != null) { + fLimitAnalyzer.endEntity(XMLSecurityManager.Limit.GENEAL_ENTITY_SIZE_LIMIT, fCurrentEntity.name); + if (fCurrentEntity.name.equals("[xml]")) { + fSecurityManager.debugPrint(); + } + } fCurrentEntity.close(); }catch(IOException ex){ throw new XNIException(ex); @@ -1400,6 +1412,9 @@ fStaxEntityResolver = null; } + fSecurityManager = (XMLSecurityManager)propertyManager.getProperty(SECURITY_MANAGER); + fLimitAnalyzer = fSecurityManager.getLimitAnalyzer(); + // initialize state //fStandalone = false; fEntities.clear(); @@ -1461,6 +1476,8 @@ fStaxEntityResolver = (StaxEntityResolverWrapper)componentManager.getProperty(STAX_ENTITY_RESOLVER, null); fValidationManager = (ValidationManager)componentManager.getProperty(VALIDATION_MANAGER, null); fSecurityManager = (XMLSecurityManager)componentManager.getProperty(SECURITY_MANAGER, null); + fLimitAnalyzer = fSecurityManager.getLimitAnalyzer(); + entityExpansionIndex = fSecurityManager.getIndex(Constants.JDK_ENTITY_EXPANSION_LIMIT); //reset general state reset(); @@ -1474,9 +1491,6 @@ // a class acting as a component manager but not // implementing that interface for whatever reason. public void reset() { - fEntityExpansionLimit = (fSecurityManager != null)? - fSecurityManager.getLimit(XMLSecurityManager.Limit.ENTITY_EXPANSION_LIMIT):0; - // initialize state fStandalone = false; @@ -1608,8 +1622,7 @@ if (suffixLength == Constants.SECURITY_MANAGER_PROPERTY.length() && propertyId.endsWith(Constants.SECURITY_MANAGER_PROPERTY)) { fSecurityManager = (XMLSecurityManager)value; - fEntityExpansionLimit = (fSecurityManager != null)? - fSecurityManager.getLimit(XMLSecurityManager.Limit.ENTITY_EXPANSION_LIMIT):0; + fLimitAnalyzer = fSecurityManager.getLimitAnalyzer(); } } diff -r 00f1d7d220a9 -r aeaabc10209e src/com/sun/org/apache/xerces/internal/impl/XMLNSDocumentScannerImpl.java --- a/src/com/sun/org/apache/xerces/internal/impl/XMLNSDocumentScannerImpl.java Thu Oct 10 16:45:02 2013 +0100 +++ b/src/com/sun/org/apache/xerces/internal/impl/XMLNSDocumentScannerImpl.java Fri Oct 11 11:35:02 2013 +0100 @@ -58,6 +58,7 @@ * @author Neeraj Bajaj, Sun Microsystems * @author Venugopal Rao K, Sun Microsystems * @author Elena Litani, IBM + * @version $Id: XMLNSDocumentScannerImpl.java,v 1.11 2010-11-01 04:39:41 joehw Exp $ */ public class XMLNSDocumentScannerImpl extends XMLDocumentScannerImpl { @@ -251,7 +252,8 @@ do { scanAttribute(fAttributes); - if (fSecurityManager != null && fAttributes.getLength() > fElementAttributeLimit){ + if (fSecurityManager != null && (!fSecurityManager.isNoLimit(fElementAttributeLimit)) && + fAttributes.getLength() > fElementAttributeLimit){ fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN, "ElementAttributeLimit", new Object[]{rawname, new Integer(fAttributes.getLength()) }, diff -r 00f1d7d220a9 -r aeaabc10209e src/com/sun/org/apache/xerces/internal/impl/XMLScanner.java --- a/src/com/sun/org/apache/xerces/internal/impl/XMLScanner.java Thu Oct 10 16:45:02 2013 +0100 +++ b/src/com/sun/org/apache/xerces/internal/impl/XMLScanner.java Fri Oct 11 11:35:02 2013 +0100 @@ -32,6 +32,8 @@ import com.sun.org.apache.xerces.internal.util.XMLChar; import com.sun.org.apache.xerces.internal.util.XMLResourceIdentifierImpl; import com.sun.org.apache.xerces.internal.util.XMLStringBuffer; +import com.sun.org.apache.xerces.internal.utils.XMLLimitAnalyzer; +import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager; import com.sun.org.apache.xerces.internal.xni.Augmentations; import com.sun.org.apache.xerces.internal.xni.XMLAttributes; import com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier; @@ -106,6 +108,9 @@ protected static final String ENTITY_MANAGER = Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_MANAGER_PROPERTY; + /** Property identifier: Security manager. */ + private static final String SECURITY_MANAGER = Constants.SECURITY_MANAGER; + // debugging /** Debug attribute normalization. */ @@ -159,6 +164,12 @@ /** xxx this should be available from EntityManager Entity storage */ protected XMLEntityStorage fEntityStore = null ; + /** Security manager. */ + protected XMLSecurityManager fSecurityManager = null; + + /** Limit analyzer. */ + protected XMLLimitAnalyzer fLimitAnalyzer = null; + // protected data /** event type */ @@ -256,6 +267,7 @@ fSymbolTable = (SymbolTable)componentManager.getProperty(SYMBOL_TABLE); fErrorReporter = (XMLErrorReporter)componentManager.getProperty(ERROR_REPORTER); fEntityManager = (XMLEntityManager)componentManager.getProperty(ENTITY_MANAGER); + fSecurityManager = (XMLSecurityManager)componentManager.getProperty(SECURITY_MANAGER); //this step is extra because we have separated the storage of entity fEntityStore = fEntityManager.getEntityStore() ; @@ -293,6 +305,10 @@ fEntityManager = (XMLEntityManager)value; } } + + if (propertyId.equals(SECURITY_MANAGER)) { + fSecurityManager = (XMLSecurityManager)value; + } /*else if(propertyId.equals(Constants.STAX_PROPERTIES)){ fStaxProperties = (HashMap)value; //TODO::discuss with neeraj what are his thoughts on passing properties. @@ -352,6 +368,8 @@ fEntityManager = (XMLEntityManager)propertyManager.getProperty(ENTITY_MANAGER); fEntityStore = fEntityManager.getEntityStore() ; fEntityScanner = (XMLEntityScanner)fEntityManager.getEntityScanner() ; + fSecurityManager = (XMLSecurityManager)propertyManager.getProperty(SECURITY_MANAGER); + //fEntityManager.reset(); // DTD preparsing defaults: fValidation = false; @@ -510,8 +528,9 @@ sawSpace = fEntityScanner.skipSpaces(); } // restore original literal value - if(currLiteral) + if(currLiteral) { currEnt.literal = true; + } // REVISIT: should we remove this error reporting? if (scanningTextDecl && state != STATE_DONE) { reportFatalError("MorePseudoAttributes", null); diff -r 00f1d7d220a9 -r aeaabc10209e src/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages.properties --- a/src/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages.properties Thu Oct 10 16:45:02 2013 +0100 +++ b/src/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages.properties Fri Oct 11 11:35:02 2013 +0100 @@ -290,8 +290,10 @@ InvalidCharInLiteral=InvalidCharInLiteral -#Application can set the limit of number of entities that should be expanded by the parser. -EntityExpansionLimitExceeded=The parser has encountered more than \"{0}\" entity expansions in this document; this is the limit imposed by the application. +# Implementation limits + EntityExpansionLimitExceeded=JAXP00010001: The parser has encountered more than \"{0}\" entity expansions in this document; this is the limit imposed by the JDK. + ElementAttributeLimit=JAXP00010002: Element \"{0}\" has more than \"{1}\" attributes, \"{1}\" is the limit imposed by the JDK. + MaxEntitySizeLimit=JAXP00010003: The length of entity \"{0}\" is \"{1}\" that exceeds the \"{2}\" limit set by \"{3}\". + TotalEntitySizeLimit=JAXP00010004: The accumulated size \"{0}\" of entities exceeded the \"{1}\" limit set by \"{2}\". + MaxXMLNameLimit=JAXP00010005: The name \"{0}\" exceeded the \"{1}\" limit set by \"{2}\". -# Application can set the limit of number of attributes of entity that should be expanded by the parser. -ElementAttributeLimit= Element \"{0}\" has more than \"{1}\" attributes, \"{1}\" is the limit imposed by the application. diff -r 00f1d7d220a9 -r aeaabc10209e src/com/sun/org/apache/xerces/internal/impl/xs/models/CMNodeFactory.java --- a/src/com/sun/org/apache/xerces/internal/impl/xs/models/CMNodeFactory.java Thu Oct 10 16:45:02 2013 +0100 +++ b/src/com/sun/org/apache/xerces/internal/impl/xs/models/CMNodeFactory.java Fri Oct 11 11:35:02 2013 +0100 @@ -109,7 +109,8 @@ } public void nodeCountCheck(){ - if( fSecurityManager != null && nodeCount++ > maxNodeLimit){ + if( fSecurityManager != null && !fSecurityManager.isNoLimit(maxNodeLimit) && + nodeCount++ > maxNodeLimit){ if(DEBUG){ System.out.println("nodeCount = " + nodeCount ) ; System.out.println("nodeLimit = " + maxNodeLimit ) ; diff -r 00f1d7d220a9 -r aeaabc10209e src/com/sun/org/apache/xerces/internal/jaxp/DocumentBuilderImpl.java --- a/src/com/sun/org/apache/xerces/internal/jaxp/DocumentBuilderImpl.java Thu Oct 10 16:45:02 2013 +0100 +++ b/src/com/sun/org/apache/xerces/internal/jaxp/DocumentBuilderImpl.java Fri Oct 11 11:35:02 2013 +0100 @@ -109,6 +109,8 @@ /** Initial EntityResolver */ private final EntityResolver fInitEntityResolver; + private XMLSecurityManager fSecurityManager; + DocumentBuilderImpl(DocumentBuilderFactoryImpl dbf, Hashtable dbfAttrs, Hashtable features) throws SAXNotRecognizedException, SAXNotSupportedException { this(dbf, dbfAttrs, features, false); @@ -152,10 +154,8 @@ domParser.setFeature(XINCLUDE_FEATURE, true); } - // If the secure processing feature is on set a security manager. - if (secureProcessing) { - domParser.setProperty(SECURITY_MANAGER, new XMLSecurityManager()); - } + fSecurityManager = new XMLSecurityManager(secureProcessing); + domParser.setProperty(SECURITY_MANAGER, fSecurityManager); this.grammar = dbf.getSchema(); if (grammar != null) { @@ -211,9 +211,9 @@ String feature = (String) entry.getKey(); boolean value = ((Boolean) entry.getValue()).booleanValue(); domParser.setFeature(feature, value); - } } } + } /** * Set any DocumentBuilderFactory attributes of our underlying DOMParser diff -r 00f1d7d220a9 -r aeaabc10209e src/com/sun/org/apache/xerces/internal/jaxp/SAXParserImpl.java --- a/src/com/sun/org/apache/xerces/internal/jaxp/SAXParserImpl.java Thu Oct 10 16:45:02 2013 +0100 +++ b/src/com/sun/org/apache/xerces/internal/jaxp/SAXParserImpl.java Fri Oct 11 11:35:02 2013 +0100 @@ -107,6 +107,8 @@ /** Initial EntityResolver */ private final EntityResolver fInitEntityResolver; + private final XMLSecurityManager fSecurityManager; + /** * Create a SAX parser with the associated features * @param features Hashtable of SAX features, may be null @@ -123,8 +125,9 @@ SAXParserImpl(SAXParserFactoryImpl spf, Hashtable features, boolean secureProcessing) throws SAXException { + fSecurityManager = new XMLSecurityManager(secureProcessing); // Instantiate a SAXParser directly and not through SAX so that we use the right ClassLoader - xmlReader = new JAXPSAXParser(this); + xmlReader = new JAXPSAXParser(this, fSecurityManager); // JAXP "namespaceAware" == SAX Namespaces feature // Note: there is a compatibility problem here with default values: @@ -143,10 +146,7 @@ xmlReader.setFeature0(XINCLUDE_FEATURE, true); } - // If the secure processing feature is on set a security manager. - if (secureProcessing) { - xmlReader.setProperty0(SECURITY_MANAGER, new XMLSecurityManager()); - } + xmlReader.setProperty0(SECURITY_MANAGER, fSecurityManager); // Set application's features, followed by validation features. setFeatures(features); @@ -368,14 +368,28 @@ private final HashMap fInitFeatures = new HashMap(); private final HashMap fInitProperties = new HashMap(); private final SAXParserImpl fSAXParser; + private XMLSecurityManager fSecurityManager; public JAXPSAXParser() { - this(null); + this(null, null); } - JAXPSAXParser(SAXParserImpl saxParser) { + JAXPSAXParser(SAXParserImpl saxParser, XMLSecurityManager securityManager) { super(); fSAXParser = saxParser; + fSecurityManager = securityManager; + /** + * This class may be used directly. So initialize the security manager if + * it is null. + */ + if (fSecurityManager == null) { + fSecurityManager = new XMLSecurityManager(true); + try { + super.setProperty(SECURITY_MANAGER, fSecurityManager); + } catch (Exception ex) { + //shall not happen + } + } } /** @@ -391,7 +405,8 @@ } if (name.equals(XMLConstants.FEATURE_SECURE_PROCESSING)) { try { - setProperty(SECURITY_MANAGER, value ? new XMLSecurityManager() : null); + fSecurityManager.setSecureProcessing(value); + setProperty(SECURITY_MANAGER, fSecurityManager); } catch (SAXNotRecognizedException exc) { // If the property is not supported @@ -427,13 +442,7 @@ throw new NullPointerException(); } if (name.equals(XMLConstants.FEATURE_SECURE_PROCESSING)) { - try { - return (super.getProperty(SECURITY_MANAGER) != null); - } - // If the property is not supported the value must be false. - catch (SAXException exc) { - return false; - } + return fSecurityManager.isSecureProcessing(); } return super.getFeature(name); } diff -r 00f1d7d220a9 -r aeaabc10209e src/com/sun/org/apache/xerces/internal/jaxp/validation/AbstractXMLSchema.java --- a/src/com/sun/org/apache/xerces/internal/jaxp/validation/AbstractXMLSchema.java Thu Oct 10 16:45:02 2013 +0100 +++ b/src/com/sun/org/apache/xerces/internal/jaxp/validation/AbstractXMLSchema.java Fri Oct 11 11:35:02 2013 +0100 @@ -41,8 +41,15 @@ */ private final HashMap fFeatures; + /** + * Map containing the initial values of properties for + * validators created using this grammar pool container. + */ + private final HashMap fProperties; + public AbstractXMLSchema() { fFeatures = new HashMap(); + fProperties = new HashMap(); } /* @@ -84,4 +91,20 @@ fFeatures.put(featureId, state ? Boolean.TRUE : Boolean.FALSE); } + /** + * Returns the initial value of a property for validators created + * using this grammar pool container or null if the validators + * should use the default value. + */ + public final Object getProperty(String propertyId) { + return fProperties.get(propertyId); + } + + /* + * Set a property on the schema + */ + public final void setProperty(String propertyId, Object state) { + fProperties.put(propertyId, state); + } + } // AbstractXMLSchema diff -r 00f1d7d220a9 -r aeaabc10209e src/com/sun/org/apache/xerces/internal/jaxp/validation/StAXValidatorHelper.java --- a/src/com/sun/org/apache/xerces/internal/jaxp/validation/StAXValidatorHelper.java Thu Oct 10 16:45:02 2013 +0100 +++ b/src/com/sun/org/apache/xerces/internal/jaxp/validation/StAXValidatorHelper.java Fri Oct 11 11:35:02 2013 +0100 @@ -26,6 +26,7 @@ package com.sun.org.apache.xerces.internal.jaxp.validation; import com.sun.org.apache.xerces.internal.impl.Constants; +import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager; import java.io.IOException; import javax.xml.transform.Result; @@ -73,6 +74,19 @@ SAXTransformerFactory tf = fComponentManager.getFeature(Constants.ORACLE_FEATURE_SERVICE_MECHANISM) ? (SAXTransformerFactory)SAXTransformerFactory.newInstance() : (SAXTransformerFactory) TransformerFactory.newInstance(DEFAULT_TRANSFORMER_IMPL, StAXValidatorHelper.class.getClassLoader()); + XMLSecurityManager securityManager = (XMLSecurityManager)fComponentManager.getProperty(Constants.SECURITY_MANAGER); + if (securityManager != null) { + for (XMLSecurityManager.Limit limit : XMLSecurityManager.Limit.values()) { + if (securityManager.isSet(limit.ordinal())){ + tf.setAttribute(limit.apiProperty(), + securityManager.getLimitValueAsString(limit)); + } + } + if (securityManager.printEntityCountInfo()) { + tf.setAttribute(Constants.JDK_ENTITY_COUNT_INFO, "yes"); + } + } + identityTransformer1 = tf.newTransformer(); identityTransformer2 = tf.newTransformerHandler(); } catch (TransformerConfigurationException e) { diff -r 00f1d7d220a9 -r aeaabc10209e src/com/sun/org/apache/xerces/internal/jaxp/validation/StreamValidatorHelper.java --- a/src/com/sun/org/apache/xerces/internal/jaxp/validation/StreamValidatorHelper.java Thu Oct 10 16:45:02 2013 +0100 +++ b/src/com/sun/org/apache/xerces/internal/jaxp/validation/StreamValidatorHelper.java Fri Oct 11 11:35:02 2013 +0100 @@ -187,6 +187,8 @@ config.setDocumentHandler(fSchemaValidator); config.setDTDHandler(null); config.setDTDContentModelHandler(null); + config.setProperty(Constants.SECURITY_MANAGER, + fComponentManager.getProperty(Constants.SECURITY_MANAGER)); fConfiguration = new SoftReference(config); return config; } diff -r 00f1d7d220a9 -r aeaabc10209e src/com/sun/org/apache/xerces/internal/jaxp/validation/XMLSchemaFactory.java --- a/src/com/sun/org/apache/xerces/internal/jaxp/validation/XMLSchemaFactory.java Thu Oct 10 16:45:02 2013 +0100 +++ b/src/com/sun/org/apache/xerces/internal/jaxp/validation/XMLSchemaFactory.java Fri Oct 11 11:35:02 2013 +0100 @@ -101,7 +101,7 @@ /** The ErrorHandlerWrapper */ private ErrorHandlerWrapper fErrorHandlerWrapper; - /** The XMLSecurityManager. */ + /** The SecurityManager. */ private XMLSecurityManager fSecurityManager; /** The container for the real grammar pool. */ @@ -130,7 +130,7 @@ fXMLSchemaLoader.setErrorHandler(fErrorHandlerWrapper); // Enable secure processing feature by default - fSecurityManager = new XMLSecurityManager(); + fSecurityManager = new XMLSecurityManager(true); fXMLSchemaLoader.setProperty(SECURITY_MANAGER, fSecurityManager); } @@ -319,7 +319,7 @@ "property-not-supported", new Object [] {name})); } try { - return fXMLSchemaLoader.getProperty(name); + return fXMLSchemaLoader.getProperty(name); } catch (XMLConfigurationException e) { String identifier = e.getIdentifier(); @@ -348,7 +348,9 @@ SAXMessageFormatter.formatMessage(null, "jaxp-secureprocessing-feature", null)); } + fSecurityManager = value ? new XMLSecurityManager() : null; + fSecurityManager.setSecureProcessing(value); fXMLSchemaLoader.setProperty(SECURITY_MANAGER, fSecurityManager); return; } else if (name.equals(Constants.ORACLE_FEATURE_SERVICE_MECHANISM)) { diff -r 00f1d7d220a9 -r aeaabc10209e src/com/sun/org/apache/xerces/internal/jaxp/validation/XMLSchemaValidatorComponentManager.java --- a/src/com/sun/org/apache/xerces/internal/jaxp/validation/XMLSchemaValidatorComponentManager.java Thu Oct 10 16:45:02 2013 +0100 +++ b/src/com/sun/org/apache/xerces/internal/jaxp/validation/XMLSchemaValidatorComponentManager.java Fri Oct 11 11:35:02 2013 +0100 @@ -176,7 +176,7 @@ private final HashMap fInitProperties = new HashMap(); /** Stores the initial security manager. */ - private final XMLSecurityManager fInitSecurityManager; + private XMLSecurityManager fInitSecurityManager; // // User Objects @@ -213,12 +213,6 @@ fComponents.put(ENTITY_RESOLVER, null); fComponents.put(ERROR_HANDLER, null); - if (System.getSecurityManager() != null) { - _isSecureMode = true; - setProperty(SECURITY_MANAGER, new XMLSecurityManager()); - } else { - fComponents.put(SECURITY_MANAGER, null); - } fComponents.put(SYMBOL_TABLE, new SymbolTable()); // setup grammar pool @@ -233,15 +227,21 @@ addRecognizedParamsAndSetDefaults(fErrorReporter, grammarContainer); addRecognizedParamsAndSetDefaults(fSchemaValidator, grammarContainer); - // if the secure processing feature is set to true, add a security manager to the configuration - Boolean secureProcessing = grammarContainer.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING); - if (Boolean.TRUE.equals(secureProcessing)) { - fInitSecurityManager = new XMLSecurityManager(); + boolean secureProcessing = grammarContainer.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING); + if (System.getSecurityManager() != null) { + _isSecureMode = true; + secureProcessing = true; } - else { - fInitSecurityManager = null; + + fInitSecurityManager = (XMLSecurityManager) + grammarContainer.getProperty(SECURITY_MANAGER); + if (fInitSecurityManager != null ) { + fInitSecurityManager.setSecureProcessing(secureProcessing); + } else { + fInitSecurityManager = new XMLSecurityManager(secureProcessing); } - fComponents.put(SECURITY_MANAGER, fInitSecurityManager); + + setProperty(SECURITY_MANAGER, fInitSecurityManager); } @@ -269,7 +269,7 @@ return FeatureState.is(fUseGrammarPoolOnly); } else if (XMLConstants.FEATURE_SECURE_PROCESSING.equals(featureId)) { - return FeatureState.is(getProperty(SECURITY_MANAGER) != null); + return FeatureState.is(fInitSecurityManager.isSecureProcessing()); } else if (SCHEMA_ELEMENT_DEFAULT.equals(featureId)) { return FeatureState.is(true); //pre-condition: VALIDATION and SCHEMA_VALIDATION are always true @@ -299,7 +299,8 @@ if (_isSecureMode && !value) { throw new XMLConfigurationException(Status.NOT_ALLOWED, XMLConstants.FEATURE_SECURE_PROCESSING); } - setProperty(SECURITY_MANAGER, value ? new XMLSecurityManager() : null); + fInitSecurityManager.setSecureProcessing(value); + setProperty(SECURITY_MANAGER, fInitSecurityManager); return; } fConfigUpdated = true; @@ -369,10 +370,12 @@ fComponents.put(propertyId, value); return; } - if (!fInitProperties.containsKey(propertyId)) { - fInitProperties.put(propertyId, super.getProperty(propertyId)); - } - super.setProperty(propertyId, value); + + //fall back to the existing property manager + if (!fInitProperties.containsKey(propertyId)) { + fInitProperties.put(propertyId, super.getProperty(propertyId)); + } + super.setProperty(propertyId, value); } /** diff -r 00f1d7d220a9 -r aeaabc10209e src/com/sun/org/apache/xerces/internal/jaxp/validation/XSGrammarPoolContainer.java --- a/src/com/sun/org/apache/xerces/internal/jaxp/validation/XSGrammarPoolContainer.java Thu Oct 10 16:45:02 2013 +0100 +++ b/src/com/sun/org/apache/xerces/internal/jaxp/validation/XSGrammarPoolContainer.java Fri Oct 11 11:35:02 2013 +0100 @@ -55,4 +55,11 @@ */ public Boolean getFeature(String featureId); + /** + * Returns the initial value of a property for validators created + * using this grammar pool container or null if the validators + * should use the default value. + */ + public Object getProperty(String propertyId); + } diff -r 00f1d7d220a9 -r aeaabc10209e src/com/sun/org/apache/xerces/internal/parsers/SAXParser.java --- a/src/com/sun/org/apache/xerces/internal/parsers/SAXParser.java Thu Oct 10 16:45:02 2013 +0100 +++ b/src/com/sun/org/apache/xerces/internal/parsers/SAXParser.java Fri Oct 11 11:35:02 2013 +0100 @@ -22,6 +22,7 @@ import com.sun.org.apache.xerces.internal.impl.Constants; import com.sun.org.apache.xerces.internal.util.SymbolTable; +import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager; import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarPool; import com.sun.org.apache.xerces.internal.xni.parser.XMLParserConfiguration; @@ -73,6 +74,7 @@ XMLGRAMMAR_POOL, }; + XMLSecurityManager securityManager; // // Constructors // diff -r 00f1d7d220a9 -r aeaabc10209e src/com/sun/org/apache/xerces/internal/parsers/SecurityConfiguration.java --- a/src/com/sun/org/apache/xerces/internal/parsers/SecurityConfiguration.java Thu Oct 10 16:45:02 2013 +0100 +++ b/src/com/sun/org/apache/xerces/internal/parsers/SecurityConfiguration.java Fri Oct 11 11:35:02 2013 +0100 @@ -44,6 +44,7 @@ * * @author Neil Graham, IBM * + * @version $Id: SecurityConfiguration.java,v 1.6 2010-11-01 04:40:09 joehw Exp $ */ public class SecurityConfiguration extends XIncludeAwareParserConfiguration { @@ -106,8 +107,8 @@ XMLComponentManager parentSettings) { super(symbolTable, grammarPool, parentSettings); - // create the XMLSecurityManager property: - setProperty(SECURITY_MANAGER_PROPERTY, new XMLSecurityManager()); + // create the SecurityManager property: + setProperty(SECURITY_MANAGER_PROPERTY, new XMLSecurityManager(true)); } // (SymbolTable,XMLGrammarPool) } // class SecurityConfiguration diff -r 00f1d7d220a9 -r aeaabc10209e src/com/sun/org/apache/xerces/internal/parsers/XML11Configuration.java --- a/src/com/sun/org/apache/xerces/internal/parsers/XML11Configuration.java Thu Oct 10 16:45:02 2013 +0100 +++ b/src/com/sun/org/apache/xerces/internal/parsers/XML11Configuration.java Fri Oct 11 11:35:02 2013 +0100 @@ -20,6 +20,12 @@ package com.sun.org.apache.xerces.internal.parsers; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Locale; +import javax.xml.XMLConstants; + import com.sun.org.apache.xerces.internal.impl.Constants; import com.sun.org.apache.xerces.internal.impl.XML11DTDScannerImpl; import com.sun.org.apache.xerces.internal.impl.XML11DocumentScannerImpl; @@ -47,6 +53,7 @@ import com.sun.org.apache.xerces.internal.util.PropertyState; import com.sun.org.apache.xerces.internal.util.Status; import com.sun.org.apache.xerces.internal.util.SymbolTable; +import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager; import com.sun.org.apache.xerces.internal.xni.XMLDTDContentModelHandler; import com.sun.org.apache.xerces.internal.xni.XMLDTDHandler; import com.sun.org.apache.xerces.internal.xni.XMLDocumentHandler; @@ -63,11 +70,6 @@ import com.sun.org.apache.xerces.internal.xni.parser.XMLErrorHandler; import com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource; import com.sun.org.apache.xerces.internal.xni.parser.XMLPullParserConfiguration; -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Locale; -import javax.xml.XMLConstants; /** * This class is the configuration used to parse XML 1.0 and XML 1.1 documents. @@ -274,6 +276,9 @@ protected static final String SCHEMA_DV_FACTORY = Constants.XERCES_PROPERTY_PREFIX + Constants.SCHEMA_DV_FACTORY_PROPERTY; + /** Property identifier: Security manager. */ + private static final String SECURITY_MANAGER = Constants.SECURITY_MANAGER; + // debugging /** Set to true and recompile to print exception stack trace. */ @@ -283,33 +288,33 @@ // Data // - protected SymbolTable fSymbolTable; + protected SymbolTable fSymbolTable; protected XMLInputSource fInputSource; protected ValidationManager fValidationManager; - protected XMLVersionDetector fVersionDetector; + protected XMLVersionDetector fVersionDetector; protected XMLLocator fLocator; - protected Locale fLocale; + protected Locale fLocale; - /** XML 1.0 Components. */ - protected ArrayList fComponents; + /** XML 1.0 Components. */ + protected ArrayList fComponents; - /** XML 1.1. Components. */ - protected ArrayList fXML11Components = null; + /** XML 1.1. Components. */ + protected ArrayList fXML11Components = null; - /** Common components: XMLEntityManager, XMLErrorReporter, XMLSchemaValidator */ - protected ArrayList fCommonComponents = null; + /** Common components: XMLEntityManager, XMLErrorReporter, XMLSchemaValidator */ + protected ArrayList fCommonComponents = null; - /** The document handler. */ - protected XMLDocumentHandler fDocumentHandler; + /** The document handler. */ + protected XMLDocumentHandler fDocumentHandler; - /** The DTD handler. */ - protected XMLDTDHandler fDTDHandler; + /** The DTD handler. */ + protected XMLDTDHandler fDTDHandler; - /** The DTD content model handler. */ - protected XMLDTDContentModelHandler fDTDContentModelHandler; + /** The DTD content model handler. */ + protected XMLDTDContentModelHandler fDTDContentModelHandler; - /** Last component in the document pipeline */ - protected XMLDocumentSource fLastComponent; + /** Last component in the document pipeline */ + protected XMLDocumentSource fLastComponent; /** * True if a parse is in progress. This state is needed because @@ -443,26 +448,26 @@ XMLGrammarPool grammarPool, XMLComponentManager parentSettings) { - super(parentSettings); + super(parentSettings); - // create a vector to hold all the components in use - // XML 1.0 specialized components - fComponents = new ArrayList(); - // XML 1.1 specialized components - fXML11Components = new ArrayList(); - // Common components for XML 1.1. and XML 1.0 - fCommonComponents = new ArrayList(); + // create a vector to hold all the components in use + // XML 1.0 specialized components + fComponents = new ArrayList(); + // XML 1.1 specialized components + fXML11Components = new ArrayList(); + // Common components for XML 1.1. and XML 1.0 + fCommonComponents = new ArrayList(); - // create table for features and properties - fFeatures = new HashMap(); - fProperties = new HashMap(); + // create table for features and properties + fFeatures = new HashMap(); + fProperties = new HashMap(); // add default recognized features final String[] recognizedFeatures = { CONTINUE_AFTER_FATAL_ERROR, LOAD_EXTERNAL_DTD, // from XMLDTDScannerImpl - VALIDATION, - NAMESPACES, + VALIDATION, + NAMESPACES, NORMALIZE_DATA, SCHEMA_ELEMENT_DEFAULT, SCHEMA_AUGMENT_PSVI, GENERATE_SYNTHETIC_ANNOTATIONS, VALIDATE_ANNOTATIONS, HONOUR_ALL_SCHEMALOCATIONS, NAMESPACE_GROWTH, @@ -527,6 +532,7 @@ SCHEMA_NONS_LOCATION, LOCALE, SCHEMA_DV_FACTORY, + SECURITY_MANAGER, }; addRecognizedProperties(recognizedProperties); @@ -574,6 +580,8 @@ fVersionDetector = new XMLVersionDetector(); + fProperties.put(SECURITY_MANAGER, new XMLSecurityManager(true)); + // add message formatters if (fErrorReporter.getMessageFormatter(XMLMessageFormatter.XML_DOMAIN) == null) { XMLMessageFormatter xmft = new XMLMessageFormatter(); diff -r 00f1d7d220a9 -r aeaabc10209e src/com/sun/org/apache/xerces/internal/utils/SecuritySupport.java --- a/src/com/sun/org/apache/xerces/internal/utils/SecuritySupport.java Thu Oct 10 16:45:02 2013 +0100 +++ b/src/com/sun/org/apache/xerces/internal/utils/SecuritySupport.java Fri Oct 11 11:35:02 2013 +0100 @@ -23,6 +23,7 @@ import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; +import java.io.IOException; import java.io.InputStream; import java.security.AccessController; @@ -31,6 +32,7 @@ import java.security.PrivilegedExceptionAction; import java.util.Locale; import java.util.MissingResourceException; +import java.util.Properties; import java.util.PropertyResourceBundle; import java.util.ResourceBundle; @@ -195,5 +197,55 @@ })).longValue(); } + /** + * Read from $java.home/lib/jaxp.properties for the specified property + * The program + * + * @param propertyId the Id of the property + * @return the value of the property + */ + static String readJAXPProperty(String propertyId) { + String value = null; + InputStream is = null; + try { + if (firstTime) { + synchronized (cacheProps) { + if (firstTime) { + String configFile = getSystemProperty("java.home") + File.separator + + "lib" + File.separator + "jaxp.properties"; + File f = new File(configFile); + if (getFileExists(f)) { + is = getFileInputStream(f); + cacheProps.load(is); + } + firstTime = false; + } + } + } + value = cacheProps.getProperty(propertyId); + + } + catch (Exception ex) {} + finally { + if (is != null) { + try { + is.close(); + } catch (IOException ex) {} + } + } + + return value; + } + + /** + * Cache for properties in java.home/lib/jaxp.properties + */ + static final Properties cacheProps = new Properties(); + + /** + * Flag indicating if the program has tried reading java.home/lib/jaxp.properties + */ + static volatile boolean firstTime = true; + private SecuritySupport () {} } diff -r 00f1d7d220a9 -r aeaabc10209e src/com/sun/org/apache/xerces/internal/utils/XMLLimitAnalyzer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/com/sun/org/apache/xerces/internal/utils/XMLLimitAnalyzer.java Fri Oct 11 11:35:02 2013 +0100 @@ -0,0 +1,236 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common Development + * and Distribution License("CDDL") (collectively, the "License"). You + * may not use this file except in compliance with the License. You can + * obtain a copy of the License at + * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html + * or packager/legal/LICENSE.txt. See the License for the specific + * language governing permissions and limitations under the License. + * + * When distributing the software, include this License Header Notice in each + * file and include the License file at packager/legal/LICENSE.txt. + * + * GPL Classpath Exception: + * Oracle designates this particular file as subject to the "Classpath" + * exception as provided by Oracle in the GPL Version 2 section of the License + * file that accompanied this code. + * + * Modifications: + * If applicable, add the following below the License Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyright [year] [name of copyright owner]" + * + * Contributor(s): + * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to + * its licensees as provided above. However, if you add GPL Version 2 code + * and therefore, elected the GPL Version 2 license, then the option applies + * only if the new code is made subject to such option by the copyright + * holder. + */ +package com.sun.org.apache.xerces.internal.utils; + +import com.sun.org.apache.xerces.internal.impl.Constants; +import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager.Limit; +import java.util.Formatter; +import java.util.HashMap; +import java.util.Map; + +/** + * A helper for analyzing entity expansion limits + * + * @author Joe Wang Oracle Corp. + * + */ +public final class XMLLimitAnalyzer { + + /** + * Map old property names with the new ones + */ + public static enum NameMap { + ENTITY_EXPANSION_LIMIT(Constants.SP_ENTITY_EXPANSION_LIMIT, Constants.ENTITY_EXPANSION_LIMIT), + MAX_OCCUR_NODE_LIMIT(Constants.SP_MAX_OCCUR_LIMIT, Constants.MAX_OCCUR_LIMIT), + ELEMENT_ATTRIBUTE_LIMIT(Constants.SP_ELEMENT_ATTRIBUTE_LIMIT, Constants.ELEMENT_ATTRIBUTE_LIMIT); + + final String newName; + final String oldName; + + NameMap(String newName, String oldName) { + this.newName = newName; + this.oldName = oldName; + } + + String getOldName(String newName) { + if (newName.equals(this.newName)) { + return oldName; + } + return null; + } + } + + private XMLSecurityManager securityManager; + /** + * Max value accumulated for each property + */ + private final int[] values; + /** + * Names of the entities corresponding to their max values + */ + private final String[] names; + /** + * Total value of accumulated entities + */ + private final int[] totalValue; + + /** + * Maintain values of the top 10 elements in the process of parsing + */ + private final Map[] caches; + + private String entityStart, entityEnd; + /** + * Default constructor. Establishes default values for known security + * vulnerabilities. + */ + public XMLLimitAnalyzer(XMLSecurityManager securityManager) { + this.securityManager = securityManager; + values = new int[Limit.values().length]; + totalValue = new int[Limit.values().length]; + names = new String[Limit.values().length]; + caches = new Map[Limit.values().length]; + } + + /** + * Add the value to the current max count for the specified property + * To find the max value of all entities, set no limit + * + * @param limit the type of the property + * @param entityName the name of the entity + * @param value the value of the entity + */ + public void addValue(Limit limit, String entityName, int value) { + addValue(limit.ordinal(), entityName, value); + } + + /** + * Add the value to the current count by the index of the property + * @param index the index of the property + * @param entityName the name of the entity + * @param value the value of the entity + */ + public void addValue(int index, String entityName, int value) { + if (index == Limit.ENTITY_EXPANSION_LIMIT.ordinal() || + index == Limit.MAX_OCCUR_NODE_LIMIT.ordinal() || + index == Limit.ELEMENT_ATTRIBUTE_LIMIT.ordinal()) { + totalValue[index] += value; + return; + } + + Map cache; + if (caches[index] == null) { + cache = new HashMap(10); + caches[index] = cache; + } else { + cache = caches[index]; + } + + int accumulatedValue = value; + if (cache.containsKey(entityName)) { + accumulatedValue += cache.get(entityName).intValue(); + cache.put(entityName, Integer.valueOf(accumulatedValue)); + } else { + cache.put(entityName, Integer.valueOf(value)); + } + + if (accumulatedValue > values[index]) { + values[index] = accumulatedValue; + names[index] = entityName; + } + + + if (index == Limit.GENEAL_ENTITY_SIZE_LIMIT.ordinal() || + index == Limit.PARAMETER_ENTITY_SIZE_LIMIT.ordinal()) { + totalValue[Limit.TOTAL_ENTITY_SIZE_LIMIT.ordinal()] += value; + } + } + + /** + * Return the value of the current max count for the specified property + * + * @param limit the property + * @return the value of the property + */ + public int getValue(Limit limit) { + return values[limit.ordinal()]; + } + + public int getValue(int index) { + return values[index]; + } + /** + * Return the total value accumulated so far + * + * @param limit the property + * @return the accumulated value of the property + */ + public int getTotalValue(Limit limit) { + return totalValue[limit.ordinal()]; + } + + public int getTotalValue(int index) { + return totalValue[index]; + } + /** + * Return the current max value (count or length) by the index of a property + * @param index the index of a property + * @return count of a property + */ + public int getValueByIndex(int index) { + return values[index]; + } + + public void startEntity(String name) { + entityStart = name; + } + + public boolean isTracking(String name) { + return entityStart.equals(name); + } + /** + * Stop tracking the entity + * @param limit the limit property + * @param name the name of an entity + */ + public void endEntity(Limit limit, String name) { + entityStart = ""; + Map cache = caches[limit.ordinal()]; + if (cache != null) { + cache.remove(name); + } + } + + public void debugPrint() { + Formatter formatter = new Formatter(); + System.out.println(formatter.format("%30s %15s %15s %15s %30s", + "Property","Limit","Total size","Size","Entity Name")); + + for (Limit limit : Limit.values()) { + formatter = new Formatter(); + System.out.println(formatter.format("%30s %15d %15d %15d %30s", + limit.name(), + securityManager.getLimit(limit), + totalValue[limit.ordinal()], + values[limit.ordinal()], + names[limit.ordinal()])); + } + } +} diff -r 00f1d7d220a9 -r aeaabc10209e src/com/sun/org/apache/xerces/internal/utils/XMLSecurityManager.java --- a/src/com/sun/org/apache/xerces/internal/utils/XMLSecurityManager.java Thu Oct 10 16:45:02 2013 +0100 +++ b/src/com/sun/org/apache/xerces/internal/utils/XMLSecurityManager.java Fri Oct 11 11:35:02 2013 +0100 @@ -40,108 +40,482 @@ */ public static enum State { //this order reflects the overriding order - DEFAULT, FSP, JAXPDOTPROPERTIES, SYSTEMPROPERTY, APIPROPERTY + + DEFAULT("default"), FSP("FEATURE_SECURE_PROCESSING"), + JAXPDOTPROPERTIES("jaxp.properties"), SYSTEMPROPERTY("system property"), + APIPROPERTY("property"); + + final String literal; + State(String literal) { + this.literal = literal; + } + + String literal() { + return literal; + } } /** * Limits managed by the security manager */ public static enum Limit { - ENTITY_EXPANSION_LIMIT(64000), - MAX_OCCUR_NODE_LIMIT(5000), - ELEMENT_ATTRIBUTE_LIMIT(10000); + + ENTITY_EXPANSION_LIMIT(Constants.JDK_ENTITY_EXPANSION_LIMIT, Constants.SP_ENTITY_EXPANSION_LIMIT, 0, 64000), + MAX_OCCUR_NODE_LIMIT(Constants.JDK_MAX_OCCUR_LIMIT, Constants.SP_MAX_OCCUR_LIMIT, 0, 5000), + ELEMENT_ATTRIBUTE_LIMIT(Constants.JDK_ELEMENT_ATTRIBUTE_LIMIT, Constants.SP_ELEMENT_ATTRIBUTE_LIMIT, 0, 10000), + TOTAL_ENTITY_SIZE_LIMIT(Constants.JDK_TOTAL_ENTITY_SIZE_LIMIT, Constants.SP_TOTAL_ENTITY_SIZE_LIMIT, 0, 50000000), + GENEAL_ENTITY_SIZE_LIMIT(Constants.JDK_GENEAL_ENTITY_SIZE_LIMIT, Constants.SP_GENEAL_ENTITY_SIZE_LIMIT, 0, 0), + PARAMETER_ENTITY_SIZE_LIMIT(Constants.JDK_PARAMETER_ENTITY_SIZE_LIMIT, Constants.SP_PARAMETER_ENTITY_SIZE_LIMIT, 0, 1000000); + + final String apiProperty; + final String systemProperty; + final int defaultValue; + final int secureValue; - final int defaultValue; + Limit(String apiProperty, String systemProperty, int value, int secureValue) { + this.apiProperty = apiProperty; + this.systemProperty = systemProperty; + this.defaultValue = value; + this.secureValue = secureValue; + } + + public boolean equalsAPIPropertyName(String propertyName) { + return (propertyName == null) ? false : apiProperty.equals(propertyName); + } - Limit(int value) { - this.defaultValue = value; + public boolean equalsSystemPropertyName(String propertyName) { + return (propertyName == null) ? false : systemProperty.equals(propertyName); + } + + public String apiProperty() { + return apiProperty; + } + + String systemProperty() { + return systemProperty; } int defaultValue() { return defaultValue; } + + int secureValue() { + return secureValue; + } } /** - * Values of the limits as defined in enum Limit + * Map old property names with the new ones */ - private final int[] limits; + public static enum NameMap { + + ENTITY_EXPANSION_LIMIT(Constants.SP_ENTITY_EXPANSION_LIMIT, Constants.ENTITY_EXPANSION_LIMIT), + MAX_OCCUR_NODE_LIMIT(Constants.SP_MAX_OCCUR_LIMIT, Constants.MAX_OCCUR_LIMIT), + ELEMENT_ATTRIBUTE_LIMIT(Constants.SP_ELEMENT_ATTRIBUTE_LIMIT, Constants.ELEMENT_ATTRIBUTE_LIMIT); + final String newName; + final String oldName; + + NameMap(String newName, String oldName) { + this.newName = newName; + this.oldName = oldName; + } + + String getOldName(String newName) { + if (newName.equals(this.newName)) { + return oldName; + } + return null; + } + } + private static final int NO_LIMIT = 0; /** - * States of the settings for each limit in limits above + * Values of the properties + */ + private final int[] values; + /** + * States of the settings for each property + */ + private State[] states; + /** + * Flag indicating if secure processing is set */ - private State[] states = {State.DEFAULT, State.DEFAULT, State.DEFAULT, State.DEFAULT}; + boolean secureProcessing; + + /** + * States that determine if properties are set explicitly + */ + private boolean[] isSet; + + + private XMLLimitAnalyzer limitAnalyzer; + /** + * Index of the special entityCountInfo property + */ + private int indexEntityCountInfo = 10000; + private String printEntityCountInfo = ""; /** * Default constructor. Establishes default values for known security * vulnerabilities. */ public XMLSecurityManager() { - limits = new int[Limit.values().length]; + this(false); + } + + /** + * Instantiate Security Manager in accordance with the status of + * secure processing + * @param secureProcessing + */ + public XMLSecurityManager(boolean secureProcessing) { + limitAnalyzer = new XMLLimitAnalyzer(this); + values = new int[Limit.values().length]; + states = new State[Limit.values().length]; + isSet = new boolean[Limit.values().length]; + this.secureProcessing = secureProcessing; for (Limit limit : Limit.values()) { - limits[limit.ordinal()] = limit.defaultValue(); + if (secureProcessing) { + values[limit.ordinal()] = limit.secureValue; + states[limit.ordinal()] = State.FSP; + } else { + values[limit.ordinal()] = limit.defaultValue(); + states[limit.ordinal()] = State.DEFAULT; + } } //read system properties or jaxp.properties readSystemProperties(); } /** - * Sets the limit for a specific type of XML constructs. This can be either - * the size or the number of the constructs. + * Setting FEATURE_SECURE_PROCESSING explicitly + */ + public void setSecureProcessing(boolean secure) { + secureProcessing = secure; + for (Limit limit : Limit.values()) { + if (secure) { + setLimit(limit.ordinal(), State.FSP, limit.secureValue()); + } else { + setLimit(limit.ordinal(), State.FSP, limit.defaultValue()); + } + } + } + + /** + * Return the state of secure processing + * @return the state of secure processing + */ + public boolean isSecureProcessing() { + return secureProcessing; + } + + + /** + * Set limit by property name and state + * @param propertyName property name + * @param state the state of the property + * @param value the value of the property + * @return true if the property is managed by the security manager; false + * if otherwise. + */ + public boolean setLimit(String propertyName, State state, Object value) { + int index = getIndex(propertyName); + if (index > -1) { + setLimit(index, state, value); + return true; + } + return false; + } + + /** + * Set the value for a specific limit. * - * @param type the type of limitation - * @param state the state of limitation - * @param limit the limit to the type + * @param limit the limit + * @param state the state of the property + * @param value the value of the property */ public void setLimit(Limit limit, State state, int value) { - //only update if it shall override - if (state.compareTo(states[limit.ordinal()]) >= 0) { - limits[limit.ordinal()] = value; - states[limit.ordinal()] = state; + setLimit(limit.ordinal(), state, value); + } + + /** + * Set the value of a property by its index + * + * @param index the index of the property + * @param state the state of the property + * @param value the value of the property + */ + public void setLimit(int index, State state, Object value) { + if (index == indexEntityCountInfo) { + printEntityCountInfo = (String)value; + } else { + int temp = 0; + try { + temp = Integer.parseInt((String) value); + if (temp < 0) { + temp = 0; + } + } catch (NumberFormatException e) {} + setLimit(index, state, temp); + } + } + + /** + * Set the value of a property by its index + * + * @param index the index of the property + * @param state the state of the property + * @param value the value of the property + */ + public void setLimit(int index, State state, int value) { + if (index == indexEntityCountInfo) { + //if it's explicitly set, it's treated as yes no matter the value + printEntityCountInfo = Constants.JDK_YES; + } else { + //only update if it shall override + if (state.compareTo(states[index]) >= 0) { + values[index] = value; + states[index] = state; + isSet[index] = true; + } } } /** - * Returns the limit set for the type specified + * Return the value of the specified property * - * @param limit the type of limitation - * @return the limit to the type + * @param propertyName the property name + * @return the value of the property as a string. If a property is managed + * by this manager, its value shall not be null. + */ + public String getLimitAsString(String propertyName) { + int index = getIndex(propertyName); + if (index > -1) { + return getLimitValueByIndex(index); + } + + return null; + } + /** + * Return the value of the specified property + * + * @param limit the property + * @return the value of the property */ public int getLimit(Limit limit) { - return limits[limit.ordinal()]; + return values[limit.ordinal()]; + } + + /** + * Return the value of a property by its ordinal + * + * @param limit the property + * @return value of a property + */ + public String getLimitValueAsString(Limit limit) { + return Integer.toString(values[limit.ordinal()]); + } + + /** + * Return the value of a property by its ordinal + * + * @param index the index of a property + * @return limit of a property as a string + */ + public String getLimitValueByIndex(int index) { + if (index == indexEntityCountInfo) { + return printEntityCountInfo; + } + + return Integer.toString(values[index]); + } + + /** + * Return the state of the limit property + * + * @param limit the limit + * @return the state of the limit property + */ + public State getState(Limit limit) { + return states[limit.ordinal()]; + } + + /** + * Return the state of the limit property + * + * @param limit the limit + * @return the state of the limit property + */ + public String getStateLiteral(Limit limit) { + return states[limit.ordinal()].literal(); + } + + /** + * Get the index by property name + * + * @param propertyName property name + * @return the index of the property if found; return -1 if not + */ + public int getIndex(String propertyName) { + for (Limit limit : Limit.values()) { + if (limit.equalsAPIPropertyName(propertyName)) { + //internally, ordinal is used as index + return limit.ordinal(); + } + } + //special property to return entity count info + if (propertyName.equals(Constants.JDK_ENTITY_COUNT_INFO)) { + return indexEntityCountInfo; + } + return -1; + } + + /** + * Check if there's no limit defined by the Security Manager + * @param limit + * @return + */ + public boolean isNoLimit(int limit) { + return limit==NO_LIMIT; + } + /** + * Check if the size (length or count) of the specified limit property is + * over the limit + * + * @param limit the type of the limit property + * @param entityName the name of the entity + * @param size the size (count or length) of the entity + * @return true if the size is over the limit, false otherwise + */ + public boolean isOverLimit(Limit limit, String entityName, int size) { + return isOverLimit(limit.ordinal(), entityName, size); + } + + /** + * Check if the value (length or count) of the specified limit property is + * over the limit + * + * @param index the index of the limit property + * @param entityName the name of the entity + * @param size the size (count or length) of the entity + * @return true if the size is over the limit, false otherwise + */ + public boolean isOverLimit(int index, String entityName, int size) { + if (values[index] == NO_LIMIT) { + return false; + } + if (size > values[index]) { + limitAnalyzer.addValue(index, entityName, size); + return true; + } + return false; + } + + /** + * Check against cumulated value + * + * @param limit the type of the limit property + * @param size the size (count or length) of the entity + * @return true if the size is over the limit, false otherwise + */ + public boolean isOverLimit(Limit limit) { + return isOverLimit(limit.ordinal()); + } + + public boolean isOverLimit(int index) { + if (values[index] == NO_LIMIT) { + return false; + } + + if (index==Limit.ELEMENT_ATTRIBUTE_LIMIT.ordinal() || + index==Limit.ENTITY_EXPANSION_LIMIT.ordinal() || + index==Limit.TOTAL_ENTITY_SIZE_LIMIT.ordinal()) { + return (limitAnalyzer.getTotalValue(index) > values[index]); + } else { + return (limitAnalyzer.getValue(index) > values[index]); + } + } + + public void debugPrint() { + if (printEntityCountInfo.equals(Constants.JDK_YES)) { + limitAnalyzer.debugPrint(); + } + } + + /** + * Return the limit analyzer + * + * @return the limit analyzer + */ + public XMLLimitAnalyzer getLimitAnalyzer() { + return limitAnalyzer; + } + + /** + * Set limit analyzer + * + * @param analyzer a limit analyzer + */ + public void setLimitAnalyzer(XMLLimitAnalyzer analyzer) { + limitAnalyzer = analyzer; + } + + /** + * Indicate if a property is set explicitly + * @param index + * @return + */ + public boolean isSet(int index) { + return isSet[index]; + } + + public boolean printEntityCountInfo() { + return printEntityCountInfo.equals(Constants.JDK_YES); } /** * Read from system properties, or those in jaxp.properties */ private void readSystemProperties() { - getSystemProperty(Limit.ENTITY_EXPANSION_LIMIT, Constants.ENTITY_EXPANSION_LIMIT); - getSystemProperty(Limit.MAX_OCCUR_NODE_LIMIT, Constants.MAX_OCCUR_LIMIT); - getSystemProperty(Limit.ELEMENT_ATTRIBUTE_LIMIT, - Constants.SYSTEM_PROPERTY_ELEMENT_ATTRIBUTE_LIMIT); + + for (Limit limit : Limit.values()) { + if (!getSystemProperty(limit, limit.systemProperty())) { + //if system property is not found, try the older form if any + for (NameMap nameMap : NameMap.values()) { + String oldName = nameMap.getOldName(limit.systemProperty()); + if (oldName != null) { + getSystemProperty(limit, oldName); + } + } + } + } + } /** * Read from system properties, or those in jaxp.properties * - * @param limit the type of the property - * @param property the property name + * @param property the type of the property + * @param sysPropertyName the name of system property */ - private void getSystemProperty(Limit limit, String property) { + private boolean getSystemProperty(Limit limit, String sysPropertyName) { try { - String value = SecuritySupport.getSystemProperty(property); + String value = SecuritySupport.getSystemProperty(sysPropertyName); if (value != null && !value.equals("")) { - limits[limit.ordinal()] = Integer.parseInt(value); + values[limit.ordinal()] = Integer.parseInt(value); states[limit.ordinal()] = State.SYSTEMPROPERTY; - return; + return true; } - value = SecuritySupport.readJAXPProperty(property); + value = SecuritySupport.readJAXPProperty(sysPropertyName); if (value != null && !value.equals("")) { - limits[limit.ordinal()] = Integer.parseInt(value); + values[limit.ordinal()] = Integer.parseInt(value); states[limit.ordinal()] = State.JAXPDOTPROPERTIES; + return true; } } catch (NumberFormatException e) { - //invalid setting ignored + //invalid setting + throw new NumberFormatException("Invalid setting for system property: " + limit.systemProperty()); } + return false; } } diff -r 00f1d7d220a9 -r aeaabc10209e src/com/sun/org/apache/xml/internal/utils/XMLReaderManager.java --- a/src/com/sun/org/apache/xml/internal/utils/XMLReaderManager.java Thu Oct 10 16:45:02 2013 +0100 +++ b/src/com/sun/org/apache/xml/internal/utils/XMLReaderManager.java Fri Oct 11 11:35:02 2013 +0100 @@ -24,6 +24,8 @@ import com.sun.org.apache.xalan.internal.utils.SecuritySupport; import com.sun.org.apache.xalan.internal.utils.FactoryImpl; +import com.sun.org.apache.xalan.internal.XalanConstants; +import com.sun.org.apache.xalan.internal.utils.XMLSecurityManager; import java.util.HashMap; import javax.xml.XMLConstants; @@ -67,6 +69,8 @@ private boolean m_useServicesMechanism = true; private boolean _secureProcessing; + + private XMLSecurityManager _xmlSecurityManager; /** * Hidden constructor */ @@ -160,6 +164,21 @@ } } + try { + if (_xmlSecurityManager != null) { + for (XMLSecurityManager.Limit limit : XMLSecurityManager.Limit.values()) { + reader.setProperty(limit.apiProperty(), + _xmlSecurityManager.getLimitValueAsString(limit)); + } + if (_xmlSecurityManager.printEntityCountInfo()) { + reader.setProperty(XalanConstants.JDK_ENTITY_COUNT_INFO, XalanConstants.JDK_YES); + } + } + } catch (SAXException se) { + System.err.println("Warning: " + reader.getClass().getName() + ": " + + se.getMessage()); + } + return reader; } @@ -199,4 +218,22 @@ } } + /** + * Get property value + */ + public Object getProperty(String name) { + if (name.equals(XalanConstants.SECURITY_MANAGER)) { + return _xmlSecurityManager; + } + return null; + } + + /** + * Set property. + */ + public void setProperty(String name, Object value) { + if (name.equals(XalanConstants.SECURITY_MANAGER)) { + _xmlSecurityManager = (XMLSecurityManager)value; + } + } }