src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/Canonicalizer.java
changeset 50614 3810c9a2efa1
parent 47216 71c04702a3d5
child 59240 b3116877866f
--- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/Canonicalizer.java	Mon Jun 18 15:24:48 2018 -0700
+++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/Canonicalizer.java	Tue Jun 19 08:06:35 2018 +0800
@@ -25,13 +25,12 @@
 import java.io.ByteArrayInputStream;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.nio.charset.StandardCharsets;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 
-import javax.xml.XMLConstants;
 import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
 
 import com.sun.org.apache.xml.internal.security.c14n.implementations.Canonicalizer11_OmitComments;
 import com.sun.org.apache.xml.internal.security.c14n.implementations.Canonicalizer11_WithComments;
@@ -42,6 +41,7 @@
 import com.sun.org.apache.xml.internal.security.c14n.implementations.CanonicalizerPhysical;
 import com.sun.org.apache.xml.internal.security.exceptions.AlgorithmAlreadyRegisteredException;
 import com.sun.org.apache.xml.internal.security.utils.JavaUtils;
+import com.sun.org.apache.xml.internal.security.utils.XMLUtils;
 import org.w3c.dom.Document;
 import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
@@ -49,12 +49,11 @@
 
 /**
  *
- * @author Christian Geuer-Pollmann
  */
 public class Canonicalizer {
 
     /** The output encoding of canonicalized data */
-    public static final String ENCODING = "UTF8";
+    public static final String ENCODING = StandardCharsets.UTF_8.name();
 
     /**
      * XPath Expression for selecting every node and continuous comments joined
@@ -103,6 +102,7 @@
         new ConcurrentHashMap<String, Class<? extends CanonicalizerSpi>>();
 
     private final CanonicalizerSpi canonicalizerSpi;
+    private boolean secureValidation;
 
     /**
      * Constructor Canonicalizer
@@ -122,7 +122,7 @@
         } catch (Exception e) {
             Object exArgs[] = { algorithmURI };
             throw new InvalidCanonicalizerException(
-                "signature.Canonicalizer.UnknownCanonicalizer", exArgs, e
+                e, "signature.Canonicalizer.UnknownCanonicalizer", exArgs
             );
         }
     }
@@ -162,7 +162,8 @@
         }
 
         canonicalizerHash.put(
-            algorithmURI, (Class<? extends CanonicalizerSpi>)Class.forName(implementingClass)
+            algorithmURI, (Class<? extends CanonicalizerSpi>)
+            ClassLoaderUtils.loadClass(implementingClass, Canonicalizer.class)
         );
     }
 
@@ -244,7 +245,7 @@
     /**
      * This method tries to canonicalize the given bytes. It's possible to even
      * canonicalize non-wellformed sequences if they are well-formed after being
-     * wrapped with a <CODE>&gt;a&lt;...&gt;/a&lt;</CODE>.
+     * wrapped with a {@code &gt;a&lt;...&gt;/a&lt;}.
      *
      * @param inputBytes
      * @return the result of the canonicalization.
@@ -256,47 +257,43 @@
     public byte[] canonicalize(byte[] inputBytes)
         throws javax.xml.parsers.ParserConfigurationException,
         java.io.IOException, org.xml.sax.SAXException, CanonicalizationException {
-        InputStream bais = new ByteArrayInputStream(inputBytes);
-        InputSource in = new InputSource(bais);
-        DocumentBuilderFactory dfactory = DocumentBuilderFactory.newInstance();
-        dfactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, Boolean.TRUE);
+        Document document = null;
+        try (InputStream bais = new ByteArrayInputStream(inputBytes)) {
+            InputSource in = new InputSource(bais);
 
-        dfactory.setNamespaceAware(true);
-
-        // needs to validate for ID attribute normalization
-        dfactory.setValidating(true);
-
-        DocumentBuilder db = dfactory.newDocumentBuilder();
+            // needs to validate for ID attribute normalization
+            DocumentBuilder db = XMLUtils.createDocumentBuilder(true, secureValidation);
 
-        /*
-         * for some of the test vectors from the specification,
-         * there has to be a validating parser for ID attributes, default
-         * attribute values, NMTOKENS, etc.
-         * Unfortunately, the test vectors do use different DTDs or
-         * even no DTD. So Xerces 1.3.1 fires many warnings about using
-         * ErrorHandlers.
-         *
-         * Text from the spec:
-         *
-         * The input octet stream MUST contain a well-formed XML document,
-         * but the input need not be validated. However, the attribute
-         * value normalization and entity reference resolution MUST be
-         * performed in accordance with the behaviors of a validating
-         * XML processor. As well, nodes for default attributes (declared
-         * in the ATTLIST with an AttValue but not specified) are created
-         * in each element. Thus, the declarations in the document type
-         * declaration are used to help create the canonical form, even
-         * though the document type declaration is not retained in the
-         * canonical form.
-         */
-        db.setErrorHandler(new com.sun.org.apache.xml.internal.security.utils.IgnoreAllErrorHandler());
+            /*
+             * for some of the test vectors from the specification,
+             * there has to be a validating parser for ID attributes, default
+             * attribute values, NMTOKENS, etc.
+             * Unfortunately, the test vectors do use different DTDs or
+             * even no DTD. So Xerces 1.3.1 fires many warnings about using
+             * ErrorHandlers.
+             *
+             * Text from the spec:
+             *
+             * The input octet stream MUST contain a well-formed XML document,
+             * but the input need not be validated. However, the attribute
+             * value normalization and entity reference resolution MUST be
+             * performed in accordance with the behaviors of a validating
+             * XML processor. As well, nodes for default attributes (declared
+             * in the ATTLIST with an AttValue but not specified) are created
+             * in each element. Thus, the declarations in the document type
+             * declaration are used to help create the canonical form, even
+             * though the document type declaration is not retained in the
+             * canonical form.
+             */
+            db.setErrorHandler(new com.sun.org.apache.xml.internal.security.utils.IgnoreAllErrorHandler());
 
-        Document document = db.parse(in);
+            document = db.parse(in);
+        }
         return this.canonicalizeSubtree(document);
     }
 
     /**
-     * Canonicalizes the subtree rooted by <CODE>node</CODE>.
+     * Canonicalizes the subtree rooted by {@code node}.
      *
      * @param node The node to canonicalize
      * @return the result of the c14n.
@@ -304,11 +301,12 @@
      * @throws CanonicalizationException
      */
     public byte[] canonicalizeSubtree(Node node) throws CanonicalizationException {
+        canonicalizerSpi.secureValidation = secureValidation;
         return canonicalizerSpi.engineCanonicalizeSubTree(node);
     }
 
     /**
-     * Canonicalizes the subtree rooted by <CODE>node</CODE>.
+     * Canonicalizes the subtree rooted by {@code node}.
      *
      * @param node
      * @param inclusiveNamespaces
@@ -317,11 +315,26 @@
      */
     public byte[] canonicalizeSubtree(Node node, String inclusiveNamespaces)
         throws CanonicalizationException {
+        canonicalizerSpi.secureValidation = secureValidation;
         return canonicalizerSpi.engineCanonicalizeSubTree(node, inclusiveNamespaces);
     }
 
     /**
-     * Canonicalizes an XPath node set. The <CODE>xpathNodeSet</CODE> is treated
+     * Canonicalizes the subtree rooted by {@code node}.
+     *
+     * @param node
+     * @param inclusiveNamespaces
+     * @return the result of the c14n.
+     * @throws CanonicalizationException
+     */
+    public byte[] canonicalizeSubtree(Node node, String inclusiveNamespaces, boolean propagateDefaultNamespace)
+            throws CanonicalizationException {
+        canonicalizerSpi.secureValidation = secureValidation;
+        return canonicalizerSpi.engineCanonicalizeSubTree(node, inclusiveNamespaces, propagateDefaultNamespace);
+    }
+
+    /**
+     * Canonicalizes an XPath node set. The {@code xpathNodeSet} is treated
      * as a list of XPath nodes, not as a list of subtrees.
      *
      * @param xpathNodeSet
@@ -330,11 +343,12 @@
      */
     public byte[] canonicalizeXPathNodeSet(NodeList xpathNodeSet)
         throws CanonicalizationException {
+        canonicalizerSpi.secureValidation = secureValidation;
         return canonicalizerSpi.engineCanonicalizeXPathNodeSet(xpathNodeSet);
     }
 
     /**
-     * Canonicalizes an XPath node set. The <CODE>xpathNodeSet</CODE> is treated
+     * Canonicalizes an XPath node set. The {@code xpathNodeSet} is treated
      * as a list of XPath nodes, not as a list of subtrees.
      *
      * @param xpathNodeSet
@@ -345,6 +359,7 @@
     public byte[] canonicalizeXPathNodeSet(
         NodeList xpathNodeSet, String inclusiveNamespaces
     ) throws CanonicalizationException {
+        canonicalizerSpi.secureValidation = secureValidation;
         return
             canonicalizerSpi.engineCanonicalizeXPathNodeSet(xpathNodeSet, inclusiveNamespaces);
     }
@@ -358,6 +373,7 @@
      */
     public byte[] canonicalizeXPathNodeSet(Set<Node> xpathNodeSet)
         throws CanonicalizationException {
+        canonicalizerSpi.secureValidation = secureValidation;
         return canonicalizerSpi.engineCanonicalizeXPathNodeSet(xpathNodeSet);
     }
 
@@ -372,6 +388,7 @@
     public byte[] canonicalizeXPathNodeSet(
         Set<Node> xpathNodeSet, String inclusiveNamespaces
     ) throws CanonicalizationException {
+        canonicalizerSpi.secureValidation = secureValidation;
         return
             canonicalizerSpi.engineCanonicalizeXPathNodeSet(xpathNodeSet, inclusiveNamespaces);
     }
@@ -401,4 +418,12 @@
         canonicalizerSpi.reset = false;
     }
 
+    public boolean isSecureValidation() {
+        return secureValidation;
+    }
+
+    public void setSecureValidation(boolean secureValidation) {
+        this.secureValidation = secureValidation;
+    }
+
 }