/**
* Copyright (c) 2000-present Liferay, Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*/
package com.liferay.portal.security.xml;
import com.liferay.portal.kernel.exception.SystemException;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.security.xml.SecureXMLFactoryProvider;
import com.liferay.portal.kernel.util.ClassLoaderUtil;
import com.liferay.portal.util.PropsValues;
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.stream.XMLInputFactory;
import org.apache.xerces.parsers.SAXParser;
import org.xml.sax.XMLReader;
/**
* @author Tomas Polesovsky
*/
public class SecureXMLFactoryProviderImpl implements SecureXMLFactoryProvider {
@Override
public DocumentBuilderFactory newDocumentBuilderFactory() {
DocumentBuilderFactory documentBuilderFactory =
DocumentBuilderFactory.newInstance();
if (!PropsValues.XML_SECURITY_ENABLED) {
return documentBuilderFactory;
}
try {
documentBuilderFactory.setFeature(
XMLConstants.FEATURE_SECURE_PROCESSING, true);
}
catch (Exception e) {
_log.error(
"Unable to initialize safe document builder factory to " +
"protect from XML Bomb attacks",
e);
}
try {
documentBuilderFactory.setFeature(
_FEATURES_DISALLOW_DOCTYPE_DECL, true);
}
catch (Exception e) {
_log.error(
"Unable to initialize safe document builder factory to " +
"protect from XML Bomb attacks",
e);
}
try {
documentBuilderFactory.setExpandEntityReferences(false);
documentBuilderFactory.setFeature(
_FEATURES_EXTERNAL_GENERAL_ENTITIES, false);
documentBuilderFactory.setFeature(
_FEATURES_EXTERNAL_PARAMETER_ENTITIES, false);
}
catch (Exception e) {
_log.error(
"Unable to initialize safe document builder factory to " +
"protect from XXE attacks",
e);
}
return documentBuilderFactory;
}
@Override
public XMLInputFactory newXMLInputFactory() {
XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
if (!PropsValues.XML_SECURITY_ENABLED) {
return xmlInputFactory;
}
xmlInputFactory.setProperty(
XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, Boolean.FALSE);
xmlInputFactory.setProperty(
XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, Boolean.FALSE);
xmlInputFactory.setProperty(XMLInputFactory.SUPPORT_DTD, Boolean.FALSE);
return xmlInputFactory;
}
@Override
public XMLReader newXMLReader() {
Class<?> clazz = getClass();
ClassLoader classLoader = clazz.getClassLoader();
ClassLoader contextClassLoader =
ClassLoaderUtil.getContextClassLoader();
XMLReader xmlReader = null;
try {
if (classLoader != contextClassLoader) {
ClassLoaderUtil.setContextClassLoader(classLoader);
}
xmlReader = new SAXParser();
}
catch (RuntimeException re) {
throw new SystemException(re);
}
finally {
if (classLoader != contextClassLoader) {
ClassLoaderUtil.setContextClassLoader(contextClassLoader);
}
}
if (!PropsValues.XML_SECURITY_ENABLED) {
return xmlReader;
}
xmlReader = new StripDoctypeXMLReader(xmlReader);
try {
xmlReader.setFeature(_FEATURES_DISALLOW_DOCTYPE_DECL, true);
}
catch (Exception e) {
_log.error(
"Unable to initialize safe SAX parser to protect from XML " +
"Bomb attacks",
e);
}
try {
xmlReader.setFeature(_FEATURES_EXTERNAL_GENERAL_ENTITIES, false);
xmlReader.setFeature(_FEATURES_EXTERNAL_PARAMETER_ENTITIES, false);
}
catch (Exception e) {
_log.error(
"Unable to initialize safe SAX parser to protect from XXE " +
"attacks",
e);
}
return xmlReader;
}
private static final String _FEATURES_DISALLOW_DOCTYPE_DECL =
"http://apache.org/xml/features/disallow-doctype-decl";
private static final String _FEATURES_EXTERNAL_GENERAL_ENTITIES =
"http://xml.org/sax/features/external-general-entities";
private static final String _FEATURES_EXTERNAL_PARAMETER_ENTITIES =
"http://xml.org/sax/features/external-parameter-entities";
private static final Log _log = LogFactoryUtil.getLog(
SecureXMLFactoryProviderImpl.class);
}