Author: dkulp Date: Mon Mar 25 18:31:23 2013 New Revision: 1460816 URL: http://svn.apache.org/r1460816 Log: Merged revisions 1460788 via git cherry-pick from https://svn.apache.org/repos/asf/cxf/branches/2.7.x-fixes
........ r1460788 | dkulp | 2013-03-25 13:56:27 -0400 (Mon, 25 Mar 2013) | 10 lines Merged revisions 1460771 via git cherry-pick from https://svn.apache.org/repos/asf/cxf/trunk ........ r1460771 | dkulp | 2013-03-25 13:34:24 -0400 (Mon, 25 Mar 2013) | 2 lines Wire in a bunch of properties to control limits on the XML parsing ........ ........ Added: cxf/branches/2.6.x-fixes/api/src/main/java/org/apache/cxf/staxutils/Messages.properties Modified: cxf/branches/2.6.x-fixes/api/src/main/java/org/apache/cxf/interceptor/StaxInInterceptor.java cxf/branches/2.6.x-fixes/api/src/main/java/org/apache/cxf/staxutils/DepthRestrictingStreamReader.java cxf/branches/2.6.x-fixes/api/src/main/java/org/apache/cxf/staxutils/StaxUtils.java cxf/branches/2.6.x-fixes/rt/core/src/main/java/org/apache/cxf/interceptor/security/DepthRestrictingStreamInterceptor.java Modified: cxf/branches/2.6.x-fixes/api/src/main/java/org/apache/cxf/interceptor/StaxInInterceptor.java URL: http://svn.apache.org/viewvc/cxf/branches/2.6.x-fixes/api/src/main/java/org/apache/cxf/interceptor/StaxInInterceptor.java?rev=1460816&r1=1460815&r2=1460816&view=diff ============================================================================== --- cxf/branches/2.6.x-fixes/api/src/main/java/org/apache/cxf/interceptor/StaxInInterceptor.java (original) +++ cxf/branches/2.6.x-fixes/api/src/main/java/org/apache/cxf/interceptor/StaxInInterceptor.java Mon Mar 25 18:31:23 2013 @@ -120,16 +120,50 @@ public class StaxInInterceptor extends A } } } + xreader = configureRestrictions(xreader, message); } catch (XMLStreamException e) { throw new Fault(new org.apache.cxf.common.i18n.Message("STREAM_CREATE_EXC", LOG, encoding), e); } - message.setContent(XMLStreamReader.class, xreader); message.getInterceptorChain().add(StaxInEndingInterceptor.INSTANCE); } + private XMLStreamReader configureRestrictions(XMLStreamReader xreader, Message message) throws XMLStreamException { + Integer maxChildElements = getInteger(message, StaxUtils.MAX_CHILD_ELEMENTS); + Integer maxElementDepth = getInteger(message, StaxUtils.MAX_ELEMENT_DEPTH); + Integer maxAttributeCount = getInteger(message, StaxUtils.MAX_ATTRIBUTE_COUNT); + Integer maxAttributeSize = getInteger(message, StaxUtils.MAX_ATTRIBUTE_SIZE); + Integer maxTextLength = getInteger(message, StaxUtils.MAX_TEXT_LENGTH); + Long maxElementCount = getLong(message, StaxUtils.MAX_ELEMENT_COUNT); + Long maxXMLCharacters = getLong(message, StaxUtils.MAX_XML_CHARACTERS); + return StaxUtils.configureReader(xreader, maxChildElements, maxElementDepth, + maxAttributeCount, maxAttributeSize, maxTextLength, + maxElementCount, maxXMLCharacters); + } + private Long getLong(Message message, String key) { + Object o = message.getContextualProperty(key); + if (o instanceof Long) { + return (Long)o; + } else if (o instanceof Number) { + return ((Number)o).longValue(); + } else if (o instanceof String) { + return Long.valueOf(o.toString()); + } + return null; + } + private Integer getInteger(Message message, String key) { + Object o = message.getContextualProperty(key); + if (o instanceof Integer) { + return (Integer)o; + } else if (o instanceof Number) { + return ((Number)o).intValue(); + } else if (o instanceof String) { + return Integer.valueOf((String)o); + } + return null; + } public static XMLInputFactory getXMLInputFactory(Message m) throws Fault { Object o = m.getContextualProperty(XMLInputFactory.class.getName()); if (o instanceof XMLInputFactory) { Modified: cxf/branches/2.6.x-fixes/api/src/main/java/org/apache/cxf/staxutils/DepthRestrictingStreamReader.java URL: http://svn.apache.org/viewvc/cxf/branches/2.6.x-fixes/api/src/main/java/org/apache/cxf/staxutils/DepthRestrictingStreamReader.java?rev=1460816&r1=1460815&r2=1460816&view=diff ============================================================================== --- cxf/branches/2.6.x-fixes/api/src/main/java/org/apache/cxf/staxutils/DepthRestrictingStreamReader.java (original) +++ cxf/branches/2.6.x-fixes/api/src/main/java/org/apache/cxf/staxutils/DepthRestrictingStreamReader.java Mon Mar 25 18:31:23 2013 @@ -42,10 +42,9 @@ public class DepthRestrictingStreamReade int elementCountThreshold, int innerElementLevelThreshold, int innerElementCountThreshold) { - super(reader); - this.props = new DocumentDepthProperties(elementCountThreshold, - innerElementLevelThreshold, - innerElementCountThreshold); + this(reader, new DocumentDepthProperties(elementCountThreshold, + innerElementLevelThreshold, + innerElementCountThreshold)); } public DepthRestrictingStreamReader(XMLStreamReader reader, Added: cxf/branches/2.6.x-fixes/api/src/main/java/org/apache/cxf/staxutils/Messages.properties URL: http://svn.apache.org/viewvc/cxf/branches/2.6.x-fixes/api/src/main/java/org/apache/cxf/staxutils/Messages.properties?rev=1460816&view=auto ============================================================================== --- cxf/branches/2.6.x-fixes/api/src/main/java/org/apache/cxf/staxutils/Messages.properties (added) +++ cxf/branches/2.6.x-fixes/api/src/main/java/org/apache/cxf/staxutils/Messages.properties Mon Mar 25 18:31:23 2013 @@ -0,0 +1,23 @@ +# +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# +# +INSECURE_PARSER_DETECTED = Could not create a secure Stax XMLInputFactory. Found class {0}. Suggest Woodstox 4.2.0 or newer. +SECURE_PROPERTY_NOT_SUPPORTED = Required security property not supported: {0} +INSTANCE_NOT_XMLSTREAMREADER2 = XMLStreamReader not an instance of XMLStreamReader2. Suggest Woodstox 4.2.0 or newer. \ No newline at end of file Modified: cxf/branches/2.6.x-fixes/api/src/main/java/org/apache/cxf/staxutils/StaxUtils.java URL: http://svn.apache.org/viewvc/cxf/branches/2.6.x-fixes/api/src/main/java/org/apache/cxf/staxutils/StaxUtils.java?rev=1460816&r1=1460815&r2=1460816&view=diff ============================================================================== --- cxf/branches/2.6.x-fixes/api/src/main/java/org/apache/cxf/staxutils/StaxUtils.java (original) +++ cxf/branches/2.6.x-fixes/api/src/main/java/org/apache/cxf/staxutils/StaxUtils.java Mon Mar 25 18:31:23 2013 @@ -32,6 +32,7 @@ import java.util.List; import java.util.Stack; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; +import java.util.logging.Level; import java.util.logging.Logger; import javax.xml.namespace.NamespaceContext; @@ -85,22 +86,33 @@ import org.apache.cxf.common.util.System import org.apache.cxf.helpers.CastUtils; import org.apache.cxf.helpers.DOMUtils; import org.apache.cxf.helpers.XMLUtils; +import org.codehaus.stax2.XMLStreamReader2; public final class StaxUtils { + // System properies for defaults, but also contextual properties usable + // for StaxInInterceptor + public static final String MAX_CHILD_ELEMENTS = + "org.apache.cxf.stax.maxChildElements"; + public static final String MAX_ELEMENT_DEPTH = + "org.apache.cxf.stax.maxElementDepth"; + public static final String MAX_ATTRIBUTE_COUNT = + "org.apache.cxf.stax.maxAttributeCount"; + public static final String MAX_ATTRIBUTE_SIZE = + "org.apache.cxf.stax.maxAttributeSize"; + public static final String MAX_TEXT_LENGTH = + "org.apache.cxf.stax.maxTextLength"; + public static final String MAX_ELEMENT_COUNT = + "org.apache.cxf.stax.maxElementCount"; + public static final String MAX_XML_CHARACTERS = + "org.apache.cxf.stax.maxXMLCharacters"; + + public static final String ALLOW_INSECURE_PARSER = + "org.apache.cxf.stax.allowInsecureParser"; + private static final String INNER_ELEMENT_COUNT_SYSTEM_PROP = "org.apache.cxf.staxutils.innerElementCountThreshold"; private static final String INNER_ELEMENT_LEVEL_SYSTEM_PROP = "org.apache.cxf.staxutils.innerElementLevelThreshold"; - private static final String MAX_ATTRIBUTE_COUNT = - "org.apache.cxf.staxutils.maxAttributeCount"; - private static final String MAX_ATTRIBUTE_SIZE = - "org.apache.cxf.staxutils.maxAttributeSize"; - private static final String MAX_TEXT_LENGTH = - "org.apache.cxf.staxutils.maxTextLength"; - private static final String MAX_ELEMENT_COUNT = - "org.apache.cxf.staxutils.maxElementCount"; - private static final String MAX_XML_CHARACTERS = - "org.apache.cxf.staxutils.maxXMLCharacters"; private static final Logger LOG = LogUtils.getL7dLogger(StaxUtils.class); @@ -122,8 +134,10 @@ public final class StaxUtils { private static int maxAttributeSize = 64 * 1024; //64K per attribute, likely just "list" will hit private static int maxTextLength = 128 * 1024 * 1024; //128M - more than this should DEFINITLEY use MTOM private static long maxElementCount = Long.MAX_VALUE; - private static long maxXMLCharacters = Long.MAX_VALUE; + private static long maxXMLCharacters = Long.MAX_VALUE; + //will change to false in the near future + private static boolean allowInsecureParser = true; static { int i = getInteger("org.apache.cxf.staxutils.pool-size", 20); @@ -131,14 +145,23 @@ public final class StaxUtils { NS_AWARE_INPUT_FACTORY_POOL = new ArrayBlockingQueue<XMLInputFactory>(i); OUTPUT_FACTORY_POOL = new ArrayBlockingQueue<XMLOutputFactory>(i); + //old names innerElementCountThreshold = getInteger(INNER_ELEMENT_LEVEL_SYSTEM_PROP, innerElementCountThreshold); innerElementLevelThreshold = getInteger(INNER_ELEMENT_COUNT_SYSTEM_PROP, innerElementLevelThreshold); + //new names + innerElementCountThreshold = getInteger(MAX_CHILD_ELEMENTS, innerElementCountThreshold); + innerElementLevelThreshold = getInteger(MAX_ELEMENT_DEPTH, innerElementLevelThreshold); maxAttributeCount = getInteger(MAX_ATTRIBUTE_COUNT, maxAttributeCount); maxAttributeSize = getInteger(MAX_ATTRIBUTE_SIZE, maxAttributeSize); maxTextLength = getInteger(MAX_TEXT_LENGTH, maxTextLength); maxElementCount = getLong(MAX_ELEMENT_COUNT, maxElementCount); maxXMLCharacters = getLong(MAX_XML_CHARACTERS, maxXMLCharacters); + String s = SystemPropertyAction.getPropertyOrNull(ALLOW_INSECURE_PARSER); + if (!StringUtils.isEmpty(s)) { + allowInsecureParser = "1".equals(s) || Boolean.parseBoolean(s); + } + XMLInputFactory xif = createXMLInputFactory(true); String xifClassName = xif.getClass().getName(); if (xifClassName.contains("ctc.wstx") || xifClassName.contains("xml.xlxp") @@ -163,7 +186,7 @@ public final class StaxUtils { } private static int getInteger(String prop, int def) { try { - String s = SystemPropertyAction.getProperty(prop); + String s = SystemPropertyAction.getPropertyOrNull(prop); if (StringUtils.isEmpty(s)) { return def; } @@ -179,7 +202,7 @@ public final class StaxUtils { } private static long getLong(String prop, long def) { try { - String s = SystemPropertyAction.getProperty(prop); + String s = SystemPropertyAction.getPropertyOrNull(prop); if (StringUtils.isEmpty(s)) { return def; } @@ -263,9 +286,17 @@ public final class StaxUtils { public static XMLInputFactory createXMLInputFactory(boolean nsAware) { XMLInputFactory factory = XMLInputFactory.newInstance(); if (!setRestrictionProperties(factory)) { - factory = new WstxInputFactory(); + try { + factory = createWoodstoxFactory(); + } catch (Throwable t) { + //ignore for now + } if (!setRestrictionProperties(factory)) { - throw new RuntimeException("Cannot create a secure XMLInputFactory"); + if (allowInsecureParser) { + LOG.log(Level.WARNING, "INSECURE_PARSER_DETECTED", factory.getClass().getName()); + } else { + throw new RuntimeException("Cannot create a secure XMLInputFactory"); + } } } setProperty(factory, XMLInputFactory.IS_NAMESPACE_AWARE, nsAware); @@ -283,6 +314,9 @@ public final class StaxUtils { return factory; } + private static XMLInputFactory createWoodstoxFactory() { + return new WstxInputFactory(); + } private static boolean setRestrictionProperties(XMLInputFactory factory) { //For now, we can only support Woodstox 4.2.x and newer as none of the other //stax parsers support these settings @@ -1673,5 +1707,84 @@ public final class StaxUtils { } } } + + //CHECKSTYLE:OFF - lots of params to configure + public static XMLStreamReader configureReader(XMLStreamReader reader, Integer maxChildElements, + Integer maxElementDepth, Integer maxAttributeCount, + Integer maxAttributeSize, Integer maxTextLength, + Long maxElementCount, Long maxXMLCharacters) + throws XMLStreamException { + //CHECKSTYLE:ON + + // We currently ONLY support Woodstox 4.2.x for most of this other than a few things + // that we can handle via a wrapper. + try { + DocumentDepthProperties p = null; + if (maxChildElements != null) { + try { + setProperty(reader, "com.ctc.wstx.maxChildrenPerElement", maxChildElements); + } catch (Throwable t) { + //we can handle this via a wrapper + p = new DocumentDepthProperties(); + p.setInnerElementCountThreshold(maxChildElements); + } + } + if (maxElementDepth != null) { + try { + setProperty(reader, "com.ctc.wstx.maxElementDepth", maxElementDepth); + } catch (Throwable t) { + //we can handle this via a wrapper + if (p == null) { + p = new DocumentDepthProperties(); + } + p.setInnerElementLevelThreshold(maxElementDepth); + } + } + if (maxAttributeCount != null) { + setProperty(reader, "com.ctc.wstx.maxAttributeCount", maxAttributeCount); + } + if (maxAttributeSize != null) { + setProperty(reader, "com.ctc.wstx.maxAttributeSize", maxAttributeSize); + } + if (maxTextLength != null) { + setProperty(reader, "com.ctc.wstx.maxTextLength", maxTextLength); + } + if (maxElementCount != null) { + try { + setProperty(reader, "com.ctc.wstx.maxElementCount", maxElementCount); + } catch (Throwable t) { + //we can handle this via a wrapper + if (p == null) { + p = new DocumentDepthProperties(); + } + p.setElementCountThreshold(maxElementCount.intValue()); + } + } + if (maxXMLCharacters != null) { + setProperty(reader, "com.ctc.wstx.maxCharacters", maxXMLCharacters); + } + if (p != null) { + reader = new DepthRestrictingStreamReader(reader, p); + } + } catch (ClassCastException cce) { + //not an XMLStreamReader2 + if (allowInsecureParser) { + LOG.warning("INSTANCE_NOT_XMLSTREAMREADER2"); + } else { + throw new XMLStreamException(cce); + } + } catch (IllegalArgumentException cce) { + //not a property supported by this version of woodstox + if (allowInsecureParser) { + LOG.log(Level.WARNING, "SECURE_PROPERTY_NOT_SUPPORTED", cce.getMessage()); + } else { + throw new XMLStreamException(cce); + } + } + return reader; + } + private static void setProperty(XMLStreamReader reader, String p, Object v) { + ((XMLStreamReader2)reader).setProperty(p, v); + } } Modified: cxf/branches/2.6.x-fixes/rt/core/src/main/java/org/apache/cxf/interceptor/security/DepthRestrictingStreamInterceptor.java URL: http://svn.apache.org/viewvc/cxf/branches/2.6.x-fixes/rt/core/src/main/java/org/apache/cxf/interceptor/security/DepthRestrictingStreamInterceptor.java?rev=1460816&r1=1460815&r2=1460816&view=diff ============================================================================== --- cxf/branches/2.6.x-fixes/rt/core/src/main/java/org/apache/cxf/interceptor/security/DepthRestrictingStreamInterceptor.java (original) +++ cxf/branches/2.6.x-fixes/rt/core/src/main/java/org/apache/cxf/interceptor/security/DepthRestrictingStreamInterceptor.java Mon Mar 25 18:31:23 2013 @@ -25,6 +25,7 @@ import java.util.List; import javax.xml.stream.XMLStreamReader; +import org.apache.cxf.interceptor.StaxInInterceptor; import org.apache.cxf.message.Message; import org.apache.cxf.phase.AbstractPhaseInterceptor; import org.apache.cxf.phase.Phase; @@ -43,6 +44,7 @@ public class DepthRestrictingStreamInter public DepthRestrictingStreamInterceptor() { this(Phase.POST_STREAM); + addAfter(StaxInInterceptor.class.getName()); } public DepthRestrictingStreamInterceptor(String phase) { @@ -69,16 +71,16 @@ public class DepthRestrictingStreamInter return; } - XMLStreamReader reader = null; - InputStream is = message.getContent(InputStream.class); - if (is != null) { - reader = StaxUtils.createXMLStreamReader(is); - message.setContent(InputStream.class, null); - } else { - reader = message.getContent(XMLStreamReader.class); - } + XMLStreamReader reader = message.getContent(XMLStreamReader.class); if (reader == null) { - return; + InputStream is = message.getContent(InputStream.class); + if (is != null) { + reader = StaxUtils.createXMLStreamReader(is); + message.setContent(InputStream.class, null); + } + if (reader == null) { + return; + } } DepthRestrictingStreamReader dr = new DepthRestrictingStreamReader(reader,
