diff --git a/modules/library/main/src/main/java/org/geotools/xml/NoExternalEntityResolver.java b/modules/library/main/src/main/java/org/geotools/xml/NoExternalEntityResolver.java new file mode 100644 index 00000000000..03d15d96d81 --- /dev/null +++ b/modules/library/main/src/main/java/org/geotools/xml/NoExternalEntityResolver.java @@ -0,0 +1,78 @@ +/* + * GeoTools - The Open Source Java GIS Toolkit + * http://geotools.org + * + * (C) 2016, Open Source Geospatial Foundation (OSGeo) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + */ +package org.geotools.xml; + +import java.io.IOException; +import java.io.Serializable; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.geotools.util.logging.Logging; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.ext.EntityResolver2; + + +/** + * EntityResolver implementation to prevent usage of external entities. + * + * When parsing an XML entity, the empty InputSource returned by this resolver provokes + * throwing of a java.net.MalformedURLException, which can be handled appropriately. + * + * @author Davide Savazzi - geo-solutions.it + */ +public class NoExternalEntityResolver implements EntityResolver2, Serializable { + + private static final long serialVersionUID = -8477717248646603150L; + public static final String ERROR_MESSAGE_BASE = "Entity resolution disallowed for "; + private static final Logger LOGGER = Logging.getLogger(NoExternalEntityResolver.class); + public static final NoExternalEntityResolver INSTANCE = new NoExternalEntityResolver(); + + protected NoExternalEntityResolver() { + // singleton + } + + @Override + public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException { + if (LOGGER.isLoggable(Level.FINEST)) { + LOGGER.finest("resolveEntity request: publicId=" + publicId + ", systemId=" + systemId); + } + + // allow schema parsing for validation. + // http(s) - external schema reference + // jar - internal schema reference + // vfs - internal schema reference (JBOSS) + if (systemId != null && systemId.matches("(?i)(jar:file|http|vfs)[^?#;]*\\.xsd")) { + return null; + } + + // do not allow external entities + throw new SAXException(ERROR_MESSAGE_BASE + systemId); + } + + @Override + public InputSource getExternalSubset(String name, String baseURI) + throws SAXException, IOException { + return null; + } + + @Override + public InputSource resolveEntity(String name, String publicId, String baseURI, String systemId) + throws SAXException, IOException { + return resolveEntity(publicId, systemId); + } +} \ No newline at end of file diff --git a/modules/unsupported/wfs-ng/src/main/java/org/geotools/data/wfs/WFSDataStore.java b/modules/unsupported/wfs-ng/src/main/java/org/geotools/data/wfs/WFSDataStore.java index d35df03ee44..cf2eb4ca489 100644 --- a/modules/unsupported/wfs-ng/src/main/java/org/geotools/data/wfs/WFSDataStore.java +++ b/modules/unsupported/wfs-ng/src/main/java/org/geotools/data/wfs/WFSDataStore.java @@ -53,6 +53,7 @@ import org.opengis.feature.simple.SimpleFeatureType; import org.opengis.feature.type.FeatureType; import org.opengis.feature.type.Name; +import org.xml.sax.EntityResolver; import com.vividsolutions.jts.geom.GeometryFactory; import com.vividsolutions.jts.geom.impl.PackedCoordinateSequenceFactory; @@ -73,7 +74,7 @@ public class WFSDataStore extends ContentDataStore { protected Map configuredStoredQueries = new ConcurrentHashMap(); - + public WFSDataStore(final WFSClient client) { this.client = client; this.names = new ConcurrentHashMap(); @@ -94,7 +95,7 @@ public WFSDataStore(final WFSClient client) { public WFSServiceInfo getInfo() { return client.getInfo(); } - + @Override protected WFSContentState createContentState(ContentEntry entry) { return new WFSContentState(entry); diff --git a/modules/unsupported/wfs-ng/src/main/java/org/geotools/data/wfs/impl/WFSDataAccessFactory.java b/modules/unsupported/wfs-ng/src/main/java/org/geotools/data/wfs/impl/WFSDataAccessFactory.java index 9c046bc0148..1c5e7cfd981 100644 --- a/modules/unsupported/wfs-ng/src/main/java/org/geotools/data/wfs/impl/WFSDataAccessFactory.java +++ b/modules/unsupported/wfs-ng/src/main/java/org/geotools/data/wfs/impl/WFSDataAccessFactory.java @@ -42,9 +42,11 @@ import org.geotools.ows.ServiceException; import org.geotools.util.KVP; import org.geotools.util.SimpleInternationalString; +import org.geotools.xml.NoExternalEntityResolver; import org.geotools.xml.XMLHandlerHints; import org.opengis.feature.Feature; import org.opengis.feature.type.FeatureType; +import org.xml.sax.EntityResolver; /** * The factory responsible for creating WFSDataAccess objects based on their capabilities and the configuration file used. This file is included as a @@ -119,7 +121,7 @@ public T lookUp(final Map params) throws IOException { } /** Access with {@link WFSDataStoreFactory#getParametersInfo() */ - private static final WFSFactoryParam[] parametersInfo = new WFSFactoryParam[19]; + private static final WFSFactoryParam[] parametersInfo = new WFSFactoryParam[20]; private static final int GMLComplianceLevel = 2; @@ -412,6 +414,18 @@ public T lookUp(final Map params) throws IOException { parametersInfo[18] = GML_COMPATIBLE_TYPENAMES = new WFSFactoryParam(name, Boolean.class, title, description, false); } + + /** + * Optional {@link EntityResolver} used to expand XML entities during parses + */ + public static final WFSFactoryParam ENTITY_RESOLVER; + static { + String name = "WFSDataStoreFactory:ENTITY_RESOLVER"; + String title = "EntityResolver"; + String description = "Sets the entity resolver used to expand XML entities"; + parametersInfo[19] = ENTITY_RESOLVER = new WFSFactoryParam(name, + EntityResolver.class, title, description, NoExternalEntityResolver.INSTANCE, Parameter.LEVEL, "program"); + } /** diff --git a/modules/unsupported/wfs-ng/src/main/java/org/geotools/data/wfs/internal/GetCapabilitiesRequest.java b/modules/unsupported/wfs-ng/src/main/java/org/geotools/data/wfs/internal/GetCapabilitiesRequest.java index 4236f8fe906..cea41b8103d 100644 --- a/modules/unsupported/wfs-ng/src/main/java/org/geotools/data/wfs/internal/GetCapabilitiesRequest.java +++ b/modules/unsupported/wfs-ng/src/main/java/org/geotools/data/wfs/internal/GetCapabilitiesRequest.java @@ -18,12 +18,15 @@ import java.io.IOException; import java.net.URL; +import java.util.Map; import org.geotools.data.ows.AbstractGetCapabilitiesRequest; import org.geotools.data.ows.HTTPResponse; import org.geotools.data.ows.Request; import org.geotools.data.ows.Response; import org.geotools.ows.ServiceException; +import org.geotools.xml.XMLHandlerHints; +import org.xml.sax.EntityResolver; public class GetCapabilitiesRequest extends AbstractGetCapabilitiesRequest { @@ -48,7 +51,12 @@ protected void initVersion() { @Override public Response createResponse(HTTPResponse response) throws ServiceException, IOException { - return new GetCapabilitiesResponse(response); + Map hints = getRequestHints(); + EntityResolver resolver = null; + if(hints != null) { + resolver = (EntityResolver) hints.get(XMLHandlerHints.ENTITY_RESOLVER); + } + return new GetCapabilitiesResponse(response, resolver); } } diff --git a/modules/unsupported/wfs-ng/src/main/java/org/geotools/data/wfs/internal/GetCapabilitiesResponse.java b/modules/unsupported/wfs-ng/src/main/java/org/geotools/data/wfs/internal/GetCapabilitiesResponse.java index f8d5fed352c..0dcabd0abb5 100644 --- a/modules/unsupported/wfs-ng/src/main/java/org/geotools/data/wfs/internal/GetCapabilitiesResponse.java +++ b/modules/unsupported/wfs-ng/src/main/java/org/geotools/data/wfs/internal/GetCapabilitiesResponse.java @@ -45,12 +45,17 @@ import org.geotools.xml.Configuration; import org.geotools.xml.DOMParser; import org.w3c.dom.Document; +import org.xml.sax.EntityResolver; public class GetCapabilitiesResponse extends org.geotools.data.ows.GetCapabilitiesResponse { private WFSGetCapabilities capabilities; - - public GetCapabilitiesResponse(HTTPResponse response) throws IOException, ServiceException { + +// public GetCapabilitiesResponse(HTTPResponse response) throws IOException, ServiceException { +// this(response, null); +// } + + public GetCapabilitiesResponse(HTTPResponse response, EntityResolver entityResolver) throws IOException, ServiceException { super(response); MODULE.finer("Parsing GetCapabilities response"); try { @@ -74,6 +79,9 @@ public GetCapabilitiesResponse(HTTPResponse response) throws IOException, Servic builderFactory.setNamespaceAware(true); builderFactory.setValidating(false); DocumentBuilder documentBuilder = builderFactory.newDocumentBuilder(); + if(entityResolver != null) { + documentBuilder.setEntityResolver(entityResolver); + } rawDocument = documentBuilder.parse(new ByteArrayInputStream(rawResponse)); } catch (Exception e) { throw new IOException("Error parsing capabilities document: " + e.getMessage(), e); diff --git a/modules/unsupported/wfs-ng/src/main/java/org/geotools/data/wfs/internal/WFSClient.java b/modules/unsupported/wfs-ng/src/main/java/org/geotools/data/wfs/internal/WFSClient.java index a1631a61952..42e167397b7 100644 --- a/modules/unsupported/wfs-ng/src/main/java/org/geotools/data/wfs/internal/WFSClient.java +++ b/modules/unsupported/wfs-ng/src/main/java/org/geotools/data/wfs/internal/WFSClient.java @@ -20,6 +20,7 @@ import java.io.IOException; import java.net.URL; +import java.util.Collections; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; @@ -44,6 +45,7 @@ import org.geotools.ows.ServiceException; import org.geotools.util.Version; import org.geotools.util.logging.Logging; +import org.geotools.xml.XMLHandlerHints; import org.opengis.filter.Filter; import org.opengis.referencing.crs.CoordinateReferenceSystem; import org.w3c.dom.Document; @@ -65,7 +67,7 @@ public WFSClient(URL capabilitiesURL, HTTPClient httpClient, WFSConfig config) public WFSClient(URL capabilitiesURL, HTTPClient httpClient, WFSConfig config, WFSGetCapabilities capabilities) throws IOException, ServiceException { - super(capabilitiesURL, httpClient, capabilities); + super(capabilitiesURL, httpClient, capabilities, Collections.singletonMap(XMLHandlerHints.ENTITY_RESOLVER, config.getEntityResolver())); this.config = config; super.specification = determineCorrectStrategy(); ((WFSStrategy) specification).setCapabilities(super.capabilities); diff --git a/modules/unsupported/wfs-ng/src/main/java/org/geotools/data/wfs/internal/WFSConfig.java b/modules/unsupported/wfs-ng/src/main/java/org/geotools/data/wfs/internal/WFSConfig.java index 4af5de2049c..e49b8a8613d 100644 --- a/modules/unsupported/wfs-ng/src/main/java/org/geotools/data/wfs/internal/WFSConfig.java +++ b/modules/unsupported/wfs-ng/src/main/java/org/geotools/data/wfs/internal/WFSConfig.java @@ -32,6 +32,7 @@ import static org.geotools.data.wfs.WFSDataStoreFactory.AXIS_ORDER; import static org.geotools.data.wfs.WFSDataStoreFactory.AXIS_ORDER_FILTER; import static org.geotools.data.wfs.WFSDataStoreFactory.GML_COMPATIBLE_TYPENAMES; +import static org.geotools.data.wfs.WFSDataStoreFactory.ENTITY_RESOLVER; import java.io.IOException; import java.nio.charset.Charset; @@ -46,6 +47,7 @@ import org.geotools.referencing.CRS; import org.opengis.feature.type.Name; import org.opengis.referencing.crs.CoordinateReferenceSystem; +import org.xml.sax.EntityResolver; /** * @see WFSStrategy#setConfig(WFSConfig) @@ -85,6 +87,8 @@ public class WFSConfig { protected String axisOrderFilter; protected boolean gmlCompatibleTypenames; + + protected EntityResolver entityResolver; public static enum PreferredHttpMethod { AUTO, HTTP_GET, HTTP_POST @@ -106,6 +110,7 @@ public WFSConfig() { filterCompliance = (Integer) FILTER_COMPLIANCE.getDefaultValue(); namespaceOverride = (String) NAMESPACE.getDefaultValue(); gmlCompatibleTypenames = (Boolean) GML_COMPATIBLE_TYPENAMES.getDefaultValue(); + entityResolver = (EntityResolver) ENTITY_RESOLVER.getDefaultValue(); } public static WFSConfig fromParams(Map params) throws IOException { @@ -142,7 +147,8 @@ public static WFSConfig fromParams(Map params) throws IOException { config.gmlCompatibleTypenames = GML_COMPATIBLE_TYPENAMES.lookUp(params) == null ? (Boolean) GML_COMPATIBLE_TYPENAMES.getDefaultValue() : GML_COMPATIBLE_TYPENAMES.lookUp(params); - + config.entityResolver = ENTITY_RESOLVER.lookUp(params); + return config; } @@ -265,6 +271,14 @@ public String getAxisOrderFilter() { public boolean isGmlCompatibleTypenames() { return gmlCompatibleTypenames; } + + /** + * Returns the entity resolved to be used for XML parses + * @return + */ + public EntityResolver getEntityResolver() { + return entityResolver; + } /** * Checks if axis flipping is needed comparing axis order requested for the DataStore with query crs. @@ -303,4 +317,5 @@ public String localTypeName(QName remoteTypeName) { } return localTypeName; } + } diff --git a/modules/unsupported/wfs-ng/src/main/java/org/geotools/data/wfs/internal/parsers/AbstractGetFeatureResponseParserFactory.java b/modules/unsupported/wfs-ng/src/main/java/org/geotools/data/wfs/internal/parsers/AbstractGetFeatureResponseParserFactory.java index 4e6f66f1482..57069f13297 100644 --- a/modules/unsupported/wfs-ng/src/main/java/org/geotools/data/wfs/internal/parsers/AbstractGetFeatureResponseParserFactory.java +++ b/modules/unsupported/wfs-ng/src/main/java/org/geotools/data/wfs/internal/parsers/AbstractGetFeatureResponseParserFactory.java @@ -43,6 +43,7 @@ import org.geotools.data.wfs.internal.WFSResponseFactory; import org.geotools.ows.ServiceException; import org.geotools.xml.Parser; +import org.xml.sax.EntityResolver; /** * An abstract WFS response parser factory for GetFeature requests in GML output formats. @@ -172,6 +173,10 @@ public WFSResponse createResponse(WFSRequest request, HTTPResponse response) thr */ public WFSException parseException(WFSRequest originatingRequest, InputStream inputStream) throws WFSException { Parser parser = new Parser(originatingRequest.getStrategy().getWfsConfiguration()); + EntityResolver resolver = originatingRequest.getStrategy().getConfig().getEntityResolver(); + if(resolver != null) { + parser.setEntityResolver(resolver); + } Object parsed; try { parsed = parser.parse(inputStream); diff --git a/modules/unsupported/wfs-ng/src/main/java/org/geotools/data/wfs/internal/v1_x/TransactionResponseImpl.java b/modules/unsupported/wfs-ng/src/main/java/org/geotools/data/wfs/internal/v1_x/TransactionResponseImpl.java index ceb7f54ade5..2a5d54b0ae9 100644 --- a/modules/unsupported/wfs-ng/src/main/java/org/geotools/data/wfs/internal/v1_x/TransactionResponseImpl.java +++ b/modules/unsupported/wfs-ng/src/main/java/org/geotools/data/wfs/internal/v1_x/TransactionResponseImpl.java @@ -39,6 +39,7 @@ import org.geotools.xml.Configuration; import org.geotools.xml.Parser; import org.opengis.filter.identity.FeatureId; +import org.xml.sax.EntityResolver; import org.xml.sax.SAXException; public class TransactionResponseImpl extends WFSResponse implements TransactionResponse { @@ -63,6 +64,10 @@ public TransactionResponseImpl(WFSRequest originatingRequest, HTTPResponse respo WFSStrategy strategy = originatingRequest.getStrategy(); Configuration wfsConfiguration = strategy.getWfsConfiguration(); Parser parser = new Parser(wfsConfiguration); + EntityResolver resolver = strategy.getConfig().getEntityResolver(); + if(resolver != null) { + parser.setEntityResolver(resolver); + } InputStream input = response.getResponseStream(); parsed = parser.parse(input); } catch (SAXException e) { diff --git a/modules/unsupported/wfs-ng/src/main/java/org/geotools/data/wfs/internal/v2_0/TransactionResponseImpl.java b/modules/unsupported/wfs-ng/src/main/java/org/geotools/data/wfs/internal/v2_0/TransactionResponseImpl.java index dfc3ce83c78..889c317e672 100644 --- a/modules/unsupported/wfs-ng/src/main/java/org/geotools/data/wfs/internal/v2_0/TransactionResponseImpl.java +++ b/modules/unsupported/wfs-ng/src/main/java/org/geotools/data/wfs/internal/v2_0/TransactionResponseImpl.java @@ -39,6 +39,7 @@ import org.geotools.xml.Configuration; import org.geotools.xml.Parser; import org.opengis.filter.identity.FeatureId; +import org.xml.sax.EntityResolver; import org.xml.sax.SAXException; public class TransactionResponseImpl extends WFSResponse implements TransactionResponse { @@ -63,6 +64,10 @@ public TransactionResponseImpl(WFSRequest originatingRequest, HTTPResponse respo WFSStrategy strategy = originatingRequest.getStrategy(); Configuration wfsConfiguration = strategy.getWfsConfiguration(); Parser parser = new Parser(wfsConfiguration); + EntityResolver resolver = strategy.getConfig().getEntityResolver(); + if(resolver != null) { + parser.setEntityResolver(resolver); + } InputStream input = response.getResponseStream(); parsed = parser.parse(input); } catch (SAXException e) { diff --git a/modules/unsupported/wfs-ng/src/test/java/org/geotools/data/wfs/integration/IntegrationTestWFSClient.java b/modules/unsupported/wfs-ng/src/test/java/org/geotools/data/wfs/integration/IntegrationTestWFSClient.java index 33588123242..cccd3fbbba5 100644 --- a/modules/unsupported/wfs-ng/src/test/java/org/geotools/data/wfs/integration/IntegrationTestWFSClient.java +++ b/modules/unsupported/wfs-ng/src/test/java/org/geotools/data/wfs/integration/IntegrationTestWFSClient.java @@ -72,6 +72,7 @@ import org.geotools.xml.Configuration; import org.geotools.xml.Encoder; import org.geotools.xml.SchemaLocationResolver; +import org.geotools.xml.XMLHandlerHints; import org.geotools.xml.impl.ParserHandler.ContextCustomizer; import org.opengis.feature.simple.SimpleFeature; import org.opengis.feature.simple.SimpleFeatureType; @@ -80,12 +81,13 @@ import org.opengis.filter.FilterFactory2; import org.opengis.filter.identity.FeatureId; import org.picocontainer.MutablePicoContainer; +import org.xml.sax.EntityResolver; import com.vividsolutions.jts.geom.GeometryFactory; public class IntegrationTestWFSClient extends WFSClient { - private URL baseDirectory; + protected URL baseDirectory; private Map diffs = new HashMap(); @@ -103,7 +105,7 @@ public IntegrationTestWFSClient(final String baseDirectory, WFSConfig config) protected Response internalIssueRequest(Request request) throws IOException { try { if (request instanceof GetCapabilitiesRequest) { - return mockCapabilities(); + return mockCapabilities(request); } if (request instanceof DescribeFeatureTypeRequest) { return mockDFT((DescribeFeatureTypeRequest) request); @@ -121,13 +123,17 @@ protected Response internalIssueRequest(Request request) throws IOException { throw new IllegalArgumentException("Unknown request : " + request); } - private Response mockCapabilities() throws IOException, ServiceException { + protected Response mockCapabilities(Request request) throws IOException, ServiceException { HTTPResponse httpResp = new TestHttpResponse("text/xml", "UTF-8", super.serverURL); - return new GetCapabilitiesResponse(httpResp); + EntityResolver resolver = null; + if(hints != null) { + resolver = (EntityResolver) hints.get(XMLHandlerHints.ENTITY_RESOLVER); + } + return new GetCapabilitiesResponse(httpResp, resolver); } - private Response mockDFT(DescribeFeatureTypeRequest request) throws ServiceException, + protected Response mockDFT(DescribeFeatureTypeRequest request) throws ServiceException, IOException { QName typeName = request.getTypeName(); @@ -144,7 +150,7 @@ private Response mockDFT(DescribeFeatureTypeRequest request) throws ServiceExcep return ret; } - private Response mockGetFeature(GetFeatureRequest request) throws IOException { + protected Response mockGetFeature(GetFeatureRequest request) throws IOException { final QName typeName = request.getTypeName(); @@ -284,7 +290,7 @@ public void close() throws IOException { } } - private Response mockTransaction(TransactionRequest request) throws IOException { + protected Response mockTransaction(TransactionRequest request) throws IOException { List added = new ArrayList(); int deleted = 0, updated = 0; diff --git a/modules/unsupported/wfs-ng/src/test/java/org/geotools/data/wfs/integration/v1_1/XXEProtectionTest.java b/modules/unsupported/wfs-ng/src/test/java/org/geotools/data/wfs/integration/v1_1/XXEProtectionTest.java new file mode 100644 index 00000000000..87c4921c447 --- /dev/null +++ b/modules/unsupported/wfs-ng/src/test/java/org/geotools/data/wfs/integration/v1_1/XXEProtectionTest.java @@ -0,0 +1,114 @@ +/* + * GeoTools - The Open Source Java GIS Toolkit + * http://geotools.org + * + * (C) 2016, Open Source Geospatial Foundation (OSGeo) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + */ +package org.geotools.data.wfs.integration.v1_1; + +import static org.junit.Assert.*; + +import java.net.URL; + +import org.geotools.data.DataUtilities; +import org.geotools.data.ows.HTTPResponse; +import org.geotools.data.simple.SimpleFeatureSource; +import org.geotools.data.simple.SimpleFeatureStore; +import org.geotools.data.wfs.TestHttpResponse; +import org.geotools.data.wfs.WFSDataStore; +import org.geotools.data.wfs.WFSTestData; +import org.geotools.data.wfs.integration.IntegrationTestWFSClient; +import org.geotools.data.wfs.internal.WFSConfig; +import org.junit.Test; +import org.opengis.filter.Filter; +import org.xml.sax.SAXException; + +public class XXEProtectionTest { + + @Test + public void testGetCapabilitiesProtection() throws Exception { + // the default config has entity resolution disabled + WFSConfig config = WFSTestData.getGmlCompatibleConfig(); + + String baseDirectory = "GeoServer_2.0/1.1.0_XXE_GetCapabilities"; + try { + new IntegrationTestWFSClient(baseDirectory, config); + fail("Should have failed with an entity resolution exception"); + } catch(Exception e) { + assertEntityResolutionDisabled(e); + } + } + + private void assertEntityResolutionDisabled(Throwable t) { + if(t instanceof SAXException) { + SAXException se = (SAXException) t; + String message = se.getMessage(); + if(message != null && message.contains("Entity resolution disallowed")) { + // fine, we found the message + return; + } + } + + // if we got here we drill down or fail, the message was not found + if(t.getCause() != null) { + assertEntityResolutionDisabled(t.getCause()); + } else { + fail("Could not find the message about entity resolution disabled"); + } + } + + /** + * The pull parser we use has entity resolution disabled, make sure it stays that way + * @throws Exception + */ + @Test + public void testGetFeatureProtection() throws Exception { + WFSConfig config = WFSTestData.getGmlCompatibleConfig(); + String baseDirectory = "GeoServer_2.0/1.1.0_XXE_GetFeature/"; + IntegrationTestWFSClient client = new IntegrationTestWFSClient(baseDirectory, config); + WFSDataStore store = new WFSDataStore(client); + SimpleFeatureSource fs = store.getFeatureSource(store.getTypeNames()[0]); + try { + DataUtilities.first(fs.getFeatures()); + } catch(Exception e) { + // custom check as MXParser does not use the EntityResolver, does not offer a way to configure it + final String msg = e.getMessage(); + assertNotNull(msg); + assertTrue(msg.contains("could not resolve entity")); + assertTrue(msg.contains("xxe")); + } + } + + @Test + public void testTransactionProtection() throws Exception { + WFSConfig config = WFSTestData.getGmlCompatibleConfig(); + String baseDirectory = "GeoServer_2.0/1.1.0_XXE_Transaction/"; + IntegrationTestWFSClient client = new IntegrationTestWFSClient(baseDirectory, config) { + protected org.geotools.data.ows.Response mockTransaction(org.geotools.data.wfs.internal.TransactionRequest request) throws java.io.IOException { + String resource = "Transaction.xml"; + URL contentUrl = new URL(baseDirectory, resource); + + HTTPResponse httpResp = new TestHttpResponse("text/xml", "UTF-8", contentUrl); + return request.createResponse(httpResp); + + }; + }; + WFSDataStore store = new WFSDataStore(client); + SimpleFeatureStore fs = (SimpleFeatureStore) store.getFeatureSource(store.getTypeNames()[0]); + try { + fs.removeFeatures(Filter.INCLUDE); + } catch(Exception e) { + assertEntityResolutionDisabled(e); + } + } +} diff --git a/modules/unsupported/wfs-ng/src/test/resources/org/geotools/data/wfs/test-data/GeoServer_2.0/1.1.0/DescribeFeatureType_archsites.xsd b/modules/unsupported/wfs-ng/src/test/resources/org/geotools/data/wfs/test-data/GeoServer_2.0/1.1.0/DescribeFeatureType_archsites.xsd index 6115108fa68..bccb01a947c 100644 --- a/modules/unsupported/wfs-ng/src/test/resources/org/geotools/data/wfs/test-data/GeoServer_2.0/1.1.0/DescribeFeatureType_archsites.xsd +++ b/modules/unsupported/wfs-ng/src/test/resources/org/geotools/data/wfs/test-data/GeoServer_2.0/1.1.0/DescribeFeatureType_archsites.xsd @@ -1,4 +1,6 @@ +]> +]> + + + My GeoServer WFS + + This is a description of your Web Feature Server. + + + WFS + WMS + GEOSERVER + + WFS + 1.1.0 + NONE + NONE + + + + + + + + + + + + + + + + 1.0.0 + 1.1.0 + + + text/xml + + + + + + + + + + text/gml; subtype=gml/3.1.1 + + + + + + + + + + + results + hits + + + text/gml; subtype=gml/3.1.1 + text/xml; subtype=gml/2.1.2 + + + + + + + + + + + ALL + SOME + + + + + + + + + + + results + hits + + + text/gml; subtype=gml/3.1.1 + + + + + + + + + + + text/gml; subtype=gml/3.1.1 + + + GenerateNew + UseExisting + ReplaceDuplicate + + + ALL + SOME + + + + + + Query + Insert + Update + Delete + Lock + + + + &xxe; + archsites_Type + Generated from sfArchsites + + archsites sfArchsites + + EPSG:26713 + + GML2 + text/xml; subtype=gml/2.1.2 + GML2-GZIP + text/xml; subtype=gml/3.1.1 + gml3 + SHAPE-ZIP + json + + + + -104 44 + + + -103 45 + + + + + + + + gml:Envelope + gml:Point + + gml:LineString + + gml:Polygon + + + + + + + + + + + + + + + + + LessThan + GreaterThan + LessThanEqualTo + GreaterThanEqualTo + EqualTo + NotEqualTo + Like + Between + NullCheck + + + + + + abs + buffer + within + + + + + + + + + + \ No newline at end of file diff --git a/modules/unsupported/wfs-ng/src/test/resources/org/geotools/data/wfs/test-data/GeoServer_2.0/1.1.0_XXE_GetFeature/DescribeFeatureType_archsites.xsd b/modules/unsupported/wfs-ng/src/test/resources/org/geotools/data/wfs/test-data/GeoServer_2.0/1.1.0_XXE_GetFeature/DescribeFeatureType_archsites.xsd new file mode 100644 index 00000000000..bccb01a947c --- /dev/null +++ b/modules/unsupported/wfs-ng/src/test/resources/org/geotools/data/wfs/test-data/GeoServer_2.0/1.1.0_XXE_GetFeature/DescribeFeatureType_archsites.xsd @@ -0,0 +1,22 @@ + +]> + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/modules/unsupported/wfs-ng/src/test/resources/org/geotools/data/wfs/test-data/GeoServer_2.0/1.1.0_XXE_GetFeature/GetCapabilities.xml b/modules/unsupported/wfs-ng/src/test/resources/org/geotools/data/wfs/test-data/GeoServer_2.0/1.1.0_XXE_GetFeature/GetCapabilities.xml new file mode 100644 index 00000000000..27fa7a74327 --- /dev/null +++ b/modules/unsupported/wfs-ng/src/test/resources/org/geotools/data/wfs/test-data/GeoServer_2.0/1.1.0_XXE_GetFeature/GetCapabilities.xml @@ -0,0 +1,225 @@ + + + + My GeoServer WFS + + This is a description of your Web Feature Server. + + + WFS + WMS + GEOSERVER + + WFS + 1.1.0 + NONE + NONE + + + + + + + + + + + + + + + + 1.0.0 + 1.1.0 + + + text/xml + + + + + + + + + + text/gml; subtype=gml/3.1.1 + + + + + + + + + + + results + hits + + + text/gml; subtype=gml/3.1.1 + text/xml; subtype=gml/2.1.2 + + + + + + + + + + + ALL + SOME + + + + + + + + + + + results + hits + + + text/gml; subtype=gml/3.1.1 + + + + + + + + + + + text/gml; subtype=gml/3.1.1 + + + GenerateNew + UseExisting + ReplaceDuplicate + + + ALL + SOME + + + + + + Query + Insert + Update + Delete + Lock + + + sf:archsites + archsites_Type + Generated from sfArchsites + + archsites sfArchsites + + EPSG:26713 + + GML2 + text/xml; subtype=gml/2.1.2 + GML2-GZIP + text/xml; subtype=gml/3.1.1 + gml3 + SHAPE-ZIP + json + + + + -104 44 + + + -103 45 + + + + + + + + gml:Envelope + gml:Point + + gml:LineString + + gml:Polygon + + + + + + + + + + + + + + + + + LessThan + GreaterThan + LessThanEqualTo + GreaterThanEqualTo + EqualTo + NotEqualTo + Like + Between + NullCheck + + + + + + abs + buffer + within + + + + + + + + + + \ No newline at end of file diff --git a/modules/unsupported/wfs-ng/src/test/resources/org/geotools/data/wfs/test-data/GeoServer_2.0/1.1.0_XXE_GetFeature/GetFeature_archsites.xml b/modules/unsupported/wfs-ng/src/test/resources/org/geotools/data/wfs/test-data/GeoServer_2.0/1.1.0_XXE_GetFeature/GetFeature_archsites.xml new file mode 100644 index 00000000000..10736c8378d --- /dev/null +++ b/modules/unsupported/wfs-ng/src/test/resources/org/geotools/data/wfs/test-data/GeoServer_2.0/1.1.0_XXE_GetFeature/GetFeature_archsites.xml @@ -0,0 +1,35 @@ + +]> + + + + + + 593493.0 4914730.0 + 593493.0 4914730.0 + + + + + 593493.0 4914730.0 + + + 1 + &xxe; + + + \ No newline at end of file diff --git a/modules/unsupported/wfs-ng/src/test/resources/org/geotools/data/wfs/test-data/GeoServer_2.0/1.1.0_XXE_Transaction/DescribeFeatureType_archsites.xsd b/modules/unsupported/wfs-ng/src/test/resources/org/geotools/data/wfs/test-data/GeoServer_2.0/1.1.0_XXE_Transaction/DescribeFeatureType_archsites.xsd new file mode 100644 index 00000000000..bccb01a947c --- /dev/null +++ b/modules/unsupported/wfs-ng/src/test/resources/org/geotools/data/wfs/test-data/GeoServer_2.0/1.1.0_XXE_Transaction/DescribeFeatureType_archsites.xsd @@ -0,0 +1,22 @@ + +]> + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/modules/unsupported/wfs-ng/src/test/resources/org/geotools/data/wfs/test-data/GeoServer_2.0/1.1.0_XXE_Transaction/GetCapabilities.xml b/modules/unsupported/wfs-ng/src/test/resources/org/geotools/data/wfs/test-data/GeoServer_2.0/1.1.0_XXE_Transaction/GetCapabilities.xml new file mode 100644 index 00000000000..27fa7a74327 --- /dev/null +++ b/modules/unsupported/wfs-ng/src/test/resources/org/geotools/data/wfs/test-data/GeoServer_2.0/1.1.0_XXE_Transaction/GetCapabilities.xml @@ -0,0 +1,225 @@ + + + + My GeoServer WFS + + This is a description of your Web Feature Server. + + + WFS + WMS + GEOSERVER + + WFS + 1.1.0 + NONE + NONE + + + + + + + + + + + + + + + + 1.0.0 + 1.1.0 + + + text/xml + + + + + + + + + + text/gml; subtype=gml/3.1.1 + + + + + + + + + + + results + hits + + + text/gml; subtype=gml/3.1.1 + text/xml; subtype=gml/2.1.2 + + + + + + + + + + + ALL + SOME + + + + + + + + + + + results + hits + + + text/gml; subtype=gml/3.1.1 + + + + + + + + + + + text/gml; subtype=gml/3.1.1 + + + GenerateNew + UseExisting + ReplaceDuplicate + + + ALL + SOME + + + + + + Query + Insert + Update + Delete + Lock + + + sf:archsites + archsites_Type + Generated from sfArchsites + + archsites sfArchsites + + EPSG:26713 + + GML2 + text/xml; subtype=gml/2.1.2 + GML2-GZIP + text/xml; subtype=gml/3.1.1 + gml3 + SHAPE-ZIP + json + + + + -104 44 + + + -103 45 + + + + + + + + gml:Envelope + gml:Point + + gml:LineString + + gml:Polygon + + + + + + + + + + + + + + + + + LessThan + GreaterThan + LessThanEqualTo + GreaterThanEqualTo + EqualTo + NotEqualTo + Like + Between + NullCheck + + + + + + abs + buffer + within + + + + + + + + + + \ No newline at end of file diff --git a/modules/unsupported/wfs-ng/src/test/resources/org/geotools/data/wfs/test-data/GeoServer_2.0/1.1.0_XXE_Transaction/GetFeature_archsites.xml b/modules/unsupported/wfs-ng/src/test/resources/org/geotools/data/wfs/test-data/GeoServer_2.0/1.1.0_XXE_Transaction/GetFeature_archsites.xml new file mode 100644 index 00000000000..cb4a7ffdc80 --- /dev/null +++ b/modules/unsupported/wfs-ng/src/test/resources/org/geotools/data/wfs/test-data/GeoServer_2.0/1.1.0_XXE_Transaction/GetFeature_archsites.xml @@ -0,0 +1,33 @@ + + + + + + + 593493.0 4914730.0 + 593493.0 4914730.0 + + + + + 593493.0 4914730.0 + + + 1 + foo + + + \ No newline at end of file diff --git a/modules/unsupported/wfs-ng/src/test/resources/org/geotools/data/wfs/test-data/GeoServer_2.0/1.1.0_XXE_Transaction/Transaction.xml b/modules/unsupported/wfs-ng/src/test/resources/org/geotools/data/wfs/test-data/GeoServer_2.0/1.1.0_XXE_Transaction/Transaction.xml new file mode 100644 index 00000000000..9d5676e8da2 --- /dev/null +++ b/modules/unsupported/wfs-ng/src/test/resources/org/geotools/data/wfs/test-data/GeoServer_2.0/1.1.0_XXE_Transaction/Transaction.xml @@ -0,0 +1,11 @@ + +]> + + + 2 + 0 + &xxe; + + + \ No newline at end of file