/*
* Copyright (c) MuleSoft, Inc. All rights reserved. http://www.mulesoft.com
* The software in this package is published under the terms of the CPAL v1.0
* license, a copy of which has been included with this distribution in the
* LICENSE.txt file.
*/
package org.mule.runtime.core.util.xmlsecurity;
import static java.lang.String.format;
import static javax.xml.XMLConstants.ACCESS_EXTERNAL_DTD;
import static javax.xml.XMLConstants.ACCESS_EXTERNAL_STYLESHEET;
import static javax.xml.XMLConstants.FEATURE_SECURE_PROCESSING;
import static javax.xml.stream.XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES;
import static javax.xml.stream.XMLInputFactory.SUPPORT_DTD;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.stream.XMLInputFactory;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerFactory;
import net.sf.saxon.jaxp.SaxonTransformerFactory;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Create different XML factories configured through the same interface for disabling vulnerabilities.
*/
public class DefaultXMLSecureFactories {
private final static Log logger = LogFactory.getLog(DefaultXMLSecureFactories.class);
public static DocumentBuilderFactory createDocumentBuilderFactory(Boolean externalEntities, Boolean expandEntities) {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
try {
factory.setFeature("http://xml.org/sax/features/external-general-entities", externalEntities);
factory.setFeature("http://xml.org/sax/features/external-parameter-entities", externalEntities);
factory.setExpandEntityReferences(expandEntities);
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", !expandEntities);
} catch (Exception e) {
logWarning("DocumentBuilderFactory", factory.getClass().getName());
}
return factory;
}
public static SAXParserFactory createSaxParserFactory(Boolean externalEntities, Boolean expandEntities) {
SAXParserFactory factory = SAXParserFactory.newInstance();
try {
factory.setFeature("http://xml.org/sax/features/external-general-entities", externalEntities);
factory.setFeature("http://xml.org/sax/features/external-parameter-entities", externalEntities);
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", !expandEntities);
} catch (Exception e) {
logWarning("SAXParserFactory", factory.getClass().getName());
}
return factory;
}
public static XMLInputFactory createXmlInputFactory(Boolean externalEntities, Boolean expandEntities) {
XMLInputFactory factory = XMLInputFactory.newInstance();
factory.setProperty(IS_SUPPORTING_EXTERNAL_ENTITIES, externalEntities);
factory.setProperty(SUPPORT_DTD, expandEntities);
return factory;
}
public static TransformerFactory createTransformerFactory(Boolean externalEntities, Boolean expandEntities) {
TransformerFactory factory = TransformerFactory.newInstance();
configureTransformerFactory(externalEntities, expandEntities, factory);
return factory;
}
public static void configureTransformerFactory(Boolean externalEntities, Boolean expandEntities, TransformerFactory factory) {
if (!externalEntities && !expandEntities) {
try {
factory.setAttribute(ACCESS_EXTERNAL_STYLESHEET, "");
factory.setAttribute(ACCESS_EXTERNAL_DTD, "");
} catch (Exception e) {
try {
factory.setFeature(FEATURE_SECURE_PROCESSING, true);
} catch (TransformerConfigurationException e1) {
logWarning("TransformerFactory", factory.getClass().getName());
}
}
}
}
public static TransformerFactory createSaxonTransformerFactory(Boolean externalEntities, Boolean expandEntities) {
TransformerFactory factory = new SaxonTransformerFactory();
try {
factory.setFeature(FEATURE_SECURE_PROCESSING, !externalEntities && !expandEntities);
} catch (TransformerConfigurationException e) {
logWarning("SaxonTransformerFactory", factory.getClass().getName());
}
return factory;
}
protected static void logWarning(String interfaceName, String implementationName) {
logger.warn(format("Can't configure XML entity expansion for %s (%s), this could introduce XXE and BL vulnerabilities",
interfaceName, implementationName));
}
}