src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/XMLSignatureInput.java
changeset 50614 3810c9a2efa1
parent 47216 71c04702a3d5
child 59240 b3116877866f
equal deleted inserted replaced
50613:0f93a75b9213 50614:3810c9a2efa1
    25 import java.io.ByteArrayInputStream;
    25 import java.io.ByteArrayInputStream;
    26 import java.io.ByteArrayOutputStream;
    26 import java.io.ByteArrayOutputStream;
    27 import java.io.IOException;
    27 import java.io.IOException;
    28 import java.io.InputStream;
    28 import java.io.InputStream;
    29 import java.io.OutputStream;
    29 import java.io.OutputStream;
       
    30 import java.nio.charset.StandardCharsets;
    30 import java.util.ArrayList;
    31 import java.util.ArrayList;
    31 import java.util.LinkedHashSet;
    32 import java.util.LinkedHashSet;
    32 import java.util.List;
    33 import java.util.List;
    33 import java.util.Set;
    34 import java.util.Set;
    34 
    35 
    35 import javax.xml.XMLConstants;
       
    36 import javax.xml.parsers.DocumentBuilder;
    36 import javax.xml.parsers.DocumentBuilder;
    37 import javax.xml.parsers.DocumentBuilderFactory;
       
    38 import javax.xml.parsers.ParserConfigurationException;
    37 import javax.xml.parsers.ParserConfigurationException;
    39 
    38 
    40 import com.sun.org.apache.xml.internal.security.c14n.CanonicalizationException;
    39 import com.sun.org.apache.xml.internal.security.c14n.CanonicalizationException;
       
    40 import com.sun.org.apache.xml.internal.security.c14n.implementations.Canonicalizer11_OmitComments;
       
    41 import com.sun.org.apache.xml.internal.security.c14n.implementations.Canonicalizer20010315OmitComments;
    41 import com.sun.org.apache.xml.internal.security.c14n.implementations.CanonicalizerBase;
    42 import com.sun.org.apache.xml.internal.security.c14n.implementations.CanonicalizerBase;
    42 import com.sun.org.apache.xml.internal.security.c14n.implementations.Canonicalizer20010315OmitComments;
       
    43 import com.sun.org.apache.xml.internal.security.c14n.implementations.Canonicalizer11_OmitComments;
       
    44 import com.sun.org.apache.xml.internal.security.exceptions.XMLSecurityRuntimeException;
    43 import com.sun.org.apache.xml.internal.security.exceptions.XMLSecurityRuntimeException;
    45 import com.sun.org.apache.xml.internal.security.utils.JavaUtils;
    44 import com.sun.org.apache.xml.internal.security.utils.JavaUtils;
    46 import com.sun.org.apache.xml.internal.security.utils.XMLUtils;
    45 import com.sun.org.apache.xml.internal.security.utils.XMLUtils;
    47 import org.w3c.dom.Document;
    46 import org.w3c.dom.Document;
    48 import org.w3c.dom.Node;
    47 import org.w3c.dom.Node;
    49 import org.xml.sax.SAXException;
    48 import org.xml.sax.SAXException;
    50 
    49 
    51 /**
    50 /**
    52  * Class XMLSignatureInput
    51  * Class XMLSignatureInput
    53  *
    52  *
    54  * @author Christian Geuer-Pollmann
       
    55  * $todo$ check whether an XMLSignatureInput can be _both_, octet stream _and_ node set?
    53  * $todo$ check whether an XMLSignatureInput can be _both_, octet stream _and_ node set?
    56  */
    54  */
    57 public class XMLSignatureInput {
    55 public class XMLSignatureInput {
    58     /*
    56     /*
    59      * The XMLSignature Input can be either:
    57      * The XMLSignature Input can be either:
    66 
    64 
    67     /**
    65     /**
    68      * Some InputStreams do not support the {@link java.io.InputStream#reset}
    66      * Some InputStreams do not support the {@link java.io.InputStream#reset}
    69      * method, so we read it in completely and work on our Proxy.
    67      * method, so we read it in completely and work on our Proxy.
    70      */
    68      */
    71     private InputStream inputOctetStreamProxy = null;
    69     private InputStream inputOctetStreamProxy;
    72     /**
    70     /**
    73      * The original NodeSet for this XMLSignatureInput
    71      * The original NodeSet for this XMLSignatureInput
    74      */
    72      */
    75     private Set<Node> inputNodeSet = null;
    73     private Set<Node> inputNodeSet;
    76     /**
    74     /**
    77      * The original Element
    75      * The original Element
    78      */
    76      */
    79     private Node subNode = null;
    77     private Node subNode;
    80     /**
    78     /**
    81      * Exclude Node *for enveloped transformations*
    79      * Exclude Node *for enveloped transformations*
    82      */
    80      */
    83     private Node excludeNode = null;
    81     private Node excludeNode;
    84     /**
    82     /**
    85      *
    83      *
    86      */
    84      */
    87     private boolean excludeComments = false;
    85     private boolean excludeComments = false;
    88 
    86 
    89     private boolean isNodeSet = false;
    87     private boolean isNodeSet = false;
    90     /**
    88     /**
    91      * A cached bytes
    89      * A cached bytes
    92      */
    90      */
    93     private byte[] bytes = null;
    91     private byte[] bytes;
       
    92     private boolean secureValidation;
    94 
    93 
    95     /**
    94     /**
    96      * Some Transforms may require explicit MIME type, charset (IANA registered
    95      * Some Transforms may require explicit MIME type, charset (IANA registered
    97      * "character set"), or other such information concerning the data they are
    96      * "character set"), or other such information concerning the data they are
    98      * receiving from an earlier Transform or the source data, although no
    97      * receiving from an earlier Transform or the source data, although no
    99      * Transform algorithm specified in this document needs such explicit
    98      * Transform algorithm specified in this document needs such explicit
   100      * information. Such data characteristics are provided as parameters to the
    99      * information. Such data characteristics are provided as parameters to the
   101      * Transform algorithm and should be described in the specification for the
   100      * Transform algorithm and should be described in the specification for the
   102      * algorithm.
   101      * algorithm.
   103      */
   102      */
   104     private String mimeType = null;
   103     private String mimeType;
   105 
   104 
   106     /**
   105     /**
   107      * Field sourceURI
   106      * Field sourceURI
   108      */
   107      */
   109     private String sourceURI = null;
   108     private String sourceURI;
   110 
   109 
   111     /**
   110     /**
   112      * Node Filter list.
   111      * Node Filter list.
   113      */
   112      */
   114     private List<NodeFilter> nodeFilters = new ArrayList<NodeFilter>();
   113     private List<NodeFilter> nodeFilters = new ArrayList<>();
   115 
   114 
   116     private boolean needsToBeExpanded = false;
   115     private boolean needsToBeExpanded = false;
   117     private OutputStream outputStream = null;
   116     private OutputStream outputStream;
   118 
   117 
   119     private DocumentBuilderFactory dfactory;
   118     /**
       
   119      * Pre-calculated digest value of the object in base64.
       
   120      */
       
   121     private String preCalculatedDigest;
   120 
   122 
   121     /**
   123     /**
   122      * Construct a XMLSignatureInput from an octet array.
   124      * Construct a XMLSignatureInput from an octet array.
   123      * <p>
   125      * <p>
   124      * This is a comfort method, which internally converts the byte[] array into
   126      * This is a comfort method, which internally converts the byte[] array into
   130         // NO defensive copy
   132         // NO defensive copy
   131         this.bytes = inputOctets;
   133         this.bytes = inputOctets;
   132     }
   134     }
   133 
   135 
   134     /**
   136     /**
   135      * Constructs a <code>XMLSignatureInput</code> from an octet stream. The
   137      * Constructs a {@code XMLSignatureInput} from an octet stream. The
   136      * stream is directly read.
   138      * stream is directly read.
   137      *
   139      *
   138      * @param inputOctetStream
   140      * @param inputOctetStream
   139      */
   141      */
   140     public XMLSignatureInput(InputStream inputOctetStream)  {
   142     public XMLSignatureInput(InputStream inputOctetStream)  {
   156      *
   158      *
   157      * @param inputNodeSet
   159      * @param inputNodeSet
   158      */
   160      */
   159     public XMLSignatureInput(Set<Node> inputNodeSet) {
   161     public XMLSignatureInput(Set<Node> inputNodeSet) {
   160         this.inputNodeSet = inputNodeSet;
   162         this.inputNodeSet = inputNodeSet;
       
   163     }
       
   164 
       
   165     /**
       
   166      * Construct a {@code XMLSignatureInput} from a known digest value in Base64.
       
   167      * This makes it possible to compare the element digest with the provided digest value.
       
   168      * @param preCalculatedDigest digest value in base64.
       
   169      */
       
   170     public XMLSignatureInput(String preCalculatedDigest) {
       
   171         this.preCalculatedDigest = preCalculatedDigest;
   161     }
   172     }
   162 
   173 
   163     /**
   174     /**
   164      * Check if the structure needs to be expanded.
   175      * Check if the structure needs to be expanded.
   165      * @return true if so.
   176      * @return true if so.
   284      * Determines if the object has been set up with a Node set
   295      * Determines if the object has been set up with a Node set
   285      *
   296      *
   286      * @return true if the object has been set up with a Node set
   297      * @return true if the object has been set up with a Node set
   287      */
   298      */
   288     public boolean isNodeSet() {
   299     public boolean isNodeSet() {
   289         return ((inputOctetStreamProxy == null
   300         return inputOctetStreamProxy == null && inputNodeSet != null || isNodeSet;
   290             && inputNodeSet != null) || isNodeSet);
       
   291     }
   301     }
   292 
   302 
   293     /**
   303     /**
   294      * Determines if the object has been set up with an Element
   304      * Determines if the object has been set up with an Element
   295      *
   305      *
   296      * @return true if the object has been set up with an Element
   306      * @return true if the object has been set up with an Element
   297      */
   307      */
   298     public boolean isElement() {
   308     public boolean isElement() {
   299         return (inputOctetStreamProxy == null && subNode != null
   309         return inputOctetStreamProxy == null && subNode != null
   300             && inputNodeSet == null && !isNodeSet);
   310             && inputNodeSet == null && !isNodeSet;
   301     }
   311     }
   302 
   312 
   303     /**
   313     /**
   304      * Determines if the object has been set up with an octet stream
   314      * Determines if the object has been set up with an octet stream
   305      *
   315      *
   306      * @return true if the object has been set up with an octet stream
   316      * @return true if the object has been set up with an octet stream
   307      */
   317      */
   308     public boolean isOctetStream() {
   318     public boolean isOctetStream() {
   309         return ((inputOctetStreamProxy != null || bytes != null)
   319         return (inputOctetStreamProxy != null || bytes != null)
   310           && (inputNodeSet == null && subNode == null));
   320           && inputNodeSet == null && subNode == null;
   311     }
   321     }
   312 
   322 
   313     /**
   323     /**
   314      * Determines if {@link #setOutputStream} has been called with a
   324      * Determines if {@link #setOutputStream} has been called with a
   315      * non-null OutputStream.
   325      * non-null OutputStream.
   325      * Determines if the object has been set up with a ByteArray
   335      * Determines if the object has been set up with a ByteArray
   326      *
   336      *
   327      * @return true is the object has been set up with an octet stream
   337      * @return true is the object has been set up with an octet stream
   328      */
   338      */
   329     public boolean isByteArray() {
   339     public boolean isByteArray() {
   330         return (bytes != null && (this.inputNodeSet == null && subNode == null));
   340         return bytes != null && this.inputNodeSet == null && subNode == null;
       
   341     }
       
   342 
       
   343     /**
       
   344      * Determines if the object has been set up with a pre-calculated digest.
       
   345      * @return
       
   346      */
       
   347     public boolean isPreCalculatedDigest() {
       
   348         return preCalculatedDigest != null;
   331     }
   349     }
   332 
   350 
   333     /**
   351     /**
   334      * Is the object correctly set up?
   352      * Is the object correctly set up?
   335      *
   353      *
   375         this.sourceURI = sourceURI;
   393         this.sourceURI = sourceURI;
   376     }
   394     }
   377 
   395 
   378     /**
   396     /**
   379      * Method toString
   397      * Method toString
   380      * @inheritDoc
   398      * {@inheritDoc}
   381      */
   399      */
   382     public String toString() {
   400     public String toString() {
   383         if (isNodeSet()) {
   401         if (isNodeSet()) {
   384             return "XMLSignatureInput/NodeSet/" + inputNodeSet.size()
   402             return "XMLSignatureInput/NodeSet/" + inputNodeSet.size()
   385                    + " nodes/" + getSourceURI();
   403                    + " nodes/" + getSourceURI();
   554         isNodeSet = b;
   572         isNodeSet = b;
   555     }
   573     }
   556 
   574 
   557     void convertToNodes() throws CanonicalizationException,
   575     void convertToNodes() throws CanonicalizationException,
   558         ParserConfigurationException, IOException, SAXException {
   576         ParserConfigurationException, IOException, SAXException {
   559         if (dfactory == null) {
   577         DocumentBuilder db = XMLUtils.createDocumentBuilder(false, secureValidation);
   560             dfactory = DocumentBuilderFactory.newInstance();
       
   561             dfactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, Boolean.TRUE);
       
   562             dfactory.setValidating(false);
       
   563             dfactory.setNamespaceAware(true);
       
   564         }
       
   565         DocumentBuilder db = dfactory.newDocumentBuilder();
       
   566         // select all nodes, also the comments.
   578         // select all nodes, also the comments.
   567         try {
   579         try {
   568             db.setErrorHandler(new com.sun.org.apache.xml.internal.security.utils.IgnoreAllErrorHandler());
   580             db.setErrorHandler(new com.sun.org.apache.xml.internal.security.utils.IgnoreAllErrorHandler());
   569 
   581 
   570             Document doc = db.parse(this.getOctetStream());
   582             Document doc = db.parse(this.getOctetStream());
   571             this.subNode = doc;
   583             this.subNode = doc;
   572         } catch (SAXException ex) {
   584         } catch (SAXException ex) {
       
   585             byte[] result = null;
   573             // if a not-wellformed nodeset exists, put a container around it...
   586             // if a not-wellformed nodeset exists, put a container around it...
   574             ByteArrayOutputStream baos = new ByteArrayOutputStream();
   587             try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
   575 
   588 
   576             baos.write("<container>".getBytes("UTF-8"));
   589                 baos.write("<container>".getBytes(StandardCharsets.UTF_8));
   577             baos.write(this.getBytes());
   590                 baos.write(this.getBytes());
   578             baos.write("</container>".getBytes("UTF-8"));
   591                 baos.write("</container>".getBytes(StandardCharsets.UTF_8));
   579 
   592 
   580             byte result[] = baos.toByteArray();
   593                 result = baos.toByteArray();
   581             Document document = db.parse(new ByteArrayInputStream(result));
   594             }
   582             this.subNode = document.getDocumentElement().getFirstChild().getFirstChild();
   595             try (InputStream is = new ByteArrayInputStream(result)) {
       
   596                 Document document = db.parse(is);
       
   597                 this.subNode = document.getDocumentElement().getFirstChild().getFirstChild();
       
   598             }
   583         } finally {
   599         } finally {
   584             if (this.inputOctetStreamProxy != null) {
   600             if (this.inputOctetStreamProxy != null) {
   585                 this.inputOctetStreamProxy.close();
   601                 this.inputOctetStreamProxy.close();
   586             }
   602             }
   587             this.inputOctetStreamProxy = null;
   603             this.inputOctetStreamProxy = null;
   588             this.bytes = null;
   604             this.bytes = null;
   589         }
   605         }
   590     }
   606     }
   591 
   607 
       
   608     public boolean isSecureValidation() {
       
   609         return secureValidation;
       
   610     }
       
   611 
       
   612     public void setSecureValidation(boolean secureValidation) {
       
   613         this.secureValidation = secureValidation;
       
   614     }
       
   615 
       
   616     public String getPreCalculatedDigest() {
       
   617         return preCalculatedDigest;
       
   618     }
   592 }
   619 }