1212import org .elasticsearch .common .Strings ;
1313import org .elasticsearch .common .hash .MessageDigests ;
1414import org .elasticsearch .core .SuppressForbidden ;
15+ import org .elasticsearch .core .XmlUtils ;
1516import org .opensaml .core .xml .XMLObject ;
1617import org .opensaml .core .xml .XMLObjectBuilderFactory ;
1718import org .opensaml .core .xml .config .XMLObjectProviderRegistrySupport ;
2425import org .opensaml .security .credential .Credential ;
2526import org .opensaml .security .x509 .X509Credential ;
2627import org .w3c .dom .Element ;
27- import org .xml .sax .SAXException ;
28- import org .xml .sax .SAXParseException ;
2928
3029import java .io .StringWriter ;
3130import java .io .Writer ;
3837import java .util .Objects ;
3938import java .util .stream .Collectors ;
4039
41- import javax .xml .XMLConstants ;
4240import javax .xml .namespace .QName ;
4341import javax .xml .parsers .DocumentBuilder ;
44- import javax .xml .parsers .DocumentBuilderFactory ;
4542import javax .xml .parsers .ParserConfigurationException ;
4643import javax .xml .transform .OutputKeys ;
4744import javax .xml .transform .Transformer ;
48- import javax .xml .transform .TransformerConfigurationException ;
4945import javax .xml .transform .TransformerException ;
50- import javax .xml .transform .TransformerFactory ;
5146import javax .xml .transform .dom .DOMSource ;
5247import javax .xml .transform .stream .StreamResult ;
5348
@@ -143,7 +138,7 @@ public static <T extends XMLObject> T buildXmlObject(Element element, Class<T> t
143138 }
144139
145140 void print (Element element , Writer writer , boolean pretty ) throws TransformerException {
146- final Transformer serializer = getHardenedXMLTransformer ();
141+ final Transformer serializer = XmlUtils . getHardenedXMLTransformer ();
147142 if (pretty ) {
148143 serializer .setOutputProperty (OutputKeys .INDENT , "yes" );
149144 }
@@ -217,57 +212,14 @@ public static Element toDomElement(XMLObject object) {
217212 }
218213 }
219214
220- @ SuppressForbidden (reason = "This is the only allowed way to construct a Transformer" )
221- public static Transformer getHardenedXMLTransformer () throws TransformerConfigurationException {
222- final TransformerFactory tfactory = TransformerFactory .newInstance ();
223- tfactory .setFeature (XMLConstants .FEATURE_SECURE_PROCESSING , true );
224- tfactory .setAttribute (XMLConstants .ACCESS_EXTERNAL_DTD , "" );
225- tfactory .setAttribute (XMLConstants .ACCESS_EXTERNAL_STYLESHEET , "" );
226- tfactory .setAttribute ("indent-number" , 2 );
227- Transformer transformer = tfactory .newTransformer ();
228- transformer .setErrorListener (new SamlFactory .TransformerErrorListener ());
229- return transformer ;
230- }
231-
232215 /**
233216 * Constructs a DocumentBuilder with all the necessary features for it to be secure
234217 *
235218 * @throws ParserConfigurationException if one of the features can't be set on the DocumentBuilderFactory
236219 */
237220 @ SuppressForbidden (reason = "This is the only allowed way to construct a DocumentBuilder" )
238221 public static DocumentBuilder getHardenedBuilder (String [] schemaFiles ) throws ParserConfigurationException {
239- final DocumentBuilderFactory dbf = DocumentBuilderFactory .newInstance ();
240- dbf .setNamespaceAware (true );
241- // Ensure that Schema Validation is enabled for the factory
242- dbf .setValidating (true );
243- // Disallow internal and external entity expansion
244- dbf .setFeature ("http://apache.org/xml/features/disallow-doctype-decl" , true );
245- dbf .setFeature ("http://xml.org/sax/features/external-general-entities" , false );
246- dbf .setFeature ("http://xml.org/sax/features/external-parameter-entities" , false );
247- dbf .setFeature ("http://apache.org/xml/features/nonvalidating/load-external-dtd" , false );
248- dbf .setFeature ("http://xml.org/sax/features/validation" , true );
249- dbf .setFeature ("http://apache.org/xml/features/nonvalidating/load-dtd-grammar" , false );
250- dbf .setIgnoringComments (true );
251- // This is required, otherwise schema validation causes signature invalidation
252- dbf .setFeature ("http://apache.org/xml/features/validation/schema/normalized-value" , false );
253- // Make sure that URL schema namespaces are not resolved/downloaded from URLs we do not control
254- dbf .setAttribute (XMLConstants .ACCESS_EXTERNAL_DTD , "file,jar" );
255- dbf .setAttribute (XMLConstants .ACCESS_EXTERNAL_SCHEMA , "file,jar" );
256- dbf .setFeature ("http://apache.org/xml/features/honour-all-schemaLocations" , true );
257- // Ensure we do not resolve XIncludes. Defaults to false, but set it explicitly to be future-proof
258- dbf .setXIncludeAware (false );
259- // Ensure we do not expand entity reference nodes
260- dbf .setExpandEntityReferences (false );
261- // Further limit danger from denial of service attacks
262- dbf .setFeature (XMLConstants .FEATURE_SECURE_PROCESSING , true );
263- dbf .setAttribute ("http://apache.org/xml/features/validation/schema" , true );
264- dbf .setAttribute ("http://apache.org/xml/features/validation/schema-full-checking" , true );
265- dbf .setAttribute ("http://java.sun.com/xml/jaxp/properties/schemaLanguage" , XMLConstants .W3C_XML_SCHEMA_NS_URI );
266- // We ship our own xsd files for schema validation since we do not trust anyone else.
267- dbf .setAttribute ("http://java.sun.com/xml/jaxp/properties/schemaSource" , resolveSchemaFilePaths (schemaFiles ));
268- DocumentBuilder documentBuilder = dbf .newDocumentBuilder ();
269- documentBuilder .setErrorHandler (new SamlFactory .DocumentBuilderErrorHandler ());
270- return documentBuilder ;
222+ return XmlUtils .getHardenedBuilder (resolveSchemaFilePaths (schemaFiles ));
271223 }
272224
273225 public static String getJavaAlorithmNameFromUri (String sigAlg ) {
@@ -293,31 +245,6 @@ private static String[] resolveSchemaFilePaths(String[] relativePaths) {
293245 }).filter (Objects ::nonNull ).toArray (String []::new );
294246 }
295247
296- private static class DocumentBuilderErrorHandler implements org .xml .sax .ErrorHandler {
297- /**
298- * Enabling schema validation with `setValidating(true)` in our
299- * DocumentBuilderFactory requires that we provide our own
300- * ErrorHandler implementation
301- *
302- * @throws SAXException If the document we attempt to parse is not valid according to the specified schema.
303- */
304- @ Override
305- public void warning (SAXParseException e ) throws SAXException {
306- LOGGER .debug ("XML Parser error " , e );
307- throw e ;
308- }
309-
310- @ Override
311- public void error (SAXParseException e ) throws SAXException {
312- warning (e );
313- }
314-
315- @ Override
316- public void fatalError (SAXParseException e ) throws SAXException {
317- warning (e );
318- }
319- }
320-
321248 private static class TransformerErrorListener implements javax .xml .transform .ErrorListener {
322249
323250 @ Override
0 commit comments