diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AssemblyAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AssemblyAnalyzer.java index cd9551006..690ab6499 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AssemblyAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AssemblyAnalyzer.java @@ -37,16 +37,15 @@ import org.w3c.dom.Document; import org.xml.sax.SAXException; import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; import java.util.ArrayList; import java.util.List; -import javax.xml.XMLConstants; import javax.xml.parsers.ParserConfigurationException; import org.owasp.dependencycheck.exception.InitializationException; import org.apache.commons.lang3.SystemUtils; +import org.owasp.dependencycheck.utils.XmlUtils; /** * Analyzer for getting company, product, and version information from a .NET @@ -124,12 +123,7 @@ public class AssemblyAnalyzer extends AbstractFileTypeAnalyzer { Document doc = null; try { final Process proc = pb.start(); - - final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); - factory.setFeature("http://xml.org/sax/features/external-general-entities", false); - factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); - final DocumentBuilder builder = factory.newDocumentBuilder(); + final DocumentBuilder builder = XmlUtils.buildSecureDocumentBuilder(); doc = builder.parse(proc.getInputStream()); @@ -265,11 +259,7 @@ public class AssemblyAnalyzer extends AbstractFileTypeAnalyzer { // Try evacuating the error stream IOUtils.copy(p.getErrorStream(), NullOutputStream.NULL_OUTPUT_STREAM); - final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); - factory.setFeature("http://xml.org/sax/features/external-general-entities", false); - factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); - final DocumentBuilder builder = factory.newDocumentBuilder(); + final DocumentBuilder builder = XmlUtils.buildSecureDocumentBuilder(); final Document doc = builder.parse(p.getInputStream()); final XPath xpath = XPathFactory.newInstance().newXPath(); final String error = xpath.evaluate("/assembly/error", doc); diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/central/CentralSearch.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/central/CentralSearch.java index 068d167d2..5f3cfc420 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/central/CentralSearch.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/central/CentralSearch.java @@ -23,15 +23,14 @@ import java.net.HttpURLConnection; import java.net.URL; import java.util.ArrayList; import java.util.List; -import javax.xml.XMLConstants; import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathFactory; import org.owasp.dependencycheck.data.nexus.MavenArtifact; import org.owasp.dependencycheck.utils.Settings; import org.owasp.dependencycheck.utils.URLConnectionFactory; +import org.owasp.dependencycheck.utils.XmlUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Document; @@ -111,11 +110,7 @@ public class CentralSearch { if (conn.getResponseCode() == 200) { boolean missing = false; try { - final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); - factory.setFeature("http://xml.org/sax/features/external-general-entities", false); - factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); - final DocumentBuilder builder = factory.newDocumentBuilder(); + final DocumentBuilder builder = XmlUtils.buildSecureDocumentBuilder(); final Document doc = builder.parse(conn.getInputStream()); final XPath xpath = XPathFactory.newInstance().newXPath(); final String numFound = xpath.evaluate("/response/result/@numFound", doc); diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nexus/NexusSearch.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nexus/NexusSearch.java index 88ed54326..c7f6b790b 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nexus/NexusSearch.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nexus/NexusSearch.java @@ -21,15 +21,12 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.net.HttpURLConnection; import java.net.URL; -import javax.xml.XMLConstants; import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathFactory; -import org.owasp.dependencycheck.utils.InvalidSettingException; -import org.owasp.dependencycheck.utils.Settings; import org.owasp.dependencycheck.utils.URLConnectionFactory; +import org.owasp.dependencycheck.utils.XmlUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Document; @@ -105,11 +102,7 @@ public class NexusSearch { switch (conn.getResponseCode()) { case 200: try { - final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); - factory.setFeature("http://xml.org/sax/features/external-general-entities", false); - factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); - final DocumentBuilder builder = factory.newDocumentBuilder(); + final DocumentBuilder builder = XmlUtils.buildSecureDocumentBuilder(); final Document doc = builder.parse(conn.getInputStream()); final XPath xpath = XPathFactory.newInstance().newXPath(); final String groupId = xpath @@ -170,11 +163,7 @@ public class NexusSearch { LOGGER.warn("Expected 200 result from Nexus, got {}", conn.getResponseCode()); return false; } - final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); - factory.setFeature("http://xml.org/sax/features/external-general-entities", false); - factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); - final DocumentBuilder builder = factory.newDocumentBuilder(); + final DocumentBuilder builder = XmlUtils.buildSecureDocumentBuilder(); final Document doc = builder.parse(conn.getInputStream()); if (!"status".equals(doc.getDocumentElement().getNodeName())) { diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nuget/XPathNuspecParser.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nuget/XPathNuspecParser.java index 0ce80df92..0f5dee91c 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nuget/XPathNuspecParser.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nuget/XPathNuspecParser.java @@ -18,11 +18,11 @@ package org.owasp.dependencycheck.data.nuget; import java.io.InputStream; -import javax.xml.XMLConstants; -import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.DocumentBuilder; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathFactory; +import org.owasp.dependencycheck.utils.XmlUtils; import org.w3c.dom.Document; import org.w3c.dom.Node; @@ -58,11 +58,8 @@ public class XPathNuspecParser implements NuspecParser { @Override public NugetPackage parse(InputStream stream) throws NuspecParseException { try { - final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); - factory.setFeature("http://xml.org/sax/features/external-general-entities", false); - factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); - final Document d = factory.newDocumentBuilder().parse(stream); + DocumentBuilder db = XmlUtils.buildSecureDocumentBuilder(); + final Document d = db.parse(stream); final XPath xpath = XPathFactory.newInstance().newXPath(); final NugetPackage nuspec = new NugetPackage(); diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/CpeUpdater.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/CpeUpdater.java index 1ee134eb2..c6e6d3e89 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/CpeUpdater.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/CpeUpdater.java @@ -26,10 +26,8 @@ import java.net.MalformedURLException; import java.net.URL; import java.util.List; import java.util.zip.GZIPInputStream; -import javax.xml.XMLConstants; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; -import javax.xml.parsers.SAXParserFactory; import org.apache.commons.io.FileUtils; import static org.owasp.dependencycheck.data.nvdcve.DatabaseProperties.LAST_CPE_UPDATE; import org.owasp.dependencycheck.data.update.cpe.CPEHandler; @@ -39,6 +37,7 @@ import org.owasp.dependencycheck.utils.DateUtil; import org.owasp.dependencycheck.utils.DownloadFailedException; import org.owasp.dependencycheck.utils.Downloader; import org.owasp.dependencycheck.utils.Settings; +import org.owasp.dependencycheck.utils.XmlUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.xml.sax.SAXException; @@ -122,11 +121,7 @@ public class CpeUpdater extends BaseUpdater implements CachedWebDataSource { */ private List processXML(final File xml) throws UpdateException { try { - final SAXParserFactory factory = SAXParserFactory.newInstance(); - factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); - factory.setFeature("http://xml.org/sax/features/external-general-entities", false); - factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); - final SAXParser saxParser = factory.newSAXParser(); + final SAXParser saxParser = XmlUtils.buildSecureSaxParser(); final CPEHandler handler = new CPEHandler(); saxParser.parse(xml, handler); return handler.getData(); diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/nvd/ProcessTask.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/nvd/ProcessTask.java index cffeba5e4..20f64e804 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/nvd/ProcessTask.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/nvd/ProcessTask.java @@ -24,16 +24,15 @@ import java.sql.SQLException; import java.util.List; import java.util.Map; import java.util.concurrent.Callable; -import javax.xml.XMLConstants; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; -import javax.xml.parsers.SAXParserFactory; import org.owasp.dependencycheck.data.nvdcve.CveDB; import org.owasp.dependencycheck.data.nvdcve.DatabaseException; import org.owasp.dependencycheck.data.nvdcve.DatabaseProperties; import org.owasp.dependencycheck.data.update.exception.UpdateException; import org.owasp.dependencycheck.dependency.VulnerableSoftware; import org.owasp.dependencycheck.utils.Settings; +import org.owasp.dependencycheck.utils.XmlUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.xml.sax.SAXException; @@ -143,11 +142,7 @@ public class ProcessTask implements Callable { protected void importXML(File file, File oldVersion) throws ParserConfigurationException, SAXException, IOException, SQLException, DatabaseException, ClassNotFoundException { - final SAXParserFactory factory = SAXParserFactory.newInstance(); - factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); - factory.setFeature("http://xml.org/sax/features/external-general-entities", false); - factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); - final SAXParser saxParser = factory.newSAXParser(); + final SAXParser saxParser = XmlUtils.buildSecureSaxParser(); final NvdCve12Handler cve12Handler = new NvdCve12Handler(); saxParser.parse(oldVersion, cve12Handler); diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/hints/HintParser.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/hints/HintParser.java index e5515a1c6..8d7afada9 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/hints/HintParser.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/hints/HintParser.java @@ -24,10 +24,9 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; -import javax.xml.XMLConstants; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; -import javax.xml.parsers.SAXParserFactory; +import org.owasp.dependencycheck.utils.XmlUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -109,15 +108,7 @@ public class HintParser { try { schemaStream = this.getClass().getClassLoader().getResourceAsStream(HINT_SCHEMA); final HintHandler handler = new HintHandler(); - final SAXParserFactory factory = SAXParserFactory.newInstance(); - factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); - factory.setFeature("http://xml.org/sax/features/external-general-entities", false); - factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); - factory.setNamespaceAware(true); - factory.setValidating(true); - final SAXParser saxParser = factory.newSAXParser(); - saxParser.setProperty(HintParser.JAXP_SCHEMA_LANGUAGE, HintParser.W3C_XML_SCHEMA); - saxParser.setProperty(HintParser.JAXP_SCHEMA_SOURCE, new InputSource(schemaStream)); + final SAXParser saxParser = XmlUtils.buildSecureSaxParser(schemaStream); final XMLReader xmlReader = saxParser.getXMLReader(); xmlReader.setErrorHandler(new HintErrorHandler()); xmlReader.setContentHandler(handler); diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/pom/PomParser.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/pom/PomParser.java index 78734d94e..fd4595737 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/pom/PomParser.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/pom/PomParser.java @@ -24,10 +24,9 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; -import javax.xml.XMLConstants; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; -import javax.xml.parsers.SAXParserFactory; +import org.owasp.dependencycheck.utils.XmlUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -86,22 +85,12 @@ public class PomParser { public Model parse(InputStream inputStream) throws PomParseException { try { final PomHandler handler = new PomHandler(); - final SAXParserFactory factory = SAXParserFactory.newInstance(); -// factory.setNamespaceAware(true); -// factory.setValidating(true); - factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); - factory.setFeature("http://xml.org/sax/features/external-general-entities", false); - factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); - final SAXParser saxParser = factory.newSAXParser(); + final SAXParser saxParser = XmlUtils.buildSecureSaxParser(); final XMLReader xmlReader = saxParser.getXMLReader(); xmlReader.setContentHandler(handler); - final Reader reader = new InputStreamReader(inputStream, "UTF-8"); final InputSource in = new InputSource(reader); - //in.setEncoding("UTF-8"); - xmlReader.parse(in); - return handler.getModel(); } catch (ParserConfigurationException ex) { LOGGER.debug("", ex); diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/suppression/SuppressionParser.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/suppression/SuppressionParser.java index b4a7fc30c..f663dd5cb 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/suppression/SuppressionParser.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/suppression/SuppressionParser.java @@ -25,10 +25,9 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; import java.util.List; -import javax.xml.XMLConstants; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; -import javax.xml.parsers.SAXParserFactory; +import org.owasp.dependencycheck.utils.XmlUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -47,21 +46,6 @@ public class SuppressionParser { * The logger. */ private static final Logger LOGGER = LoggerFactory.getLogger(SuppressionParser.class); - /** - * JAXP Schema Language. Source: - * http://docs.oracle.com/javase/tutorial/jaxp/sax/validation.html - */ - public static final String JAXP_SCHEMA_LANGUAGE = "http://java.sun.com/xml/jaxp/properties/schemaLanguage"; - /** - * W3C XML Schema. Source: - * http://docs.oracle.com/javase/tutorial/jaxp/sax/validation.html - */ - public static final String W3C_XML_SCHEMA = "http://www.w3.org/2001/XMLSchema"; - /** - * JAXP Schema Source. Source: - * http://docs.oracle.com/javase/tutorial/jaxp/sax/validation.html - */ - public static final String JAXP_SCHEMA_SOURCE = "http://java.sun.com/xml/jaxp/properties/schemaSource"; /** * The suppression schema file location. */ @@ -126,15 +110,7 @@ public class SuppressionParser { try { schemaStream = this.getClass().getClassLoader().getResourceAsStream(SUPPRESSION_SCHEMA); final SuppressionHandler handler = new SuppressionHandler(); - final SAXParserFactory factory = SAXParserFactory.newInstance(); - factory.setNamespaceAware(true); - factory.setValidating(true); - factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); - factory.setFeature("http://xml.org/sax/features/external-general-entities", false); - factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); - final SAXParser saxParser = factory.newSAXParser(); - saxParser.setProperty(SuppressionParser.JAXP_SCHEMA_LANGUAGE, SuppressionParser.W3C_XML_SCHEMA); - saxParser.setProperty(SuppressionParser.JAXP_SCHEMA_SOURCE, new InputSource(schemaStream)); + SAXParser saxParser = XmlUtils.buildSecureSaxParser(schemaStream); final XMLReader xmlReader = saxParser.getXMLReader(); xmlReader.setErrorHandler(new SuppressionErrorHandler()); xmlReader.setContentHandler(handler); @@ -173,6 +149,8 @@ public class SuppressionParser { } } + + /** * Parses the given XML stream and returns a list of the suppression rules * contained. @@ -186,15 +164,7 @@ public class SuppressionParser { try { schemaStream = this.getClass().getClassLoader().getResourceAsStream(OLD_SUPPRESSION_SCHEMA); final SuppressionHandler handler = new SuppressionHandler(); - final SAXParserFactory factory = SAXParserFactory.newInstance(); - factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); - factory.setFeature("http://xml.org/sax/features/external-general-entities", false); - factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); - factory.setNamespaceAware(true); - factory.setValidating(true); - final SAXParser saxParser = factory.newSAXParser(); - saxParser.setProperty(SuppressionParser.JAXP_SCHEMA_LANGUAGE, SuppressionParser.W3C_XML_SCHEMA); - saxParser.setProperty(SuppressionParser.JAXP_SCHEMA_SOURCE, new InputSource(schemaStream)); + final SAXParser saxParser = XmlUtils.buildSecureSaxParser(schemaStream); final XMLReader xmlReader = saxParser.getXMLReader(); xmlReader.setErrorHandler(new SuppressionErrorHandler()); xmlReader.setContentHandler(handler); diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/xml/suppression/SuppressionHandlerTest.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/xml/suppression/SuppressionHandlerTest.java index 9517a1a7f..25997a7ba 100644 --- a/dependency-check-core/src/test/java/org/owasp/dependencycheck/xml/suppression/SuppressionHandlerTest.java +++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/xml/suppression/SuppressionHandlerTest.java @@ -28,6 +28,7 @@ import javax.xml.parsers.SAXParserFactory; import static org.junit.Assert.assertTrue; import org.junit.Test; import org.owasp.dependencycheck.BaseTest; +import org.owasp.dependencycheck.utils.XmlUtils; import org.xml.sax.InputSource; import org.xml.sax.XMLReader; @@ -45,15 +46,10 @@ public class SuppressionHandlerTest extends BaseTest { @Test public void testHandler() throws Exception { File file = BaseTest.getResourceAsFile(this, "suppressions.xml"); - File schema = BaseTest.getResourceAsFile(this, "schema/suppression.xsd"); - SuppressionHandler handler = new SuppressionHandler(); + InputStream schemaStream = BaseTest.getResourceAsStream(this, "schema/suppression.xsd"); - SAXParserFactory factory = SAXParserFactory.newInstance(); - factory.setNamespaceAware(true); - factory.setValidating(true); - SAXParser saxParser = factory.newSAXParser(); - saxParser.setProperty(SuppressionParser.JAXP_SCHEMA_LANGUAGE, SuppressionParser.W3C_XML_SCHEMA); - saxParser.setProperty(SuppressionParser.JAXP_SCHEMA_SOURCE, schema); + SuppressionHandler handler = new SuppressionHandler(); + SAXParser saxParser = XmlUtils.buildSecureSaxParser(schemaStream); XMLReader xmlReader = saxParser.getXMLReader(); xmlReader.setErrorHandler(new SuppressionErrorHandler()); xmlReader.setContentHandler(handler); diff --git a/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/XmlUtils.java b/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/XmlUtils.java new file mode 100644 index 000000000..d948b700f --- /dev/null +++ b/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/XmlUtils.java @@ -0,0 +1,123 @@ +/* + * This file is part of dependency-check-core. + * + * Licensed 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. + * + * Copyright (c) 2016 Jeremy Long. All Rights Reserved. + */ +package org.owasp.dependencycheck.utils; + +import java.io.InputStream; +import javax.xml.XMLConstants; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; +import org.xml.sax.SAXException; +import org.xml.sax.SAXNotRecognizedException; +import org.xml.sax.SAXNotSupportedException; + +/** + * Collection of XML related code. + * + * @author Jeremy Long + */ +public final class XmlUtils { + + /** + * JAXP Schema Language. Source: + * http://docs.oracle.com/javase/tutorial/jaxp/sax/validation.html + */ + public static final String JAXP_SCHEMA_LANGUAGE = "http://java.sun.com/xml/jaxp/properties/schemaLanguage"; + /** + * W3C XML Schema. Source: + * http://docs.oracle.com/javase/tutorial/jaxp/sax/validation.html + */ + public static final String W3C_XML_SCHEMA = "http://www.w3.org/2001/XMLSchema"; + /** + * JAXP Schema Source. Source: + * http://docs.oracle.com/javase/tutorial/jaxp/sax/validation.html + */ + public static final String JAXP_SCHEMA_SOURCE = "http://java.sun.com/xml/jaxp/properties/schemaSource"; + + /** + * Private constructor for a utility class. + */ + private XmlUtils() { + } + + /** + * Constructs a validating secure SAX Parser. + * + * @param schemaStream the schema to validate the XML against + * @return a SAX Parser + * @throws ParserConfigurationException is thrown if there is a parser + * configuration exception + * @throws SAXNotRecognizedException thrown if there is an unrecognized + * feature + * @throws SAXNotSupportedException thrown if there is a non-supported + * feature + * @throws SAXException is thrown if there is a SAXException + */ + public static SAXParser buildSecureSaxParser(InputStream schemaStream) throws ParserConfigurationException, + SAXNotRecognizedException, SAXNotSupportedException, SAXException { + final SAXParserFactory factory = SAXParserFactory.newInstance(); + factory.setNamespaceAware(true); + factory.setValidating(true); + factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + factory.setFeature("http://xml.org/sax/features/external-general-entities", false); + factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + final SAXParser saxParser = factory.newSAXParser(); + saxParser.setProperty(JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA); + saxParser.setProperty(JAXP_SCHEMA_SOURCE, schemaStream); + return saxParser; + } + + /** + * Constructs a secure SAX Parser. + * + * @return a SAX Parser + * @throws ParserConfigurationException thrown if there is a parser + * configuration exception + * @throws SAXNotRecognizedException thrown if there is an unrecognized + * feature + * @throws SAXNotSupportedException thrown if there is a non-supported + * feature + * @throws SAXException is thrown if there is a SAXException + */ + public static SAXParser buildSecureSaxParser() throws ParserConfigurationException, + SAXNotRecognizedException, SAXNotSupportedException, SAXException { + final SAXParserFactory factory = SAXParserFactory.newInstance(); + factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + factory.setFeature("http://xml.org/sax/features/external-general-entities", false); + factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + return factory.newSAXParser(); + } + + /** + * Constructs a new document builder with security features enabled. + * + * @return a new document builder + * @throws ParserConfigurationException thrown if there is a parser + * configuration exception + */ + public static DocumentBuilder buildSecureDocumentBuilder() throws ParserConfigurationException { + final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + factory.setFeature("http://xml.org/sax/features/external-general-entities", false); + factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + DocumentBuilder db = factory.newDocumentBuilder(); + return db; + } +}