1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.forgerock.util.xml;
18
19 import java.lang.reflect.Method;
20 import javax.xml.XMLConstants;
21 import javax.xml.parsers.DocumentBuilder;
22 import javax.xml.parsers.DocumentBuilderFactory;
23 import javax.xml.parsers.ParserConfigurationException;
24 import javax.xml.parsers.SAXParser;
25 import javax.xml.parsers.SAXParserFactory;
26 import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory;
28 import org.xml.sax.SAXException;
29
30
31
32
33 public final class XMLUtils {
34
35 private static final Logger LOGGER = LoggerFactory.getLogger(XMLUtils.class);
36 private static final Object SECURITY_MANAGER;
37 private static final Integer ENTITY_EXP_LIMIT =
38 Integer.getInteger("org.forgerock.util.xml.entity.expansion.limit", 5000);
39
40
41
42
43
44
45
46
47
48 static {
49 Object securityManager = null;
50 try {
51 Class<?> securityManagerClass = Class.forName("org.apache.xerces.util.SecurityManager");
52 securityManager = securityManagerClass.newInstance();
53 Method setEntityExpansionLimit = securityManagerClass.getMethod("setEntityExpansionLimit", int.class);
54 setEntityExpansionLimit.invoke(securityManager, ENTITY_EXP_LIMIT);
55 } catch (ClassNotFoundException ex) {
56 LOGGER.debug("Not using Xerces");
57 } catch (Exception ex) {
58 LOGGER.debug("Unable to set expansion limit for Xerces, using default settings", ex);
59 securityManager = null;
60 }
61 SECURITY_MANAGER = securityManager;
62 }
63
64 private XMLUtils() {
65
66 }
67
68
69
70
71
72
73
74
75
76
77 public static DocumentBuilder getSafeDocumentBuilder(boolean validating) throws ParserConfigurationException {
78 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
79 dbf.setValidating(validating);
80 dbf.setNamespaceAware(true);
81 dbf.setXIncludeAware(false);
82 dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
83 dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
84 dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
85 dbf.setExpandEntityReferences(false);
86 if (SECURITY_MANAGER != null) {
87 dbf.setAttribute("http://apache.org/xml/properties/security-manager", SECURITY_MANAGER);
88 }
89 try {
90 dbf.setAttribute("http://www.oracle.com/xml/jaxp/properties/entityExpansionLimit", ENTITY_EXP_LIMIT);
91 } catch (IllegalArgumentException ie) { }
92 DocumentBuilder db = dbf.newDocumentBuilder();
93 db.setEntityResolver(new XMLHandler());
94 return db;
95 }
96
97
98
99
100
101
102
103
104
105
106
107
108 public static SAXParser getSafeSAXParser(boolean validating) throws ParserConfigurationException, SAXException {
109 SAXParserFactory saxFactory = SAXParserFactory.newInstance();
110 saxFactory.setValidating(validating);
111 saxFactory.setNamespaceAware(true);
112 saxFactory.setXIncludeAware(false);
113 saxFactory.setFeature("http://xml.org/sax/features/external-general-entities", false);
114 saxFactory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
115 saxFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
116 SAXParser sp = saxFactory.newSAXParser();
117 if (SECURITY_MANAGER != null) {
118 sp.setProperty("http://apache.org/xml/properties/security-manager", SECURITY_MANAGER);
119 }
120 try {
121 sp.setProperty("http://www.oracle.com/xml/jaxp/properties/entityExpansionLimit", ENTITY_EXP_LIMIT);
122 } catch (Exception ex) { }
123 sp.getXMLReader().setEntityResolver(new XMLHandler());
124 return sp;
125 }
126 }