Please find attached a patch which backports the security fix to the
version of Spring present in Debian Wheezy.
diff --git a/debian/patches/CVE-2014-0225.patch b/debian/patches/CVE-2014-0225.patch
new file mode 100644
index 0000000..9fe2e7b
--- /dev/null
+++ b/debian/patches/CVE-2014-0225.patch
@@ -0,0 +1,305 @@
+--- a/projects/org.springframework.oxm/src/main/java/org/springframework/oxm/jaxb/Jaxb2Marshaller.java
++++ b/projects/org.springframework.oxm/src/main/java/org/springframework/oxm/jaxb/Jaxb2Marshaller.java
+@@ -21,6 +21,7 @@
+ 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;
+@@ -69,6 +70,7 @@
+ 
+ import org.apache.commons.logging.Log;
+ import org.apache.commons.logging.LogFactory;
++import org.xml.sax.EntityResolver;
+ import org.xml.sax.InputSource;
+ import org.xml.sax.SAXException;
+ import org.xml.sax.XMLReader;
+@@ -668,8 +670,11 @@
+ 			if (xmlReader == null) {
+ 				xmlReader = XMLReaderFactory.createXMLReader();
+ 			}
+-			xmlReader.setFeature("http://xml.org/sax/features/external-general-entities";,
+-					this.processExternalEntities);
++                        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);
+ 		}
+@@ -865,4 +870,11 @@
+ 		}
+ 	}
+ 
++
++	private static final EntityResolver NO_OP_ENTITY_RESOLVER = new EntityResolver() {
++		public InputSource resolveEntity(String publicId, String systemId) {
++			return new InputSource(new StringReader(""));
++		}
++	};
++
+ }
+--- a/projects/org.springframework.oxm/src/main/java/org/springframework/oxm/support/AbstractMarshaller.java
++++ b/projects/org.springframework.oxm/src/main/java/org/springframework/oxm/support/AbstractMarshaller.java
+@@ -20,6 +20,7 @@
+ 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.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;
+@@ -203,6 +205,9 @@
+ 	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;
+ 	}
+ 
+@@ -563,4 +568,11 @@
+ 	protected abstract Object unmarshalSaxReader(XMLReader xmlReader, InputSource inputSource)
+ 			throws XmlMappingException, IOException;
+ 
++
++	private static final EntityResolver NO_OP_ENTITY_RESOLVER = new EntityResolver() {
++		public InputSource resolveEntity(String publicId, String systemId) {
++			return new InputSource(new StringReader(""));
++		}
++	};
++
+ }
+--- a/projects/org.springframework.web/src/main/java/org/springframework/http/converter/xml/Jaxb2RootElementHttpMessageConverter.java
++++ b/projects/org.springframework.web/src/main/java/org/springframework/http/converter/xml/Jaxb2RootElementHttpMessageConverter.java
+@@ -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;
+@@ -28,6 +29,8 @@
+ import javax.xml.bind.annotation.XmlType;
+ import javax.xml.transform.Result;
+ import javax.xml.transform.Source;
++import javax.xml.transform.sax.SAXSource;
++import javax.xml.transform.stream.StreamSource;
+ 
+ import org.springframework.core.annotation.AnnotationUtils;
+ import org.springframework.http.HttpHeaders;
+@@ -36,6 +39,11 @@
+ 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;
++import org.xml.sax.helpers.XMLReaderFactory;
+ 
+ /**
+  * Implementation of {@link org.springframework.http.converter.HttpMessageConverter HttpMessageConverter} that can read
+@@ -49,6 +57,21 @@
+  */
+ public class Jaxb2RootElementHttpMessageConverter extends AbstractJaxb2HttpMessageConverter<Object> {
+ 
++	private boolean processExternalEntities = false;
++
++
++	/**
++	 * Indicates whether external XML entities are processed when converting to a Source.
++	 * <p>Default is {@code false}, meaning that external entities are not resolved.
++	 */
++	public void setProcessExternalEntities(boolean processExternalEntities) {
++		this.processExternalEntities = processExternalEntities;
++	}
++
++	public boolean isProcessExternalEntities() {
++		return this.processExternalEntities;
++	}
++
+ 	@Override
+ 	public boolean canRead(Class<?> clazz, MediaType mediaType) {
+ 		return (clazz.isAnnotationPresent(XmlRootElement.class) || clazz.isAnnotationPresent(XmlType.class)) &&
+@@ -69,6 +92,7 @@
+ 	@Override
+ 	protected Object readFromSource(Class<?> clazz, HttpHeaders headers, Source source) throws IOException {
+ 		try {
++			source = processSource(source);
+ 			Unmarshaller unmarshaller = createUnmarshaller(clazz);
+ 			if (clazz.isAnnotationPresent(XmlRootElement.class)) {
+ 				return unmarshaller.unmarshal(source);
+@@ -87,6 +111,29 @@
+ 		}
+ 	}
+ 
++	protected Source processSource(Source source) {
++		if (source instanceof StreamSource) {
++			StreamSource streamSource = (StreamSource) source;
++			InputSource inputSource = new InputSource(streamSource.getInputStream());
++			try {
++				XMLReader xmlReader = XMLReaderFactory.createXMLReader();
++				String featureName = "http://xml.org/sax/features/external-general-entities";;
++				xmlReader.setFeature(featureName, isProcessExternalEntities());
++				if (!isProcessExternalEntities()) {
++					xmlReader.setEntityResolver(NO_OP_ENTITY_RESOLVER);
++				}
++				return new SAXSource(xmlReader, inputSource);
++			}
++			catch (SAXException ex) {
++				logger.warn("Processing of external entities could not be disabled", ex);
++				return source;
++			}
++		}
++		else {
++			return source;
++		}
++	}
++
+ 	@Override
+ 	protected void writeToResult(Object o, HttpHeaders headers, Result result) throws IOException {
+ 		try {
+@@ -109,4 +156,11 @@
+ 		}
+ 	}
+ 
++
++	private static final EntityResolver NO_OP_ENTITY_RESOLVER = new EntityResolver() {
++		public InputSource resolveEntity(String publicId, String systemId) {
++			return new InputSource(new StringReader(""));
++		}
++	};
++
+ }
+--- a/projects/org.springframework.web/src/main/java/org/springframework/http/converter/xml/SourceHttpMessageConverter.java
++++ b/projects/org.springframework.web/src/main/java/org/springframework/http/converter/xml/SourceHttpMessageConverter.java
+@@ -21,9 +21,11 @@
+ import java.io.IOException;
+ import java.io.InputStream;
+ import java.io.OutputStream;
++import java.io.StringReader;
+ import javax.xml.parsers.DocumentBuilder;
+ import javax.xml.parsers.DocumentBuilderFactory;
+ import javax.xml.parsers.ParserConfigurationException;
++import javax.xml.stream.XMLResolver;
+ import javax.xml.stream.XMLInputFactory;
+ import javax.xml.stream.XMLStreamException;
+ import javax.xml.stream.XMLStreamReader;
+@@ -38,6 +40,7 @@
+ 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;
+@@ -125,8 +128,11 @@
+         try {
+             DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
+             documentBuilderFactory.setNamespaceAware(true);
+-            documentBuilderFactory.setFeature("http://xml.org/sax/features/external-general-entities";, processExternalEntities);
++            documentBuilderFactory.setFeature("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);
+         }
+@@ -141,8 +147,11 @@
+     private SAXSource readSAXSource(InputStream body) throws IOException {
+         try {
+             XMLReader reader = XMLReaderFactory.createXMLReader();
+-            reader.setFeature("http://xml.org/sax/features/external-general-entities";, processExternalEntities);
++            reader.setFeature("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) {
+@@ -219,4 +228,17 @@
+ 		}
+ 	}
+ 
++
++	private static final EntityResolver NO_OP_ENTITY_RESOLVER = new EntityResolver() {
++		public InputSource resolveEntity(String publicId, String systemId) {
++			return new InputSource(new StringReader(""));
++		}
++	};
++
++	private static final XMLResolver NO_OP_XML_RESOLVER = new XMLResolver() {
++		public Object resolveEntity(String publicID, String systemID, String base, String ns) {
++			return new ByteArrayInputStream(new byte[0]);
++		}
++	};
++
+ }
+--- a/projects/org.springframework.web/src/test/java/org/springframework/http/converter/xml/Jaxb2RootElementHttpMessageConverterTest.java
++++ b/projects/org.springframework.web/src/test/java/org/springframework/http/converter/xml/Jaxb2RootElementHttpMessageConverterTest.java
+@@ -98,6 +98,33 @@
+ 		assertEquals("Invalid result", "Hello World", result.s);
+ 	}
+ 
++        @Test
++	public void readXmlRootElementExternalEntityDisabled() throws Exception {
++		Resource external = new ClassPathResource("external.txt", getClass());
++		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>";
++		MockHttpInputMessage inputMessage = new MockHttpInputMessage(content.getBytes("UTF-8"));
++		RootElement rootElement = (RootElement) converter.read(RootElement.class, inputMessage);
++
++		assertEquals("", rootElement.external);
++	}
++
++	@Test
++	public void readXmlRootElementExternalEntityEnabled() throws Exception {
++		Resource external = new ClassPathResource("external.txt", getClass());
++		String content =  "<!DOCTYPE root [" +
++				"  <!ELEMENT external ANY >\n" +
++				"  <!ENTITY ext SYSTEM \"" + external.getURI() + "\" >]>" +
++				"  <rootElement><external>&ext;</external></rootElement>";
++		MockHttpInputMessage inputMessage = new MockHttpInputMessage(content.getBytes("UTF-8"));
++		this.converter.setProcessExternalEntities(true);
++		RootElement rootElement = (RootElement) converter.read(RootElement.class, inputMessage);
++
++		assertEquals("Foo Bar", rootElement.external);
++	}
++
+ 	@Test
+ 	public void writeXmlRootElement() throws Exception {
+ 		MockHttpOutputMessage outputMessage = new MockHttpOutputMessage();
+--- a/projects/org.springframework.web/src/test/java/org/springframework/http/converter/xml/SourceHttpMessageConverterTests.java
++++ b/projects/org.springframework.web/src/test/java/org/springframework/http/converter/xml/SourceHttpMessageConverterTests.java
+@@ -67,9 +67,10 @@
+ 		converter = new SourceHttpMessageConverter<Source>();
+ 		Resource external = new ClassPathResource("external.txt", getClass());
+ 
+-		bodyExternal = "<!DOCTYPE root [" +
+-				"  <!ELEMENT root ANY >\n" +
+-				"  <!ENTITY ext SYSTEM \"" + external.getURI() + "\" >]><root>&ext;</root>";
++                bodyExternal = "<!DOCTYPE root SYSTEM \"http://192.168.28.42/1.jsp\"; [" +
++                                "  <!ELEMENT root ANY >\n" +
++                                "  <!ENTITY ext SYSTEM \"" + external.getURI() + "\" >]><root>&ext;</root>";
++
+ 	}
+ 
+ 	@Test
diff --git a/debian/patches/series b/debian/patches/series
index 16c66b6..b41827d 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -12,3 +12,4 @@ CVE-2013-6429.patch
 CVE-2013-6430.patch
 CVE-2014-0054.patch
 CVE-2014-1904.patch
+CVE-2014-0225.patch
__
This is the maintainer address of Debian's Java team
<http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pkg-java-maintainers>. 
Please use
debian-j...@lists.debian.org for discussions and questions.

Reply via email to