001
014
015 package com.liferay.portal.security.xml;
016
017 import com.liferay.portal.kernel.log.Log;
018 import com.liferay.portal.kernel.log.LogFactoryUtil;
019 import com.liferay.portal.util.ClassLoaderUtil;
020 import com.liferay.portal.util.PropsValues;
021
022 import javax.xml.XMLConstants;
023 import javax.xml.parsers.DocumentBuilderFactory;
024 import javax.xml.stream.XMLInputFactory;
025
026 import org.apache.xerces.parsers.SAXParser;
027
028 import org.xml.sax.XMLReader;
029
030
033 public class SecureXMLFactoryProviderImpl implements SecureXMLFactoryProvider {
034
035 @Override
036 public DocumentBuilderFactory newDocumentBuilderFactory() {
037 DocumentBuilderFactory documentBuilderFactory =
038 DocumentBuilderFactory.newInstance();
039
040 if (!PropsValues.XML_SECURITY_ENABLED) {
041 return documentBuilderFactory;
042 }
043
044 try {
045 documentBuilderFactory.setFeature(
046 XMLConstants.FEATURE_SECURE_PROCESSING, true);
047 }
048 catch (Exception e) {
049 _log.error(
050 "Unable to initialize safe document builder factory to " +
051 "protect from XML Bomb attacks",
052 e);
053 }
054
055 try {
056 documentBuilderFactory.setFeature(
057 _FEATURES_DISALLOW_DOCTYPE_DECL, true);
058 }
059 catch (Exception e) {
060 _log.error(
061 "Unable to initialize safe document builder factory to " +
062 "protect from XML Bomb attacks",
063 e);
064 }
065
066 try {
067 documentBuilderFactory.setExpandEntityReferences(false);
068 documentBuilderFactory.setFeature(
069 _FEATURES_EXTERNAL_GENERAL_ENTITIES, false);
070 documentBuilderFactory.setFeature(
071 _FEATURES_EXTERNAL_PARAMETER_ENTITIES, false);
072 }
073 catch (Exception e) {
074 _log.error(
075 "Unable to initialize safe document builder factory to " +
076 "protect from XXE attacks",
077 e);
078 }
079
080 return documentBuilderFactory;
081 }
082
083 @Override
084 public XMLInputFactory newXMLInputFactory() {
085 XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
086
087 if (!PropsValues.XML_SECURITY_ENABLED) {
088 return xmlInputFactory;
089 }
090
091 xmlInputFactory.setProperty(
092 XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, Boolean.FALSE);
093 xmlInputFactory.setProperty(
094 XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, Boolean.FALSE);
095 xmlInputFactory.setProperty(XMLInputFactory.SUPPORT_DTD, Boolean.FALSE);
096
097 return xmlInputFactory;
098 }
099
100 @Override
101 public XMLReader newXMLReader() {
102 Class<?> clazz = getClass();
103
104 ClassLoader classLoader = clazz.getClassLoader();
105
106 ClassLoader contextClassLoader =
107 ClassLoaderUtil.getContextClassLoader();
108
109 XMLReader xmlReader = null;
110
111 try {
112 if (classLoader != contextClassLoader) {
113 ClassLoaderUtil.setContextClassLoader(classLoader);
114 }
115
116 xmlReader = new SAXParser();
117 }
118 finally {
119 if (classLoader != contextClassLoader) {
120 ClassLoaderUtil.setContextClassLoader(contextClassLoader);
121 }
122 }
123
124 if (!PropsValues.XML_SECURITY_ENABLED) {
125 return xmlReader;
126 }
127
128 xmlReader = new StripDoctypeXMLReader(xmlReader);
129
130 try {
131 xmlReader.setFeature(_FEATURES_DISALLOW_DOCTYPE_DECL, true);
132 }
133 catch (Exception e) {
134 _log.error(
135 "Unable to initialize safe SAX parser to protect from XML " +
136 "Bomb attacks",
137 e);
138 }
139
140 try {
141 xmlReader.setFeature(_FEATURES_EXTERNAL_GENERAL_ENTITIES, false);
142 xmlReader.setFeature(_FEATURES_EXTERNAL_PARAMETER_ENTITIES, false);
143 }
144 catch (Exception e) {
145 _log.error(
146 "Unable to initialize safe SAX parser to protect from XXE " +
147 "attacks",
148 e);
149 }
150
151 return xmlReader;
152 }
153
154 private static final String _FEATURES_DISALLOW_DOCTYPE_DECL =
155 "http:
156
157 private static final String _FEATURES_EXTERNAL_GENERAL_ENTITIES =
158 "http:
159
160 private static final String _FEATURES_EXTERNAL_PARAMETER_ENTITIES =
161 "http:
162
163 private static Log _log = LogFactoryUtil.getLog(
164 SecureXMLFactoryProviderImpl.class);
165
166 }