Disable URL resolution in DTD declarations
Issue: SPR-11768
This commit is contained in:
@@ -21,6 +21,7 @@ import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.StringReader;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.lang.reflect.GenericArrayType;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
@@ -70,6 +71,7 @@ import javax.xml.validation.SchemaFactory;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.w3c.dom.ls.LSResourceResolver;
|
||||
import org.xml.sax.EntityResolver;
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.XMLReader;
|
||||
@@ -800,7 +802,11 @@ public class Jaxb2Marshaller implements MimeMarshaller, MimeUnmarshaller, Generi
|
||||
if (xmlReader == null) {
|
||||
xmlReader = XMLReaderFactory.createXMLReader();
|
||||
}
|
||||
xmlReader.setFeature("http://xml.org/sax/features/external-general-entities", isProcessExternalEntities());
|
||||
String name = "http://xml.org/sax/features/external-general-entities";
|
||||
xmlReader.setFeature(name, isProcessExternalEntities());
|
||||
if (!isProcessExternalEntities()) {
|
||||
xmlReader.setEntityResolver(NO_OP_ENTITY_RESOLVER);
|
||||
}
|
||||
return new SAXSource(xmlReader, inputSource);
|
||||
}
|
||||
catch (SAXException ex) {
|
||||
@@ -1009,4 +1015,12 @@ public class Jaxb2Marshaller implements MimeMarshaller, MimeUnmarshaller, Generi
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static final EntityResolver NO_OP_ENTITY_RESOLVER = new EntityResolver() {
|
||||
@Override
|
||||
public InputSource resolveEntity(String publicId, String systemId) {
|
||||
return new InputSource(new StringReader(""));
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
import java.io.Writer;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
@@ -42,6 +43,7 @@ import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.w3c.dom.Node;
|
||||
import org.xml.sax.ContentHandler;
|
||||
import org.xml.sax.EntityResolver;
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.XMLReader;
|
||||
@@ -134,6 +136,9 @@ public abstract class AbstractMarshaller implements Marshaller, Unmarshaller {
|
||||
protected XMLReader createXmlReader() throws SAXException {
|
||||
XMLReader xmlReader = XMLReaderFactory.createXMLReader();
|
||||
xmlReader.setFeature("http://xml.org/sax/features/external-general-entities", isProcessExternalEntities());
|
||||
if (!isProcessExternalEntities()) {
|
||||
xmlReader.setEntityResolver(NO_OP_ENTITY_RESOLVER);
|
||||
}
|
||||
return xmlReader;
|
||||
}
|
||||
|
||||
@@ -545,4 +550,12 @@ public abstract class AbstractMarshaller implements Marshaller, Unmarshaller {
|
||||
protected abstract Object unmarshalReader(Reader reader)
|
||||
throws XmlMappingException, IOException;
|
||||
|
||||
|
||||
private static final EntityResolver NO_OP_ENTITY_RESOLVER = new EntityResolver() {
|
||||
@Override
|
||||
public InputSource resolveEntity(String publicId, String systemId) {
|
||||
return new InputSource(new StringReader(""));
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.http.converter.xml;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
@@ -32,6 +33,7 @@ import javax.xml.bind.Unmarshaller;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import javax.xml.bind.annotation.XmlType;
|
||||
import javax.xml.stream.XMLInputFactory;
|
||||
import javax.xml.stream.XMLResolver;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
import javax.xml.stream.XMLStreamReader;
|
||||
import javax.xml.transform.Result;
|
||||
@@ -226,7 +228,16 @@ public class Jaxb2CollectionHttpMessageConverter<T extends Collection>
|
||||
protected XMLInputFactory createXmlInputFactory() {
|
||||
XMLInputFactory inputFactory = XMLInputFactory.newInstance();
|
||||
inputFactory.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, false);
|
||||
inputFactory.setXMLResolver(NO_OP_XML_RESOLVER);
|
||||
return inputFactory;
|
||||
}
|
||||
|
||||
|
||||
private static final XMLResolver NO_OP_XML_RESOLVER = new XMLResolver() {
|
||||
@Override
|
||||
public Object resolveEntity(String publicID, String systemID, String base, String ns) {
|
||||
return new ByteArrayInputStream(new byte[0]);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.springframework.http.converter.xml;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import javax.xml.bind.JAXBElement;
|
||||
import javax.xml.bind.JAXBException;
|
||||
import javax.xml.bind.MarshalException;
|
||||
@@ -38,6 +39,7 @@ import org.springframework.http.converter.HttpMessageConversionException;
|
||||
import org.springframework.http.converter.HttpMessageNotReadableException;
|
||||
import org.springframework.http.converter.HttpMessageNotWritableException;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.xml.sax.EntityResolver;
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.XMLReader;
|
||||
@@ -66,6 +68,10 @@ public class Jaxb2RootElementHttpMessageConverter extends AbstractJaxb2HttpMessa
|
||||
this.processExternalEntities = processExternalEntities;
|
||||
}
|
||||
|
||||
public boolean isProcessExternalEntities() {
|
||||
return this.processExternalEntities;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean canRead(Class<?> clazz, MediaType mediaType) {
|
||||
@@ -113,7 +119,10 @@ public class Jaxb2RootElementHttpMessageConverter extends AbstractJaxb2HttpMessa
|
||||
try {
|
||||
XMLReader xmlReader = XMLReaderFactory.createXMLReader();
|
||||
String featureName = "http://xml.org/sax/features/external-general-entities";
|
||||
xmlReader.setFeature(featureName, this.processExternalEntities);
|
||||
xmlReader.setFeature(featureName, isProcessExternalEntities());
|
||||
if (!isProcessExternalEntities()) {
|
||||
xmlReader.setEntityResolver(NO_OP_ENTITY_RESOLVER);
|
||||
}
|
||||
return new SAXSource(xmlReader, inputSource);
|
||||
}
|
||||
catch (SAXException ex) {
|
||||
@@ -148,4 +157,12 @@ public class Jaxb2RootElementHttpMessageConverter extends AbstractJaxb2HttpMessa
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static final EntityResolver NO_OP_ENTITY_RESOLVER = new EntityResolver() {
|
||||
@Override
|
||||
public InputSource resolveEntity(String publicId, String systemId) {
|
||||
return new InputSource(new StringReader(""));
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -20,11 +20,13 @@ import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.StringReader;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.stream.XMLResolver;
|
||||
import javax.xml.transform.Result;
|
||||
import javax.xml.transform.Source;
|
||||
import javax.xml.transform.TransformerException;
|
||||
@@ -35,6 +37,7 @@ import javax.xml.transform.stream.StreamResult;
|
||||
import javax.xml.transform.stream.StreamSource;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
import org.xml.sax.EntityResolver;
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.XMLReader;
|
||||
@@ -128,8 +131,11 @@ public class SourceHttpMessageConverter<T extends Source> extends AbstractHttpMe
|
||||
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
|
||||
documentBuilderFactory.setNamespaceAware(true);
|
||||
documentBuilderFactory.setFeature(
|
||||
"http://xml.org/sax/features/external-general-entities", this.processExternalEntities);
|
||||
"http://xml.org/sax/features/external-general-entities", isProcessExternalEntities());
|
||||
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
|
||||
if (!isProcessExternalEntities()) {
|
||||
documentBuilder.setEntityResolver(NO_OP_ENTITY_RESOLVER);
|
||||
}
|
||||
Document document = documentBuilder.parse(body);
|
||||
return new DOMSource(document);
|
||||
}
|
||||
@@ -145,8 +151,11 @@ public class SourceHttpMessageConverter<T extends Source> extends AbstractHttpMe
|
||||
try {
|
||||
XMLReader reader = XMLReaderFactory.createXMLReader();
|
||||
reader.setFeature(
|
||||
"http://xml.org/sax/features/external-general-entities", this.processExternalEntities);
|
||||
"http://xml.org/sax/features/external-general-entities", isProcessExternalEntities());
|
||||
byte[] bytes = StreamUtils.copyToByteArray(body);
|
||||
if (!isProcessExternalEntities()) {
|
||||
reader.setEntityResolver(NO_OP_ENTITY_RESOLVER);
|
||||
}
|
||||
return new SAXSource(reader, new InputSource(new ByteArrayInputStream(bytes)));
|
||||
}
|
||||
catch (SAXException ex) {
|
||||
@@ -211,4 +220,19 @@ public class SourceHttpMessageConverter<T extends Source> extends AbstractHttpMe
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static final EntityResolver NO_OP_ENTITY_RESOLVER = new EntityResolver() {
|
||||
@Override
|
||||
public InputSource resolveEntity(String publicId, String systemId) {
|
||||
return new InputSource(new StringReader(""));
|
||||
}
|
||||
};
|
||||
|
||||
private static final XMLResolver NO_OP_XML_RESOLVER = new XMLResolver() {
|
||||
@Override
|
||||
public Object resolveEntity(String publicID, String systemID, String base, String ns) {
|
||||
return new ByteArrayInputStream(new byte[0]);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -100,7 +100,7 @@ public class Jaxb2RootElementHttpMessageConverterTest {
|
||||
@Test
|
||||
public void readXmlRootElementExternalEntityDisabled() throws Exception {
|
||||
Resource external = new ClassPathResource("external.txt", getClass());
|
||||
String content = "<!DOCTYPE root [" +
|
||||
String content = "<!DOCTYPE root SYSTEM \"http://192.168.28.42/1.jsp\" [" +
|
||||
" <!ELEMENT external ANY >\n" +
|
||||
" <!ENTITY ext SYSTEM \"" + external.getURI() + "\" >]>" +
|
||||
" <rootElement><external>&ext;</external></rootElement>";
|
||||
|
||||
@@ -63,7 +63,7 @@ public class SourceHttpMessageConverterTests {
|
||||
public void setUp() throws IOException {
|
||||
converter = new SourceHttpMessageConverter<Source>();
|
||||
Resource external = new ClassPathResource("external.txt", getClass());
|
||||
bodyExternal = "<!DOCTYPE root [" +
|
||||
bodyExternal = "<!DOCTYPE root SYSTEM \"http://192.168.28.42/1.jsp\" [" +
|
||||
" <!ELEMENT root ANY >\n" +
|
||||
" <!ENTITY ext SYSTEM \"" + external.getURI() + "\" >]><root>&ext;</root>";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user