This is an automated email from the git hooks/post-receive script. jamespage pushed a commit to branch master in repository lucene-solr.
commit d2d82454b5dbe797773c64164000d06a68225c39 Author: James Page <[email protected]> Date: Fri Dec 6 12:29:41 2013 +0000 Fixes for new security vulnerabilities (Closes: #731113): * Fixes for new security vulnerabilities (Closes: #731113): - debian/patches/CVE-2013-6397.patch: Fix DocumentAnalysisRequestHandler to correctly use EmptyEntityResolver to prevent loading of external entities like UpdateRequestHandler does. CVE-2013-6397 - debian/patches/CVE-2013-6407_CVE-2013-6408.patch: XML and XSLT UpdateRequestHandler should not try to resolve external entities. This improves speed of loading e.g. XSL-transformed XHTML documents. CVE-2013-6407 Fix XML parsing in XPathEntityProcessor to correctly expand named entities, but ignore external entities. CVE-2013-6408 --- debian/changelog | 19 + debian/patches/CVE-2013-6397.patch | 177 +++++++++ debian/patches/CVE-2013-6407_CVE-2013-6408.patch | 480 +++++++++++++++++++++++ debian/patches/series | 2 + 4 files changed, 678 insertions(+) diff --git a/debian/changelog b/debian/changelog index 9ce056a..415a4ed 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,22 @@ +lucene-solr (3.6.2+dfsg-2) UNRELEASED; urgency=low + + * Fixes for new security vulnerabilities (Closes: #731113): + - debian/patches/CVE-2013-6397.patch: + Fix DocumentAnalysisRequestHandler to correctly use + EmptyEntityResolver to prevent loading of external entities like + UpdateRequestHandler does. + CVE-2013-6397 + - debian/patches/CVE-2013-6407_CVE-2013-6408.patch: + XML and XSLT UpdateRequestHandler should not try to + resolve external entities. This improves speed of loading e.g. + XSL-transformed XHTML documents. + CVE-2013-6407 + Fix XML parsing in XPathEntityProcessor to correctly + expand named entities, but ignore external entities. + CVE-2013-6408 + + -- James Page <[email protected]> Fri, 06 Dec 2013 12:25:26 +0000 + lucene-solr (3.6.2+dfsg-1) unstable; urgency=low * Upload to unstable. diff --git a/debian/patches/CVE-2013-6397.patch b/debian/patches/CVE-2013-6397.patch new file mode 100644 index 0000000..d26a1b1 --- /dev/null +++ b/debian/patches/CVE-2013-6397.patch @@ -0,0 +1,177 @@ +Description: Fix for CVE-2013-6397 +Origin: https://issues.apache.org/jira/browse/SOLR-4882 + +--- a/solr/contrib/velocity/src/java/org/apache/solr/response/VelocityResponseWriter.java ++++ b/solr/contrib/velocity/src/java/org/apache/solr/response/VelocityResponseWriter.java +@@ -64,7 +64,6 @@ public class VelocityResponseWriter impl + } catch (ClassCastException e) { + // known edge case where QueryResponse's extraction assumes "response" is a SolrDocumentList + // (AnalysisRequestHandler emits a "response") +- e.printStackTrace(); + rsp = new SolrResponseBase(); + rsp.setResponse(parsedResponse); + } +@@ -123,6 +122,7 @@ public class VelocityResponseWriter impl + SolrVelocityResourceLoader resourceLoader = + new SolrVelocityResourceLoader(request.getCore().getSolrConfig().getResourceLoader()); + engine.setProperty("solr.resource.loader.instance", resourceLoader); ++ engine.setProperty(RuntimeConstants.RESOURCE_LOADER, "params,solr"); + + // TODO: Externalize Velocity properties + engine.setProperty(RuntimeConstants.RESOURCE_LOADER, "params,file,solr"); +--- a/solr/core/src/java/org/apache/solr/core/SolrResourceLoader.java ++++ b/solr/core/src/java/org/apache/solr/core/SolrResourceLoader.java +@@ -25,6 +25,7 @@ import java.io.IOException; + import java.io.InputStream; + import java.io.InputStreamReader; + import java.net.MalformedURLException; ++import java.net.URI; + import java.net.URL; + import java.net.URLClassLoader; + import java.util.*; +@@ -212,7 +213,7 @@ public class SolrResourceLoader implemen + } + + public String getConfigDir() { +- return instanceDir + "conf/"; ++ return instanceDir + "conf" + File.separator; + } + + public String getDataDir() { +@@ -250,27 +251,46 @@ public class SolrResourceLoader implemen + public InputStream openResource(String resource) { + InputStream is=null; + try { +- File f0 = new File(resource); +- File f = f0; ++ File f0 = new File(resource), f = f0; + if (!f.isAbsolute()) { + // try $CWD/$configDir/$resource +- f = new File(getConfigDir() + resource); ++ f = new File(getConfigDir() + resource).getAbsoluteFile(); + } +- if (f.isFile() && f.canRead()) { ++ boolean found = f.isFile() && f.canRead(); ++ if (!found) { // no success with $CWD/$configDir/$resource ++ f = f0.getAbsoluteFile(); ++ found = f.isFile() && f.canRead(); ++ } ++ // check that we don't escape instance dir ++ if (found) { ++ if (!Boolean.parseBoolean(System.getProperty("solr.allow.unsafe.resourceloading", "false"))) { ++ final URI instanceURI = new File(getInstanceDir()).getAbsoluteFile().toURI().normalize(); ++ final URI fileURI = f.toURI().normalize(); ++ if (instanceURI.relativize(fileURI) == fileURI) { ++ // no URI relativize possible, so they don't share same base folder ++ throw new RuntimeException("For security reasons, SolrResourceLoader cannot load files from outside the instance's directory: " + f + ++ "; if you want to override this safety feature and you are sure about the consequences, you can pass the system property "+ ++ "-Dsolr.allow.unsafe.resourceloading=true to your JVM"); ++ } ++ } ++ // relativize() returned a relative, new URI, so we are fine! + return new FileInputStream(f); +- } else if (f != f0) { // no success with $CWD/$configDir/$resource +- if (f0.isFile() && f0.canRead()) +- return new FileInputStream(f0); + } +- // delegate to the class loader (looking into $INSTANCE_DIR/lib jars) +- is = classLoader.getResourceAsStream(resource); +- if (is == null) +- is = classLoader.getResourceAsStream(getConfigDir() + resource); ++ // Delegate to the class loader (looking into $INSTANCE_DIR/lib jars). ++ // We need a ClassLoader-compatible (forward-slashes) path here! ++ is = classLoader.getResourceAsStream(resource.replace(File.separatorChar, '/')); ++ // This is a hack just for tests (it is not done in ZKResourceLoader)! ++ // -> the getConfigDir's path must not be absolute! ++ if (is == null && System.getProperty("jetty.testMode") != null && !new File(getConfigDir()).isAbsolute()) { ++ is = classLoader.getResourceAsStream((getConfigDir() + resource).replace(File.separatorChar, '/')); ++ } ++ } catch (RuntimeException re) { ++ throw re; // preserve original Exception + } catch (Exception e) { + throw new RuntimeException("Error opening " + resource, e); + } + if (is==null) { +- throw new RuntimeException("Can't find resource '" + resource + "' in classpath or '" + getConfigDir() + "', cwd="+System.getProperty("user.dir")); ++ throw new RuntimeException("Can't find resource '" + resource + "' in classpath or '" + new File(getConfigDir()).getAbsolutePath() + "'"); + } + return is; + } +--- a/solr/core/src/test/org/apache/solr/core/ResourceLoaderTest.java ++++ b/solr/core/src/test/org/apache/solr/core/ResourceLoaderTest.java +@@ -19,9 +19,10 @@ package org.apache.solr.core; + + import junit.framework.Assert; + +-import org.apache.lucene.util.LuceneTestCase; ++import org.apache.lucene.util._TestUtil; + import org.apache.solr.analysis.KeywordTokenizerFactory; + import org.apache.solr.analysis.NGramFilterFactory; ++import org.apache.solr.SolrTestCaseJ4; + import org.apache.solr.common.SolrException; + import org.apache.solr.handler.admin.LukeRequestHandler; + import org.apache.solr.handler.component.FacetComponent; +@@ -30,12 +31,13 @@ import org.apache.solr.util.plugin.Resou + import org.apache.solr.util.plugin.SolrCoreAware; + + import java.io.File; ++import java.io.IOException; + import java.io.InputStream; + import java.nio.charset.CharacterCodingException; + import java.util.Arrays; + import java.util.List; + +-public class ResourceLoaderTest extends LuceneTestCase ++public class ResourceLoaderTest extends SolrTestCaseJ4 + { + public void testInstanceDir() throws Exception { + SolrResourceLoader loader = new SolrResourceLoader(null); +@@ -47,7 +49,27 @@ public class ResourceLoaderTest extends + assertTrue(instDir + " is not equal to " + "solr/", instDir.equals("solr" + File.separator) == true); + } + +- public void testAwareCompatibility() ++ public void testEscapeInstanceDir() throws Exception { ++ File temp = _TestUtil.getTempDir("testEscapeInstanceDir"); ++ try { ++ temp.mkdirs(); ++ new File(temp, "dummy.txt").createNewFile(); ++ File instanceDir = new File(temp, "instance"); ++ instanceDir.mkdir(); ++ new File(instanceDir, "conf").mkdir(); ++ SolrResourceLoader loader = new SolrResourceLoader(instanceDir.getAbsolutePath()); ++ try { ++ loader.openResource("../../dummy.txt").close(); ++ fail(); ++ } catch (RuntimeException re) { ++ assertTrue(re.getMessage().startsWith("For security reasons, SolrResourceLoader")); ++ } ++ } finally { ++ _TestUtil.rmDir(temp); ++ } ++ } ++ ++ public void testAwareCompatibility() throws Exception + { + SolrResourceLoader loader = new SolrResourceLoader( "." ); + +--- a/solr/core/src/test/org/apache/solr/schema/PrimitiveFieldTypeTest.java ++++ b/solr/core/src/test/org/apache/solr/schema/PrimitiveFieldTypeTest.java +@@ -41,10 +41,17 @@ public class PrimitiveFieldTypeTest exte + // set some system properties for use by tests + System.setProperty("solr.test.sys.prop1", "propone"); + System.setProperty("solr.test.sys.prop2", "proptwo"); ++ System.setProperty("solr.allow.unsafe.resourceloading", "true"); + + initMap = new HashMap<String,String>(); + config = new SolrConfig(testConfHome + "solrconfig.xml"); + } ++ ++ @Override ++ public void tearDown() throws Exception { ++ System.clearProperty("solr.allow.unsafe.resourceloading"); ++ super.tearDown(); ++ } + + @SuppressWarnings("deprecation") + @Test diff --git a/debian/patches/CVE-2013-6407_CVE-2013-6408.patch b/debian/patches/CVE-2013-6407_CVE-2013-6408.patch new file mode 100644 index 0000000..2eacbad --- /dev/null +++ b/debian/patches/CVE-2013-6407_CVE-2013-6408.patch @@ -0,0 +1,480 @@ +Description: Fixes for CVE-2013-6407 and CVE-2013-6408 +Origin: https://issues.apache.org/jira/browse/SOLR-5520 + +--- a/solr/CHANGES.txt ++++ b/solr/CHANGES.txt +@@ -20,6 +20,17 @@ when more advanced customization is requ + See README.txt and http://lucene.apache.org/solr for more information + on how to get started. + ++* SOLR-5520, SOLR-4881: Fix DocumentAnalysisRequestHandler to correctly use ++ EmptyEntityResolver to prevent loading of external entities like ++ UpdateRequestHandler does. (Hossman, Uwe Schindler) ++ ++* SOLR-5520, SOLR-3895: XML and XSLT UpdateRequestHandler should not try to ++ resolve external entities. This improves speed of loading e.g. ++ XSL-transformed XHTML documents. (Martin Herfurt, uschindler, hossman) ++ ++* SOLR-5520, SOLR-3614: Fix XML parsing in XPathEntityProcessor to correctly ++ expand named entities, but ignore external entities. (uschindler, hossman) ++ + ================== 3.6.2 ================== + + Bug Fixes +--- a/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/XPathRecordReader.java ++++ b/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/XPathRecordReader.java +@@ -17,6 +17,7 @@ + package org.apache.solr.handler.dataimport; + + import org.apache.solr.common.util.XMLErrorLogger; ++import org.apache.solr.util.EmptyEntityResolver; + import javax.xml.stream.XMLInputFactory; + import static javax.xml.stream.XMLStreamConstants.*; + import javax.xml.stream.XMLStreamException; +@@ -625,10 +626,22 @@ public class XPathRecordReader { + } + + static XMLInputFactory factory = XMLInputFactory.newInstance(); +- static{ +- factory.setProperty(XMLInputFactory.IS_VALIDATING , Boolean.FALSE); +- factory.setProperty(XMLInputFactory.SUPPORT_DTD , Boolean.FALSE); ++ static { ++ EmptyEntityResolver.configureXMLInputFactory(factory); + factory.setXMLReporter(XMLLOG); ++ try { ++ // The java 1.6 bundled stax parser (sjsxp) does not currently have a thread-safe ++ // XMLInputFactory, as that implementation tries to cache and reuse the ++ // XMLStreamReader. Setting the parser-specific "reuse-instance" property to false ++ // prevents this. ++ // All other known open-source stax parsers (and the bea ref impl) ++ // have thread-safe factories. ++ factory.setProperty("reuse-instance", Boolean.FALSE); ++ } catch (IllegalArgumentException ex) { ++ // Other implementations will likely throw this exception since "reuse-instance" ++ // isimplementation specific. ++ LOG.debug("Unable to set the 'reuse-instance' property for the input chain: " + factory); ++ } + } + + /**Implement this interface to stream records as and when one is found. +--- a/solr/contrib/dataimporthandler/src/test/org/apache/solr/handler/dataimport/TestXPathEntityProcessor.java ++++ b/solr/contrib/dataimporthandler/src/test/org/apache/solr/handler/dataimport/TestXPathEntityProcessor.java +@@ -87,7 +87,11 @@ public class TestXPathEntityProcessor ex + break; + result.add(row); + } +- assertEquals(2, ((List)result.get(0).get("a")).size()); ++ List l = (List)result.get(0).get("a"); ++ assertEquals(3, l.size()); ++ assertEquals("1", l.get(0)); ++ assertEquals("2", l.get(1)); ++ assertEquals("ΓΌ", l.get(2)); + } + + @Test +@@ -298,7 +302,7 @@ public class TestXPathEntityProcessor ex + + "\t\t<price>9.90</price>\n" + + "\t\t<year>1982</year>\n" + "\t</cd>\n" + "</catalog>\t"; + +- private static final String testXml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><root><a>1</a><a>2</a></root>"; ++ private static final String testXml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE root [\n<!ENTITY uuml \"ü\" >\n]>\n<root><a>1</a><a>2</a><a>ü</a></root>"; + + private static final String testXmlFlatten = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><root><a>1<b>B</b>2</a></root>"; + } +--- a/solr/core/src/java/org/apache/solr/handler/DocumentAnalysisRequestHandler.java ++++ b/solr/core/src/java/org/apache/solr/handler/DocumentAnalysisRequestHandler.java +@@ -36,6 +36,7 @@ import org.apache.solr.request.SolrQuery + import org.apache.solr.schema.FieldType; + import org.apache.solr.schema.IndexSchema; + import org.apache.solr.schema.SchemaField; ++import org.apache.solr.util.EmptyEntityResolver; + import org.slf4j.Logger; + import org.slf4j.LoggerFactory; + +@@ -91,6 +92,8 @@ public class DocumentAnalysisRequestHand + super.init(args); + + inputFactory = XMLInputFactory.newInstance(); ++ EmptyEntityResolver.configureXMLInputFactory(inputFactory); ++ inputFactory.setXMLReporter(xmllog); + try { + // The java 1.6 bundled stax parser (sjsxp) does not currently have a thread-safe + // XMLInputFactory, as that implementation tries to cache and reuse the +@@ -104,7 +107,6 @@ public class DocumentAnalysisRequestHand + // isimplementation specific. + log.debug("Unable to set the 'reuse-instance' property for the input factory: " + inputFactory); + } +- inputFactory.setXMLReporter(xmllog); + } + + /** +--- a/solr/core/src/java/org/apache/solr/handler/XmlUpdateRequestHandler.java ++++ b/solr/core/src/java/org/apache/solr/handler/XmlUpdateRequestHandler.java +@@ -28,6 +28,7 @@ import org.apache.solr.request.SolrQuery + import org.apache.solr.response.SolrQueryResponse; + import org.apache.solr.update.processor.UpdateRequestProcessor; + import org.apache.solr.update.processor.UpdateRequestProcessorChain; ++import org.apache.solr.util.EmptyEntityResolver; + import org.slf4j.Logger; + import org.slf4j.LoggerFactory; + +@@ -89,6 +90,8 @@ public class XmlUpdateRequestHandler ext + super.init(args); + + inputFactory = XMLInputFactory.newInstance(); ++ inputFactory.setXMLReporter(xmllog); ++ EmptyEntityResolver.configureXMLInputFactory(inputFactory); + try { + // The java 1.6 bundled stax parser (sjsxp) does not currently have a thread-safe + // XMLInputFactory, as that implementation tries to cache and reuse the +@@ -103,7 +106,6 @@ public class XmlUpdateRequestHandler ext + // isimplementation specific. + log.debug("Unable to set the 'reuse-instance' property for the input chain: " + inputFactory); + } +- inputFactory.setXMLReporter(xmllog); + } + + @Override +--- a/solr/core/src/java/org/apache/solr/handler/XsltUpdateRequestHandler.java ++++ b/solr/core/src/java/org/apache/solr/handler/XsltUpdateRequestHandler.java +@@ -22,10 +22,12 @@ import org.apache.solr.common.util.Named + import org.apache.solr.common.util.XMLErrorLogger; + import org.apache.solr.request.SolrQueryRequest; + import org.apache.solr.update.processor.UpdateRequestProcessor; ++import org.apache.solr.util.EmptyEntityResolver; + import org.slf4j.Logger; + import org.slf4j.LoggerFactory; + + import javax.xml.stream.XMLInputFactory; ++import javax.xml.parsers.SAXParserFactory; + + /** + * Add documents to solr using the STAX XML parser, transforming it with XSLT first +@@ -41,6 +43,7 @@ public class XsltUpdateRequestHandler ex + private static final String XSLT_CACHE_PARAM = "xsltCacheLifetimeSeconds"; + + XMLInputFactory inputFactory; ++ SAXParserFactory saxFactory; + private Integer xsltCacheLifetimeSeconds; + + @Override +@@ -48,6 +51,8 @@ public class XsltUpdateRequestHandler ex + super.init(args); + + inputFactory = XMLInputFactory.newInstance(); ++ inputFactory.setXMLReporter(xmllog); ++ EmptyEntityResolver.configureXMLInputFactory(inputFactory); + try { + // The java 1.6 bundled stax parser (sjsxp) does not currently have a thread-safe + // XMLInputFactory, as that implementation tries to cache and reuse the +@@ -62,7 +67,11 @@ public class XsltUpdateRequestHandler ex + // isimplementation specific. + log.debug("Unable to set the 'reuse-instance' property for the input chain: " + inputFactory); + } +- inputFactory.setXMLReporter(xmllog); ++ ++ // Init SAX parser (for XSL): ++ saxFactory = SAXParserFactory.newInstance(); ++ saxFactory.setNamespaceAware(true); // XSL needs this! ++ EmptyEntityResolver.configureSAXParserFactory(saxFactory); + + final SolrParams p = SolrParams.toSolrParams(args); + this.xsltCacheLifetimeSeconds = p.getInt(XSLT_CACHE_PARAM,XSLT_CACHE_DEFAULT); +@@ -71,7 +80,7 @@ public class XsltUpdateRequestHandler ex + + @Override + protected ContentStreamLoader newLoader(SolrQueryRequest req, UpdateRequestProcessor processor) { +- return new XsltXMLLoader(processor, inputFactory, xsltCacheLifetimeSeconds); ++ return new XsltXMLLoader(processor, inputFactory, saxFactory, xsltCacheLifetimeSeconds); + } + + //////////////////////// SolrInfoMBeans methods ////////////////////// +--- a/solr/core/src/java/org/apache/solr/handler/XsltXMLLoader.java ++++ b/solr/core/src/java/org/apache/solr/handler/XsltXMLLoader.java +@@ -25,10 +25,12 @@ import org.apache.solr.common.util.Conte + import org.apache.solr.common.util.ContentStreamBase; + import org.apache.solr.common.util.XMLErrorLogger; + import org.apache.solr.core.SolrConfig; ++import org.apache.solr.util.EmptyEntityResolver; + import org.slf4j.Logger; + import org.slf4j.LoggerFactory; + import org.apache.commons.io.IOUtils; + ++import javax.xml.parsers.SAXParserFactory; + import javax.xml.stream.XMLStreamReader; + import javax.xml.stream.XMLStreamException; + import javax.xml.stream.XMLInputFactory; +@@ -38,6 +40,7 @@ import javax.xml.transform.dom.DOMSource + import javax.xml.transform.dom.DOMResult; + import javax.xml.transform.sax.SAXSource; + import org.xml.sax.InputSource; ++import org.xml.sax.XMLReader; + + import java.io.InputStream; + import java.io.IOException; +@@ -50,14 +53,18 @@ import java.util.Map; + * + **/ + class XsltXMLLoader extends XMLLoader { ++ public static Logger log = LoggerFactory.getLogger(XsltXMLLoader.class); ++ private static final XMLErrorLogger xmllog = new XMLErrorLogger(log); + + public static final String TRANSFORM_PARAM = "tr"; + public static final String CONTEXT_TRANSFORMER_KEY = "xsltupdater.transformer"; + ++ private final SAXParserFactory saxFactory; + private final Integer xsltCacheLifetimeSeconds; + +- public XsltXMLLoader(UpdateRequestProcessor processor, XMLInputFactory inputFactory, Integer xsltCacheLifetimeSeconds) { ++ public XsltXMLLoader(UpdateRequestProcessor processor, XMLInputFactory inputFactory, SAXParserFactory saxFactory, Integer xsltCacheLifetimeSeconds) { + super(processor, inputFactory); ++ this.saxFactory = saxFactory; + this.xsltCacheLifetimeSeconds = xsltCacheLifetimeSeconds; + } + +@@ -74,7 +81,10 @@ class XsltXMLLoader extends XMLLoader { + final String charset = ContentStreamBase.getCharsetFromContentType(stream.getContentType()); + final InputSource isrc = new InputSource(is); + isrc.setEncoding(charset); +- final SAXSource source = new SAXSource(isrc); ++ final XMLReader xmlr = saxFactory.newSAXParser().getXMLReader(); ++ xmlr.setErrorHandler(xmllog); ++ xmlr.setEntityResolver(EmptyEntityResolver.SAX_INSTANCE); ++ final SAXSource source = new SAXSource(xmlr, isrc); + t.transform(source, result); + } catch(TransformerException te) { + throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, te.getMessage(), te); +--- /dev/null ++++ b/solr/core/src/java/org/apache/solr/util/EmptyEntityResolver.java +@@ -0,0 +1,99 @@ ++package org.apache.solr.util; ++ ++/* ++ * 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. ++ */ ++ ++import java.io.InputStream; ++import org.xml.sax.InputSource; ++import org.xml.sax.EntityResolver; ++import javax.xml.XMLConstants; ++import javax.xml.parsers.SAXParserFactory; ++import javax.xml.stream.XMLInputFactory; ++import javax.xml.stream.XMLResolver; ++import javax.xml.transform.Source; ++import javax.xml.transform.stream.StreamSource; ++ ++import org.apache.commons.io.input.ClosedInputStream; ++ ++/** ++ * This class provides several singletons of entity resolvers used by ++ * SAX and StAX in the Java API. This is needed to make secure ++ * XML parsers, that don't resolve external entities from untrusted sources. ++ * <p>This class also provides static methods to configure SAX and StAX ++ * parsers to be safe. ++ * <p>Parsers will get an empty, closed stream for every external ++ * entity, so they will not fail while parsing (unless the external entity ++ * is needed for processing!). ++ */ ++public final class EmptyEntityResolver { ++ ++ public static final EntityResolver SAX_INSTANCE = new EntityResolver() { ++ // not in Java 5: @Override ++ public InputSource resolveEntity(String publicId, String systemId) { ++ return new InputSource(ClosedInputStream.CLOSED_INPUT_STREAM); ++ } ++ }; ++ ++ public static final XMLResolver STAX_INSTANCE = new XMLResolver() { ++ // not in Java 5: @Override ++ public InputStream resolveEntity(String publicId, String systemId, String baseURI, String namespace) { ++ return ClosedInputStream.CLOSED_INPUT_STREAM; ++ } ++ }; ++ ++ // no instance! ++ private EmptyEntityResolver() {} ++ ++ private static void trySetSAXFeature(SAXParserFactory saxFactory, String feature, boolean enabled) { ++ try { ++ saxFactory.setFeature(feature, enabled); ++ } catch (Exception ex) { ++ // ignore ++ } ++ } ++ ++ /** Configures the given {@link SAXParserFactory} to do secure XML processing of untrusted sources. ++ * It is required to also set {@link #SAX_INSTANCE} on the created {@link XMLReader}. ++ * @see #SAX_INSTANCE ++ */ ++ public static void configureSAXParserFactory(SAXParserFactory saxFactory) { ++ // don't enable validation of DTDs: ++ saxFactory.setValidating(false); ++ // enable secure processing: ++ trySetSAXFeature(saxFactory, XMLConstants.FEATURE_SECURE_PROCESSING, true); ++ } ++ ++ private static void trySetStAXProperty(XMLInputFactory inputFactory, String key, Object value) { ++ try { ++ inputFactory.setProperty(key, value); ++ } catch (Exception ex) { ++ // ignore ++ } ++ } ++ ++ /** Configures the given {@link XMLInputFactory} to not parse external entities. ++ * No further configuration on is needed, all required entity resolvers are configured. ++ */ ++ public static void configureXMLInputFactory(XMLInputFactory inputFactory) { ++ // don't enable validation of DTDs: ++ trySetStAXProperty(inputFactory, XMLInputFactory.IS_VALIDATING, Boolean.FALSE); ++ // enable this to *not* produce parsing failure on external entities: ++ trySetStAXProperty(inputFactory, XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, Boolean.TRUE); ++ inputFactory.setXMLResolver(EmptyEntityResolver.STAX_INSTANCE); ++ } ++ ++} +--- a/solr/core/src/test/org/apache/solr/handler/XmlUpdateRequestHandlerTest.java ++++ b/solr/core/src/test/org/apache/solr/handler/XmlUpdateRequestHandlerTest.java +@@ -17,6 +17,7 @@ + package org.apache.solr.handler; + + import org.apache.commons.lang.ObjectUtils; ++import org.apache.solr.common.util.NamedList; + import org.apache.solr.request.SolrQueryRequest; + import org.apache.solr.response.SolrQueryResponse; + import org.apache.solr.update.AddUpdateCommand; +@@ -40,7 +41,7 @@ import org.junit.Test; + + public class XmlUpdateRequestHandlerTest extends AbstractSolrTestCase + { +- private XMLInputFactory inputFactory = XMLInputFactory.newInstance(); ++ private XMLInputFactory inputFactory; + protected XmlUpdateRequestHandler handler; + + @Override public String getSchemaFile() { return "schema.xml"; } +@@ -50,6 +51,8 @@ public class XmlUpdateRequestHandlerTest + public void setUp() throws Exception { + super.setUp(); + handler = new XmlUpdateRequestHandler(); ++ handler.init(new NamedList<String>()); ++ this.inputFactory = handler.inputFactory; + } + + @Override +@@ -118,6 +121,46 @@ public class XmlUpdateRequestHandlerTest + } + + @Test ++ public void testExternalEntities() throws Exception ++ { ++ String file = getFile("mailing_lists.pdf").toURI().toASCIIString(); ++ String xml = ++ "<?xml version=\"1.0\"?>" + ++ // check that external entities are not resolved! ++ "<!DOCTYPE foo [<!ENTITY bar SYSTEM \""+file+"\">]>" + ++ "<add>" + ++ " &bar;" + ++ " <doc>" + ++ " <field name=\"id\">12345</field>" + ++ " <field name=\"name\">kitten</field>" + ++ " </doc>" + ++ "</add>"; ++ SolrQueryRequest req = req(); ++ SolrQueryResponse rsp = new SolrQueryResponse(); ++ BufferingRequestProcessor p = new BufferingRequestProcessor(null); ++ XMLLoader loader = new XMLLoader(p, inputFactory); ++ loader.load(req, rsp, new ContentStreamBase.StringStream(xml)); ++ ++ AddUpdateCommand add = p.addCommands.get(0); ++ assertEquals("12345", add.solrDoc.getField("id").getFirstValue()); ++ req.close(); ++ } ++ ++ public void testNamedEntity() throws Exception { ++ assertU("<?xml version=\"1.0\" ?>\n"+ ++ "<!DOCTYPE add [\n<!ENTITY wacky \"zzz\" >\n]>"+ ++ "<add><doc>"+ ++ "<field name=\"id\">1</field>"+ ++ "<field name=\"foo_s\">&wacky;</field>" + ++ "</doc></add>"); ++ ++ assertU("<commit/>"); ++ assertQ(req("foo_s:zzz"), ++ "//*[@numFound='1']" ++ ); ++ } ++ ++ @Test + public void testReadDelete() throws Exception { + String xml = + "<update>" + +--- a/solr/core/src/test/org/apache/solr/handler/XsltUpdateRequestHandlerTest.java ++++ b/solr/core/src/test/org/apache/solr/handler/XsltUpdateRequestHandlerTest.java +@@ -90,4 +90,54 @@ public class XsltUpdateRequestHandlerTes + , "//int[@name='id'][.='12345']" + ); + } ++ ++ @Test ++ public void testEntities() throws Exception ++ { ++ // use a binary file, so when it's loaded fail with XML eror: ++ String file = getFile("mailing_lists.pdf").toURI().toASCIIString(); ++ String xml = ++ "<?xml version=\"1.0\"?>" + ++ "<!DOCTYPE foo [" + ++ // check that external entities are not resolved! ++ "<!ENTITY bar SYSTEM \""+file+"\">"+ ++ // but named entities should be ++ "<!ENTITY wacky \"zzz\">"+ ++ "]>" + ++ "<random>" + ++ " &bar;" + ++ " <document>" + ++ " <node name=\"id\" value=\"12345\"/>" + ++ " <node name=\"foo_s\" value=\"&wacky;\"/>" + ++ " </document>" + ++ "</random>"; ++ Map<String,String> args = new HashMap<String, String>(); ++ args.put("tr", "xsl-update-handler-test.xsl"); ++ ++ SolrCore core = h.getCore(); ++ LocalSolrQueryRequest req = new LocalSolrQueryRequest( core, new MapSolrParams( args) ); ++ ArrayList<ContentStream> streams = new ArrayList<ContentStream>(); ++ streams.add(new ContentStreamBase.StringStream(xml)); ++ req.setContentStreams(streams); ++ SolrQueryResponse rsp = new SolrQueryResponse(); ++ XsltUpdateRequestHandler handler = new XsltUpdateRequestHandler(); ++ handler.init(new NamedList<String>()); ++ handler.handleRequestBody(req, rsp); ++ StringWriter sw = new StringWriter(32000); ++ QueryResponseWriter responseWriter = core.getQueryResponseWriter(req); ++ responseWriter.write(sw,req,rsp); ++ req.close(); ++ String response = sw.toString(); ++ assertU(response); ++ assertU(commit()); ++ ++ assertQ("test document was correctly committed", req("q","*:*") ++ , "//result[@numFound='1']" ++ , "//int[@name='id'][.='12345']" ++ ); ++ assertQ("test document can be searched by the string defined by the named entity", req("q","foo_s:zzz") ++ , "//result[@numFound='1']" ++ , "//int[@name='id'][.='12345']" ++ ); ++ } + } diff --git a/debian/patches/series b/debian/patches/series index be79de5..0a6edb8 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -6,3 +6,5 @@ icu4.4-compat.patch regex-test-failure.patch #set-data-dir.patch remove-prettify.patch +CVE-2013-6397.patch +CVE-2013-6407_CVE-2013-6408.patch -- Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-java/lucene-solr.git _______________________________________________ pkg-java-commits mailing list [email protected] http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pkg-java-commits

