This is an automated email from the ASF dual-hosted git repository. coheigea pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/cxf.git
commit 8b2b484109df9821af77ccc9ce07a7d16920d7c7 Author: Colm O hEigeartaigh <[email protected]> AuthorDate: Tue Nov 26 14:44:36 2019 +0000 CXF-8167 - Restrict the URI schemes allowed when importing schemas or WSDLs --- .../cxf/wsdl11/AbstractWrapperWSDLLocator.java | 22 ++++++++ .../tools/validator/internal/SchemaValidator.java | 35 +++---------- .../tools/validator/internal/WSDL11Validator.java | 2 +- .../cxf/tools/validator/WSDLValidationTest.java | 20 +++++++- .../test/resources/validator_wsdl/ftp_import.wsdl | 59 ++++++++++++++++++++++ .../test/resources/validator_wsdl/ftp_import2.wsdl | 59 ++++++++++++++++++++++ 6 files changed, 168 insertions(+), 29 deletions(-) diff --git a/rt/wsdl/src/main/java/org/apache/cxf/wsdl11/AbstractWrapperWSDLLocator.java b/rt/wsdl/src/main/java/org/apache/cxf/wsdl11/AbstractWrapperWSDLLocator.java index 98c86de..81a53fd 100644 --- a/rt/wsdl/src/main/java/org/apache/cxf/wsdl11/AbstractWrapperWSDLLocator.java +++ b/rt/wsdl/src/main/java/org/apache/cxf/wsdl11/AbstractWrapperWSDLLocator.java @@ -19,12 +19,24 @@ package org.apache.cxf.wsdl11; import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; import javax.wsdl.xml.WSDLLocator; import org.xml.sax.InputSource; public abstract class AbstractWrapperWSDLLocator implements WSDLLocator { + private static final List<String> ALLOWED_SCHEMES; + + static { + List<String> schemes = Arrays.asList("file", "http", "https", "classpath", "jar"); + ALLOWED_SCHEMES = Collections.unmodifiableList(schemes); + } + protected WSDLLocator parent; String wsdlUrl; InputSource last; @@ -83,6 +95,16 @@ public abstract class AbstractWrapperWSDLLocator implements WSDLLocator { } public InputSource getImportInputSource(String parentLocation, String importLocation) { + // Do a check on the scheme to see if it's anything that could be a security risk + try { + URI url = new URI(importLocation); + if (!(url.getScheme() == null || ALLOWED_SCHEMES.contains(url.getScheme()))) { + throw new IllegalArgumentException("The " + url.getScheme() + " URI scheme is not allowed"); + } + } catch (URISyntaxException e) { + // Just continue here as we might still be able to load it from the filesystem + } + InputSource src = parent.getImportInputSource(parentLocation, importLocation); lastImport = null; if (src == null || (src.getByteStream() == null && src.getCharacterStream() == null)) { diff --git a/tools/validator/src/main/java/org/apache/cxf/tools/validator/internal/SchemaValidator.java b/tools/validator/src/main/java/org/apache/cxf/tools/validator/internal/SchemaValidator.java index b4c722d..e58dc1a 100644 --- a/tools/validator/src/main/java/org/apache/cxf/tools/validator/internal/SchemaValidator.java +++ b/tools/validator/src/main/java/org/apache/cxf/tools/validator/internal/SchemaValidator.java @@ -24,7 +24,6 @@ import java.io.FilenameFilter; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; -import java.net.URLConnection; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -114,8 +113,7 @@ public class SchemaValidator extends AbstractDefinitionValidator { throw new ToolException(e); } - String systemId = null; - systemId = URIParserUtil.getAbsoluteURI(wsdlsource); + String systemId = URIParserUtil.getAbsoluteURI(wsdlsource); InputSource is = new InputSource(systemId); return validate(is, schemas); @@ -127,7 +125,7 @@ public class SchemaValidator extends AbstractDefinitionValidator { SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); sf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, Boolean.TRUE); - sf.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "file"); + sf.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "file,http,https"); SchemaResourceResolver resourceResolver = new SchemaResourceResolver(); sf.setResourceResolver(resourceResolver); @@ -392,35 +390,18 @@ class SchemaResourceResolver implements LSResourceResolver { resURL = namespaceURI; } - if (resURL != null && resURL.startsWith("http://")) { + if (resURL == null) { + return null; + } + + localFile = resURL; + if (resURL.startsWith("http://")) { String filename = NSFILEMAP.get(resURL); if (filename != null) { localFile = ToolConstants.CXF_SCHEMAS_DIR_INJAR + filename; - } else { - URL url; - URLConnection urlCon = null; - try { - url = new URL(resURL); - urlCon = url.openConnection(); - urlCon.setUseCaches(false); - lsin = new LSInputImpl(); - lsin.setSystemId(resURL); - lsin.setByteStream(urlCon.getInputStream()); - msg = new Message("RESOLVE_FROM_REMOTE", LOG, url); - LOG.log(Level.FINE, msg.toString()); - return lsin; - } catch (Exception e) { - e.printStackTrace(); - return null; - } } - } else if (resURL != null && !resURL.startsWith("http:")) { - localFile = resURL; - } else { - return null; } - URIResolver resolver; try { msg = new Message("RESOLVE_FROM_LOCAL", LOG, localFile); diff --git a/tools/validator/src/main/java/org/apache/cxf/tools/validator/internal/WSDL11Validator.java b/tools/validator/src/main/java/org/apache/cxf/tools/validator/internal/WSDL11Validator.java index 29c8cbb..df65f6d 100644 --- a/tools/validator/src/main/java/org/apache/cxf/tools/validator/internal/WSDL11Validator.java +++ b/tools/validator/src/main/java/org/apache/cxf/tools/validator/internal/WSDL11Validator.java @@ -61,7 +61,7 @@ import org.apache.cxf.tools.validator.AbstractValidator; import org.apache.cxf.wsdl.WSDLManager; public class WSDL11Validator extends AbstractDefinitionValidator { - protected static final Logger LOG = LogUtils.getL7dLogger(SchemaValidator.class); + protected static final Logger LOG = LogUtils.getL7dLogger(WSDL11Validator.class); private final List<AbstractValidator> validators = new ArrayList<>(); public WSDL11Validator(final Definition definition) { diff --git a/tools/validator/src/test/java/org/apache/cxf/tools/validator/WSDLValidationTest.java b/tools/validator/src/test/java/org/apache/cxf/tools/validator/WSDLValidationTest.java index 8e249e8..96650a6 100644 --- a/tools/validator/src/test/java/org/apache/cxf/tools/validator/WSDLValidationTest.java +++ b/tools/validator/src/test/java/org/apache/cxf/tools/validator/WSDLValidationTest.java @@ -213,6 +213,24 @@ public class WSDLValidationTest extends ToolTestBase { } } + @Test + public void testIllegalWSDLImportProtocol() throws Exception { + String[] args = new String[] {"-verbose", + getLocation("/validator_wsdl/ftp_import.wsdl")}; + WSDLValidator.main(args); + + assertTrue(getStdErr().indexOf("The ftp URI scheme is not allowed") != -1); + } + + @Test + public void testIllegalXSDImportProtocol() throws Exception { + String[] args = new String[] {"-verbose", + getLocation("/validator_wsdl/ftp_import2.wsdl")}; + WSDLValidator.main(args); + + assertTrue(getStdErr().indexOf("The ftp URI scheme is not allowed") != -1); + } + @Override protected String getLocation(String wsdlFile) throws Exception { Enumeration<URL> e = WSDLValidationTest.class.getClassLoader().getResources(wsdlFile); @@ -226,4 +244,4 @@ public class WSDLValidationTest extends ToolTestBase { return WSDLValidationTest.class.getResource(wsdlFile).toURI().getPath(); } -} \ No newline at end of file +} diff --git a/tools/validator/src/test/resources/validator_wsdl/ftp_import.wsdl b/tools/validator/src/test/resources/validator_wsdl/ftp_import.wsdl new file mode 100644 index 0000000..370cf00 --- /dev/null +++ b/tools/validator/src/test/resources/validator_wsdl/ftp_import.wsdl @@ -0,0 +1,59 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + 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. +--> +<definitions xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:tns="http://www.iona.com/artix/defaults" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="defaults.wsdl" targetNamespace="http://www.iona.com/artix/defaults"> + <import location="ftp://localhost:12345" namespace="http://www.example.org/contract/DoubleIt"/> + <types> + <xsd:schema xmlns="http://www.iona.com/artix/defaults" xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.iona.com/artix/defaults"> + <xsd:complexType name="TestType"> + <xsd:sequence> + <xsd:element maxOccurs="1" minOccurs="1" name="msg" type="xsd:string"/> + <xsd:element maxOccurs="1" minOccurs="1" name="num" type="xsd:int"/> + </xsd:sequence> + </xsd:complexType> + <xsd:element name="Test" type="TestType"/> + </xsd:schema> + </types> + <message name="TestMessage"> + <part element="tns:Test" name="params"/> + </message> + <portType name="TestPortType"> + <operation name="Test"> + <input message="tns:TestMessage"/> + <output message="tns:TestMessage"/> + </operation> + </portType> + <binding name="TestPortTypeDefaults" type="tns:TestPortType"> + <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/> + <operation name="Test"> + <soap:operation soapAction="" style="document"/> + <input name="TestRequest"> + <soap:body use="literal"/> + </input> + <output name="TestResponse"> + <soap:body use="literal"/> + </output> + </operation> + </binding> + <service name="TestService"> + <port binding="tns:TestPortTypeDefaults" name="TestPort"> + <soap:address location="http://localhost:9100/TestService"/> + </port> + </service> +</definitions> diff --git a/tools/validator/src/test/resources/validator_wsdl/ftp_import2.wsdl b/tools/validator/src/test/resources/validator_wsdl/ftp_import2.wsdl new file mode 100644 index 0000000..abdde94 --- /dev/null +++ b/tools/validator/src/test/resources/validator_wsdl/ftp_import2.wsdl @@ -0,0 +1,59 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + 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. +--> +<definitions xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:tns="http://www.iona.com/artix/defaults" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="defaults.wsdl" targetNamespace="http://www.iona.com/artix/defaults"> + <types> + <xsd:schema xmlns="http://www.iona.com/artix/defaults" xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.iona.com/artix/defaults"> + <xsd:import schemaLocation="ftp://localhost:12345" namespace="http://www.example.org/contract/DoubleIt"/> + <xsd:complexType name="TestType"> + <xsd:sequence> + <xsd:element maxOccurs="1" minOccurs="1" name="msg" type="xsd:string"/> + <xsd:element maxOccurs="1" minOccurs="1" name="num" type="xsd:int"/> + </xsd:sequence> + </xsd:complexType> + <xsd:element name="Test" type="TestType"/> + </xsd:schema> + </types> + <message name="TestMessage"> + <part element="tns:Test" name="params"/> + </message> + <portType name="TestPortType"> + <operation name="Test"> + <input message="tns:TestMessage"/> + <output message="tns:TestMessage"/> + </operation> + </portType> + <binding name="TestPortTypeDefaults" type="tns:TestPortType"> + <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/> + <operation name="Test"> + <soap:operation soapAction="" style="document"/> + <input name="TestRequest"> + <soap:body use="literal"/> + </input> + <output name="TestResponse"> + <soap:body use="literal"/> + </output> + </operation> + </binding> + <service name="TestService"> + <port binding="tns:TestPortTypeDefaults" name="TestPort"> + <soap:address location="http://localhost:9100/TestService"/> + </port> + </service> +</definitions>
