You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by fo...@apache.org on 2017/02/24 13:35:15 UTC
camel git commit: CAMEL-10894: DTD handling in the XML Validator
corrected
Repository: camel
Updated Branches:
refs/heads/master 927244de6 -> 8afc5d175
CAMEL-10894: DTD handling in the XML Validator corrected
Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/8afc5d17
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/8afc5d17
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/8afc5d17
Branch: refs/heads/master
Commit: 8afc5d1757795fde715902067360af5d90f046da
Parents: 927244d
Author: Franz Forsthofer <fr...@sap.com>
Authored: Fri Feb 24 13:57:10 2017 +0100
Committer: Franz Forsthofer <fr...@sap.com>
Committed: Fri Feb 24 14:34:34 2017 +0100
----------------------------------------------------------------------
.../processor/validation/SchemaReader.java | 15 +++-
.../ValidatorDtdAccessAbstractTest.java | 86 ++++++++++++++++++++
.../validator/ValidatorDtdAccessOffTest.java | 61 ++++++++++++++
.../validator/ValidatorDtdAccessOnTest.java | 61 ++++++++++++++
4 files changed, 221 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/camel/blob/8afc5d17/camel-core/src/main/java/org/apache/camel/processor/validation/SchemaReader.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/processor/validation/SchemaReader.java b/camel-core/src/main/java/org/apache/camel/processor/validation/SchemaReader.java
index 68ea309..354acd4 100644
--- a/camel-core/src/main/java/org/apache/camel/processor/validation/SchemaReader.java
+++ b/camel-core/src/main/java/org/apache/camel/processor/validation/SchemaReader.java
@@ -30,7 +30,6 @@ import javax.xml.validation.SchemaFactory;
import org.w3c.dom.ls.LSResourceResolver;
import org.xml.sax.SAXException;
-
import org.apache.camel.CamelContext;
import org.apache.camel.converter.IOConverter;
import org.apache.camel.util.IOHelper;
@@ -46,8 +45,12 @@ import org.slf4j.LoggerFactory;
*/
public class SchemaReader {
+ /** Key of the global option to switch either off or on the access to external DTDs in the XML Validator for StreamSources.
+ * Only effective, if not a custom schema factory is used.*/
+ public static final String ACCESS_EXTERNAL_DTD = "CamelXmlValidatorAccessExternalDTD";
+
private static final Logger LOG = LoggerFactory.getLogger(SchemaReader.class);
-
+
private String schemaLanguage = XMLConstants.W3C_XML_SCHEMA_NS_URI;
// must be volatile because is accessed from different threads see ValidatorEndpoint.clearCachedSchema
private volatile Schema schema;
@@ -169,6 +172,14 @@ public class SchemaReader {
SchemaFactory factory = SchemaFactory.newInstance(schemaLanguage);
if (getResourceResolver() != null) {
factory.setResourceResolver(getResourceResolver());
+ }
+ if (!Boolean.parseBoolean(camelContext.getGlobalOptions().get(ACCESS_EXTERNAL_DTD))) {
+ try {
+ factory.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, "");
+ } catch (SAXException e) {
+ LOG.error(e.getMessage(), e);
+ throw new IllegalStateException(e);
+ }
}
return factory;
}
http://git-wip-us.apache.org/repos/asf/camel/blob/8afc5d17/camel-core/src/test/java/org/apache/camel/component/validator/ValidatorDtdAccessAbstractTest.java
----------------------------------------------------------------------
diff --git a/camel-core/src/test/java/org/apache/camel/component/validator/ValidatorDtdAccessAbstractTest.java b/camel-core/src/test/java/org/apache/camel/component/validator/ValidatorDtdAccessAbstractTest.java
new file mode 100644
index 0000000..cc83594
--- /dev/null
+++ b/camel-core/src/test/java/org/apache/camel/component/validator/ValidatorDtdAccessAbstractTest.java
@@ -0,0 +1,86 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.validator;
+
+import java.net.UnknownHostException;
+
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.ValidationException;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.processor.validation.SchemaReader;
+
+public abstract class ValidatorDtdAccessAbstractTest extends ContextTestSupport {
+
+ protected MockEndpoint finallyEndpoint;
+ protected MockEndpoint invalidEndpoint;
+ protected MockEndpoint unknownHostExceptionEndpoint;
+ protected MockEndpoint validEndpoint;
+
+ protected String payloud = getPayloudPart("Hello world!");
+
+ protected String ssrfPayloud = "<!DOCTYPE roottag PUBLIC \"-//VSR//PENTEST//EN\" \"http://notexisting/test\">\n" + payloud;
+
+ protected String xxePayloud = "<!DOCTYPE updateProfile [<!ENTITY file SYSTEM \"http://notexistinghost/test\">]>\n" + getPayloudPart("&file;");
+
+ private final boolean accessExternalDTD;
+
+ public ValidatorDtdAccessAbstractTest(boolean accessExternalDTD) {
+ this.accessExternalDTD = accessExternalDTD;
+ }
+
+
+ private String getPayloudPart(String bodyValue) {
+ return "<mail xmlns='http://foo.com/bar'><subject>Hey</subject><body>" + bodyValue + "</body></mail>";
+ }
+
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ validEndpoint = resolveMandatoryEndpoint("mock:valid", MockEndpoint.class);
+ invalidEndpoint = resolveMandatoryEndpoint("mock:invalid", MockEndpoint.class);
+ unknownHostExceptionEndpoint = resolveMandatoryEndpoint("mock:unknownHostException", MockEndpoint.class);
+ finallyEndpoint = resolveMandatoryEndpoint("mock:finally", MockEndpoint.class);
+ }
+
+ @Override
+ protected RouteBuilder createRouteBuilder() throws Exception {
+ return new RouteBuilder() {
+
+ @Override
+ public void configure() throws Exception {
+ // switch on DTD Access
+ if (accessExternalDTD) {
+ getContext().getGlobalOptions().put(SchemaReader.ACCESS_EXTERNAL_DTD, "true");
+ }
+ from("direct:start")
+ .doTry()
+ .to("validator:org/apache/camel/component/validator/schema.xsd")
+ .to("mock:valid")
+ .doCatch(ValidationException.class)
+ .to("mock:invalid")
+ .doCatch(UnknownHostException.class)
+ .to("mock:unknownHostException")
+ .doFinally()
+ .to("mock:finally").end();
+ }
+ };
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/8afc5d17/camel-core/src/test/java/org/apache/camel/component/validator/ValidatorDtdAccessOffTest.java
----------------------------------------------------------------------
diff --git a/camel-core/src/test/java/org/apache/camel/component/validator/ValidatorDtdAccessOffTest.java b/camel-core/src/test/java/org/apache/camel/component/validator/ValidatorDtdAccessOffTest.java
new file mode 100644
index 0000000..37f0aee
--- /dev/null
+++ b/camel-core/src/test/java/org/apache/camel/component/validator/ValidatorDtdAccessOffTest.java
@@ -0,0 +1,61 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.validator;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+
+import org.apache.camel.component.mock.MockEndpoint;
+
+public class ValidatorDtdAccessOffTest extends ValidatorDtdAccessAbstractTest {
+
+ public ValidatorDtdAccessOffTest() {
+ super(false);
+ }
+
+ /** Tests that no external DTD call is executed for StringSource. */
+ public void testInvalidMessageWithExternalDTDStringSource() throws Exception {
+ invalidEndpoint.expectedMessageCount(1);
+ finallyEndpoint.expectedMessageCount(1);
+
+ template.sendBody("direct:start", ssrfPayloud);
+
+ MockEndpoint.assertIsSatisfied(validEndpoint, unknownHostExceptionEndpoint, finallyEndpoint);
+ }
+
+ /** Tests that external DTD call is not executed for StreamSource. */
+ public void testInvalidMessageWithExternalDTDStreamSource() throws Exception {
+ invalidEndpoint.expectedMessageCount(1);
+ finallyEndpoint.expectedMessageCount(1);
+ InputStream is = new ByteArrayInputStream(ssrfPayloud.getBytes(StandardCharsets.UTF_8));
+ template.sendBody("direct:start", is);
+
+ MockEndpoint.assertIsSatisfied(validEndpoint, unknownHostExceptionEndpoint, finallyEndpoint);
+ }
+
+ /** Tests that XXE is not possible for StreamSource. */
+ public void testInvalidMessageXXESourceStream() throws Exception {
+ invalidEndpoint.expectedMessageCount(1);
+ finallyEndpoint.expectedMessageCount(1);
+ InputStream is = new ByteArrayInputStream(xxePayloud.getBytes(StandardCharsets.UTF_8));
+ template.sendBody("direct:start", is);
+
+ MockEndpoint.assertIsSatisfied(validEndpoint, unknownHostExceptionEndpoint, finallyEndpoint);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/8afc5d17/camel-core/src/test/java/org/apache/camel/component/validator/ValidatorDtdAccessOnTest.java
----------------------------------------------------------------------
diff --git a/camel-core/src/test/java/org/apache/camel/component/validator/ValidatorDtdAccessOnTest.java b/camel-core/src/test/java/org/apache/camel/component/validator/ValidatorDtdAccessOnTest.java
new file mode 100644
index 0000000..b57303d
--- /dev/null
+++ b/camel-core/src/test/java/org/apache/camel/component/validator/ValidatorDtdAccessOnTest.java
@@ -0,0 +1,61 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.validator;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+
+import org.apache.camel.component.mock.MockEndpoint;
+
+public class ValidatorDtdAccessOnTest extends ValidatorDtdAccessAbstractTest {
+
+ public ValidatorDtdAccessOnTest() {
+ super(true);
+ }
+
+ /** Tests that external DTD call is executed for StringSource by expecting an UnkonwHostException. */
+ public void testInvalidMessageWithExternalDTDStringSource() throws Exception {
+ unknownHostExceptionEndpoint.expectedMessageCount(1);
+ finallyEndpoint.expectedMessageCount(1);
+
+ template.sendBody("direct:start", ssrfPayloud);
+
+ MockEndpoint.assertIsSatisfied(validEndpoint, unknownHostExceptionEndpoint, finallyEndpoint);
+ }
+
+ /** Tests that external DTD call is executed for StreamSourceby expecting an UnkonwHostException. */
+ public void testInvalidMessageWithExternalDTDStreamSource() throws Exception {
+ unknownHostExceptionEndpoint.expectedMessageCount(1);
+ finallyEndpoint.expectedMessageCount(1);
+ InputStream is = new ByteArrayInputStream(ssrfPayloud.getBytes(StandardCharsets.UTF_8));
+ template.sendBody("direct:start", is);
+
+ MockEndpoint.assertIsSatisfied(validEndpoint, unknownHostExceptionEndpoint, finallyEndpoint);
+ }
+
+ /** Tests that XXE is possible for StreamSource by expecting an UnkonwHostException. */
+ public void testInvalidMessageXXESourceStream() throws Exception {
+ unknownHostExceptionEndpoint.expectedMessageCount(1);
+ finallyEndpoint.expectedMessageCount(1);
+ InputStream is = new ByteArrayInputStream(xxePayloud.getBytes(StandardCharsets.UTF_8));
+ template.sendBody("direct:start", is);
+
+ MockEndpoint.assertIsSatisfied(validEndpoint, unknownHostExceptionEndpoint, finallyEndpoint);
+ }
+
+}