|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
|
|
package com.sun.org.apache.xalan.internal.utils; |
|
|
|
import java.util.concurrent.CopyOnWriteArrayList; |
|
import jdk.xml.internal.JdkConstants; |
|
import jdk.xml.internal.JdkProperty.ImplPropMap; |
|
import jdk.xml.internal.JdkProperty.State; |
|
import jdk.xml.internal.SecuritySupport; |
|
import org.xml.sax.SAXException; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public final class XMLSecurityManager { |
|
|
|
|
|
|
|
*/ |
|
@SuppressWarnings("deprecation") |
|
public static enum Limit { |
|
|
|
ENTITY_EXPANSION_LIMIT("EntityExpansionLimit", JdkConstants.JDK_ENTITY_EXPANSION_LIMIT, |
|
JdkConstants.SP_ENTITY_EXPANSION_LIMIT, 0, 64000), |
|
MAX_OCCUR_NODE_LIMIT("MaxOccurLimit", JdkConstants.JDK_MAX_OCCUR_LIMIT, |
|
JdkConstants.SP_MAX_OCCUR_LIMIT, 0, 5000), |
|
ELEMENT_ATTRIBUTE_LIMIT("ElementAttributeLimit", JdkConstants.JDK_ELEMENT_ATTRIBUTE_LIMIT, |
|
JdkConstants.SP_ELEMENT_ATTRIBUTE_LIMIT, 0, 10000), |
|
TOTAL_ENTITY_SIZE_LIMIT("TotalEntitySizeLimit", JdkConstants.JDK_TOTAL_ENTITY_SIZE_LIMIT, |
|
JdkConstants.SP_TOTAL_ENTITY_SIZE_LIMIT, 0, 50000000), |
|
GENERAL_ENTITY_SIZE_LIMIT("MaxEntitySizeLimit", JdkConstants.JDK_GENERAL_ENTITY_SIZE_LIMIT, |
|
JdkConstants.SP_GENERAL_ENTITY_SIZE_LIMIT, 0, 0), |
|
PARAMETER_ENTITY_SIZE_LIMIT("MaxEntitySizeLimit", JdkConstants.JDK_PARAMETER_ENTITY_SIZE_LIMIT, |
|
JdkConstants.SP_PARAMETER_ENTITY_SIZE_LIMIT, 0, 1000000), |
|
MAX_ELEMENT_DEPTH_LIMIT("MaxElementDepthLimit", JdkConstants.JDK_MAX_ELEMENT_DEPTH, |
|
JdkConstants.SP_MAX_ELEMENT_DEPTH, 0, 0), |
|
MAX_NAME_LIMIT("MaxXMLNameLimit", JdkConstants.JDK_XML_NAME_LIMIT, |
|
JdkConstants.SP_XML_NAME_LIMIT, 1000, 1000), |
|
ENTITY_REPLACEMENT_LIMIT("EntityReplacementLimit", JdkConstants.JDK_ENTITY_REPLACEMENT_LIMIT, |
|
JdkConstants.SP_ENTITY_REPLACEMENT_LIMIT, 0, 3000000); |
|
|
|
final String key; |
|
final String apiProperty; |
|
final String systemProperty; |
|
final int defaultValue; |
|
final int secureValue; |
|
|
|
Limit(String key, String apiProperty, String systemProperty, int value, int secureValue) { |
|
this.key = key; |
|
this.apiProperty = apiProperty; |
|
this.systemProperty = systemProperty; |
|
this.defaultValue = value; |
|
this.secureValue = secureValue; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public boolean is(String name) { |
|
|
|
return (systemProperty != null && systemProperty.equals(name)) || |
|
|
|
(apiProperty.equals(name)); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public State getState(String name) { |
|
if (systemProperty != null && systemProperty.equals(name)) { |
|
return State.APIPROPERTY; |
|
} else if (apiProperty.equals(name)) { |
|
|
|
return State.LEGACY_APIPROPERTY; |
|
} |
|
return null; |
|
} |
|
|
|
public String key() { |
|
return key; |
|
} |
|
|
|
public String apiProperty() { |
|
return apiProperty; |
|
} |
|
|
|
public String systemProperty() { |
|
return systemProperty; |
|
} |
|
|
|
public int defaultValue() { |
|
return defaultValue; |
|
} |
|
|
|
int secureValue() { |
|
return secureValue; |
|
} |
|
} |
|
|
|
|
|
|
|
*/ |
|
public static enum NameMap { |
|
|
|
ENTITY_EXPANSION_LIMIT(JdkConstants.SP_ENTITY_EXPANSION_LIMIT, |
|
JdkConstants.ENTITY_EXPANSION_LIMIT), |
|
MAX_OCCUR_NODE_LIMIT(JdkConstants.SP_MAX_OCCUR_LIMIT, |
|
JdkConstants.MAX_OCCUR_LIMIT), |
|
ELEMENT_ATTRIBUTE_LIMIT(JdkConstants.SP_ELEMENT_ATTRIBUTE_LIMIT, |
|
JdkConstants.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 final int[] values; |
|
|
|
|
|
*/ |
|
private State[] states; |
|
|
|
|
|
*/ |
|
private boolean[] isSet; |
|
|
|
|
|
|
|
|
|
*/ |
|
private final int indexEntityCountInfo = 10000; |
|
private String printEntityCountInfo = ""; |
|
|
|
|
|
|
|
|
|
*/ |
|
public XMLSecurityManager() { |
|
this(false); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
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; |
|
} |
|
} |
|
|
|
readSystemProperties(); |
|
} |
|
|
|
|
|
|
|
*/ |
|
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()); |
|
} |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public boolean setLimit(String propertyName, State state, Object value) { |
|
int index = getIndex(propertyName); |
|
if (index > -1) { |
|
State pState = state; |
|
if (index != indexEntityCountInfo && state == State.APIPROPERTY) { |
|
pState = (Limit.values()[index]).getState(propertyName); |
|
} |
|
setLimit(index, pState, value); |
|
return true; |
|
} |
|
return false; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void setLimit(Limit limit, State state, int value) { |
|
setLimit(limit.ordinal(), state, value); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void setLimit(int index, State state, Object value) { |
|
if (index == indexEntityCountInfo) { |
|
|
|
printEntityCountInfo = (String)value; |
|
} else { |
|
int temp; |
|
if (value instanceof Integer) { |
|
temp = (Integer)value; |
|
} else { |
|
temp = Integer.parseInt((String) value); |
|
if (temp < 0) { |
|
temp = 0; |
|
} |
|
} |
|
setLimit(index, state, temp); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void setLimit(int index, State state, int value) { |
|
if (index == indexEntityCountInfo) { |
|
|
|
printEntityCountInfo = JdkConstants.JDK_YES; |
|
} else { |
|
|
|
if (state.compareTo(states[index]) >= 0) { |
|
values[index] = value; |
|
states[index] = state; |
|
isSet[index] = true; |
|
} |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public String getLimitAsString(String propertyName) { |
|
int index = getIndex(propertyName); |
|
if (index > -1) { |
|
return getLimitValueByIndex(index); |
|
} |
|
|
|
return null; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public String getLimitValueAsString(Limit limit) { |
|
return Integer.toString(values[limit.ordinal()]); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public int getLimit(Limit limit) { |
|
return values[limit.ordinal()]; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public int getLimitByIndex(int index) { |
|
return values[index]; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public String getLimitValueByIndex(int index) { |
|
if (index == indexEntityCountInfo) { |
|
return printEntityCountInfo; |
|
} |
|
|
|
return Integer.toString(values[index]); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public State getState(Limit limit) { |
|
return states[limit.ordinal()]; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public String getStateLiteral(Limit limit) { |
|
return states[limit.ordinal()].literal(); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public int getIndex(String propertyName) { |
|
for (Limit limit : Limit.values()) { |
|
|
|
if (limit.is(propertyName)) { |
|
|
|
return limit.ordinal(); |
|
} |
|
} |
|
|
|
if (ImplPropMap.ENTITYCOUNT.is(propertyName)) { |
|
return indexEntityCountInfo; |
|
} |
|
return -1; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public boolean isSet(int index) { |
|
return isSet[index]; |
|
} |
|
|
|
public boolean printEntityCountInfo() { |
|
return printEntityCountInfo.equals(JdkConstants.JDK_YES); |
|
} |
|
|
|
|
|
*/ |
|
private void readSystemProperties() { |
|
|
|
for (Limit limit : Limit.values()) { |
|
if (!getSystemProperty(limit, limit.systemProperty())) { |
|
|
|
for (NameMap nameMap : NameMap.values()) { |
|
String oldName = nameMap.getOldName(limit.systemProperty()); |
|
if (oldName != null) { |
|
getSystemProperty(limit, oldName); |
|
} |
|
} |
|
} |
|
} |
|
|
|
} |
|
|
|
|
|
private static final CopyOnWriteArrayList<String> printedWarnings = new CopyOnWriteArrayList<>(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public static void printWarning(String parserClassName, String propertyName, SAXException exception) { |
|
String key = parserClassName+":"+propertyName; |
|
if (printedWarnings.addIfAbsent(key)) { |
|
System.err.println( "Warning: "+parserClassName+": "+exception.getMessage()); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
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) { |
|
|
|
throw new NumberFormatException("Invalid setting for system property: " + limit.systemProperty()); |
|
} |
|
return false; |
|
} |
|
} |