Blame SOURCES/0001-SOLR-11477-Disallow-resolving-of-external-entities-i.patch

c96e1a
From 29d9942d5266a4decc9804e3304bd0514c8027d4 Mon Sep 17 00:00:00 2001
c96e1a
From: Christine Poerschke <cpoerschke@apache.org>
c96e1a
Date: Fri, 13 Oct 2017 12:46:58 +0100
c96e1a
Subject: [PATCH] SOLR-11477: Disallow resolving of external entities in Lucene
c96e1a
c96e1a
---
c96e1a
 .../apache/lucene/queryparser/xml/CoreParser.java  | 65 +++++++++++++++++++---
c96e1a
 1 file changed, 56 insertions(+), 9 deletions(-)
c96e1a
c96e1a
diff --git a/queryparser/src/java/org/apache/lucene/queryparser/xml/CoreParser.java b/queryparser/src/java/org/apache/lucene/queryparser/xml/CoreParser.java
c96e1a
index 02ac8b9..ac40779 100644
c96e1a
--- a/queryparser/src/java/org/apache/lucene/queryparser/xml/CoreParser.java
c96e1a
+++ b/queryparser/src/java/org/apache/lucene/queryparser/xml/CoreParser.java
c96e1a
@@ -6,10 +6,18 @@ import org.apache.lucene.queryparser.xml.builders.*;
c96e1a
 import org.apache.lucene.search.Query;
c96e1a
 import org.w3c.dom.Document;
c96e1a
 import org.w3c.dom.Element;
c96e1a
+import org.xml.sax.EntityResolver;
c96e1a
+import org.xml.sax.ErrorHandler;
c96e1a
+import org.xml.sax.InputSource;
c96e1a
+import org.xml.sax.SAXException;
c96e1a
 
c96e1a
+
c96e1a
+import javax.xml.XMLConstants;
c96e1a
 import javax.xml.parsers.DocumentBuilder;
c96e1a
 import javax.xml.parsers.DocumentBuilderFactory;
c96e1a
+import javax.xml.parsers.ParserConfigurationException;
c96e1a
 import java.io.InputStream;
c96e1a
+import java.util.Locale;
c96e1a
 
c96e1a
 /*
c96e1a
  * Licensed to the Apache Software Foundation (ASF) under one or more
c96e1a
@@ -118,6 +126,10 @@ public class CoreParser implements QueryBuilder {
c96e1a
     queryFactory.addBuilder("SpanNot", snot);
c96e1a
   }
c96e1a
 
c96e1a
+  /**
c96e1a
+   * Parses the given stream as XML file and returns a {@link Query}.
c96e1a
+   * By default this disallows external entities for security reasons.
c96e1a
+   */
c96e1a
   public Query parse(InputStream xmlStream) throws ParserException {
c96e1a
     return getQuery(parseXML(xmlStream).getDocumentElement());
c96e1a
   }
c96e1a
@@ -130,23 +142,48 @@ public class CoreParser implements QueryBuilder {
c96e1a
     filterFactory.addBuilder(nodeName, builder);
c96e1a
   }
c96e1a
 
c96e1a
-  private static Document parseXML(InputStream pXmlFile) throws ParserException {
c96e1a
-    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
c96e1a
-    DocumentBuilder db = null;
c96e1a
+  /**
c96e1a
+   * Returns a SAX {@link EntityResolver} to be used by {@link DocumentBuilder}.
c96e1a
+   * By default this returns {@link #DISALLOW_EXTERNAL_ENTITY_RESOLVER}, which disallows the
c96e1a
+   * expansion of external entities (for security reasons). To restore legacy behavior,
c96e1a
+   * override this method to return {@code null}.
c96e1a
+   */
c96e1a
+  protected EntityResolver getEntityResolver() {
c96e1a
+    return DISALLOW_EXTERNAL_ENTITY_RESOLVER;
c96e1a
+  }
c96e1a
+
c96e1a
+  /**
c96e1a
+   * Subclass and override to return a SAX {@link ErrorHandler} to be used by {@link DocumentBuilder}.
c96e1a
+   * By default this returns {@code null} so no error handler is used.
c96e1a
+   * This method can be used to redirect XML parse errors/warnings to a custom logger.
c96e1a
+   */
c96e1a
+  protected ErrorHandler getErrorHandler() {
c96e1a
+    return null;
c96e1a
+  }
c96e1a
+
c96e1a
+  private Document parseXML(InputStream pXmlFile) throws ParserException {
c96e1a
+    final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
c96e1a
+    dbf.setValidating(false);
c96e1a
     try {
c96e1a
-      db = dbf.newDocumentBuilder();
c96e1a
+      dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
c96e1a
+    } catch (ParserConfigurationException e) {
c96e1a
+      // ignore since all implementations are required to support the
c96e1a
+      // {@link javax.xml.XMLConstants#FEATURE_SECURE_PROCESSING} feature
c96e1a
     }
c96e1a
-    catch (Exception se) {
c96e1a
-      throw new ParserException("XML Parser configuration error", se);
c96e1a
+    final DocumentBuilder db;
c96e1a
+    try {
c96e1a
+        db = dbf.newDocumentBuilder();
c96e1a
+    } catch (Exception se) {
c96e1a
+        throw new ParserException("XML Parser configuration error.", se);
c96e1a
     }
c96e1a
-    org.w3c.dom.Document doc = null;
c96e1a
     try {
c96e1a
-      doc = db.parse(pXmlFile);
c96e1a
+      db.setEntityResolver(getEntityResolver());
c96e1a
+      db.setErrorHandler(getErrorHandler());
c96e1a
+      return db.parse(pXmlFile);
c96e1a
     }
c96e1a
     catch (Exception se) {
c96e1a
       throw new ParserException("Error parsing XML stream:" + se, se);
c96e1a
     }
c96e1a
-    return doc;
c96e1a
   }
c96e1a
 
c96e1a
 
c96e1a
@@ -154,4 +191,14 @@ public class CoreParser implements QueryBuilder {
c96e1a
   public Query getQuery(Element e) throws ParserException {
c96e1a
     return queryFactory.getQuery(e);
c96e1a
   }
c96e1a
+
c96e1a
+  public static final EntityResolver DISALLOW_EXTERNAL_ENTITY_RESOLVER = new EntityResolver() {
c96e1a
+    @Override
c96e1a
+    public InputSource resolveEntity(String publicId, String systemId) throws SAXException {
c96e1a
+      throw new SAXException(String.format(Locale.ENGLISH,
c96e1a
+            "External Entity resolving unsupported:  publicId=\"%s\" systemId=\"%s\"",
c96e1a
+            publicId, systemId));
c96e1a
+    }
c96e1a
+  };
c96e1a
+
c96e1a
 }
c96e1a
-- 
c96e1a
2.13.6
c96e1a