/*
* Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package com.sun.org.apache.xml.internal.security.signature;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.xml.parsers.ParserConfigurationException;
import com.sun.org.apache.xml.internal.security.c14n.CanonicalizationException;
import com.sun.org.apache.xml.internal.security.c14n.InvalidCanonicalizerException;
import com.sun.org.apache.xml.internal.security.exceptions.XMLSecurityException;
import com.sun.org.apache.xml.internal.security.transforms.Transforms;
import com.sun.org.apache.xml.internal.security.utils.Constants;
import com.sun.org.apache.xml.internal.security.utils.I18n;
import com.sun.org.apache.xml.internal.security.utils.SignatureElementProxy;
import com.sun.org.apache.xml.internal.security.utils.XMLUtils;
import com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolver;
import com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverSpi;
import org.w3c.dom.Attr;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;
/**
* Handles <ds:Manifest>
elements.
*
This element holds the Reference
elements
XMLsignature
is placed
*/
public Manifest(Document doc) {
super(doc);
XMLUtils.addReturnToElement(this.constructionElement);
this.references = new ArrayListaddDocument
method is used to add a new resource to the
* signed info. A {@link com.sun.org.apache.xml.internal.security.signature.Reference} is built
* from the supplied values.
*
* @param baseURI the URI of the resource where the XML instance was stored
* @param referenceURI URI
attribute in Reference
for specifying
* where data is
* @param transforms com.sun.org.apache.xml.internal.security.signature.Transforms object with an ordered
* list of transformations to be performed.
* @param digestURI The digest algorithm URI to be used.
* @param referenceId
* @param referenceType
* @throws XMLSignatureException
*/
public void addDocument(
String baseURI, String referenceURI, Transforms transforms,
String digestURI, String referenceId, String referenceType
) throws XMLSignatureException {
// the this.doc is handed implicitly by the this.getOwnerDocument()
Reference ref =
new Reference(this.doc, baseURI, referenceURI, this, transforms, digestURI);
if (referenceId != null) {
ref.setId(referenceId);
}
if (referenceType != null) {
ref.setType(referenceType);
}
// add Reference object to our cache vector
this.references.add(ref);
// add the Element of the Reference object to the Manifest/SignedInfo
this.constructionElement.appendChild(ref.getElement());
XMLUtils.addReturnToElement(this.constructionElement);
}
/**
* The calculation of the DigestValues in the References must be after the
* References are already added to the document and during the signing
* process. This ensures that all necessary data is in place.
*
* @throws ReferenceNotInitializedException
* @throws XMLSignatureException
*/
public void generateDigestValues()
throws XMLSignatureException, ReferenceNotInitializedException {
for (int i = 0; i < this.getLength(); i++) {
// update the cached Reference object, the Element content is automatically updated
Reference currentRef = this.references.get(i);
currentRef.generateDigestValue();
}
}
/**
* Return the nonnegative number of added references.
*
* @return the number of references
*/
public int getLength() {
return this.references.size();
}
/**
* Return the i
* values are 0 to {link@ getSize}-1
.
*
* @param i Index of the requested {@link Reference}
* @return the Id
attribute
*
* @param Id the Id
attribute in ds:Manifest
*/
public void setId(String Id) {
if (Id != null) {
this.constructionElement.setAttributeNS(null, Constants._ATT_ID, Id);
this.constructionElement.setIdAttributeNS(null, Constants._ATT_ID, true);
}
}
/**
* Returns the Id
attribute
*
* @return the Id
attribute in ds:Manifest
*/
public String getId() {
return this.constructionElement.getAttributeNS(null, Constants._ATT_ID);
}
/**
* Used to do a reference
* validation of all enclosed references using the {@link Reference#verify} method.
*
* This step loops through all {@link Reference}s and does verify the hash
* values. If one or more verifications fail, the method returns
* false
. If all verifications are successful,
* it returns true
. The results of the individual reference
* validations are available by using the {@link #getVerificationResult(int)} method
*
* @return true if all References verify, false if one or more do not verify.
* @throws MissingResourceFailureException if a {@link Reference} does not verify
* (throws a {@link com.sun.org.apache.xml.internal.security.signature.ReferenceNotInitializedException}
* because of an uninitialized {@link XMLSignatureInput}
* @see com.sun.org.apache.xml.internal.security.signature.Reference#verify
* @see com.sun.org.apache.xml.internal.security.signature.SignedInfo#verify()
* @see com.sun.org.apache.xml.internal.security.signature.MissingResourceFailureException
* @throws XMLSecurityException
*/
public boolean verifyReferences()
throws MissingResourceFailureException, XMLSecurityException {
return this.verifyReferences(false);
}
/**
* Used to do a reference
* validation of all enclosed references using the {@link Reference#verify} method.
*
*
This step loops through all {@link Reference}s and does verify the hash
* values. If one or more verifications fail, the method returns
* false
. If all verifications are successful,
* it returns true
. The results of the individual reference
* validations are available by using the {@link #getVerificationResult(int)} method
*
* @param followManifests
* @return true if all References verify, false if one or more do not verify.
* @throws MissingResourceFailureException if a {@link Reference} does not verify
* (throws a {@link com.sun.org.apache.xml.internal.security.signature.ReferenceNotInitializedException}
* because of an uninitialized {@link XMLSignatureInput}
* @see com.sun.org.apache.xml.internal.security.signature.Reference#verify
* @see com.sun.org.apache.xml.internal.security.signature.SignedInfo#verify(boolean)
* @see com.sun.org.apache.xml.internal.security.signature.MissingResourceFailureException
* @throws XMLSecurityException
*/
public boolean verifyReferences(boolean followManifests)
throws MissingResourceFailureException, XMLSecurityException {
if (referencesEl == null) {
this.referencesEl =
XMLUtils.selectDsNodes(
this.constructionElement.getFirstChild(), Constants._TAG_REFERENCE
);
}
if (log.isLoggable(java.util.logging.Level.FINE)) {
log.log(java.util.logging.Level.FINE, "verify " + referencesEl.length + " References");
log.log(java.util.logging.Level.FINE, "I am " + (followManifests
? "" : "not") + " requested to follow nested Manifests");
}
if (referencesEl.length == 0) {
throw new XMLSecurityException("empty");
}
if (secureValidation && referencesEl.length > MAXIMUM_REFERENCE_COUNT) {
Object exArgs[] = { referencesEl.length, MAXIMUM_REFERENCE_COUNT };
throw new XMLSecurityException("signature.tooManyReferences", exArgs);
}
this.verificationResults = new boolean[referencesEl.length];
boolean verify = true;
for (int i = 0; i < this.referencesEl.length; i++) {
Reference currentRef =
new Reference(referencesEl[i], this.baseURI, this, secureValidation);
this.references.set(i, currentRef);
// if only one item does not verify, the whole verification fails
try {
boolean currentRefVerified = currentRef.verify();
this.setVerificationResult(i, currentRefVerified);
if (!currentRefVerified) {
verify = false;
}
if (log.isLoggable(java.util.logging.Level.FINE)) {
log.log(java.util.logging.Level.FINE, "The Reference has Type " + currentRef.getType());
}
// was verification successful till now and do we want to verify the Manifest?
if (verify && followManifests && currentRef.typeIsReferenceToManifest()) {
if (log.isLoggable(java.util.logging.Level.FINE)) {
log.log(java.util.logging.Level.FINE, "We have to follow a nested Manifest");
}
try {
XMLSignatureInput signedManifestNodes =
currentRef.dereferenceURIandPerformTransforms(null);
SetURI
attribute
* in reference
element
*
* @param resolver {@link ResourceResolver} can provide the implemenatin subclass of
* {@link ResourceResolverSpi} for retrieving resource.
*/
public void addResourceResolver(ResourceResolver resolver) {
if (resolver == null) {
return;
}
if (perManifestResolvers == null) {
perManifestResolvers = new ArrayListURI
attribute
* in reference
element
*
* @param resolverSpi the implementation subclass of {@link ResourceResolverSpi} for
* retrieving the resource.
*/
public void addResourceResolver(ResourceResolverSpi resolverSpi) {
if (resolverSpi == null) {
return;
}
if (perManifestResolvers == null) {
perManifestResolvers = new ArrayList