0N/A/*
0N/A * reserved comment block
0N/A * DO NOT REMOVE OR ALTER!
0N/A */
0N/A/*
0N/A * Copyright 1999-2004 The Apache Software Foundation.
0N/A *
0N/A * Licensed under the Apache License, Version 2.0 (the "License");
0N/A * you may not use this file except in compliance with the License.
0N/A * You may obtain a copy of the License at
0N/A *
0N/A * http://www.apache.org/licenses/LICENSE-2.0
0N/A *
0N/A * Unless required by applicable law or agreed to in writing, software
0N/A * distributed under the License is distributed on an "AS IS" BASIS,
0N/A * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0N/A * See the License for the specific language governing permissions and
0N/A * limitations under the License.
0N/A *
0N/A */
0N/Apackage com.sun.org.apache.xml.internal.security.signature;
0N/A
0N/A
0N/A
0N/Aimport java.io.IOException;
0N/Aimport java.util.ArrayList;
0N/Aimport java.util.HashMap;
0N/Aimport java.util.Iterator;
0N/Aimport java.util.List;
0N/Aimport java.util.Set;
0N/A
0N/Aimport javax.xml.parsers.ParserConfigurationException;
0N/A
0N/Aimport com.sun.org.apache.xml.internal.security.c14n.CanonicalizationException;
0N/Aimport com.sun.org.apache.xml.internal.security.c14n.InvalidCanonicalizerException;
0N/Aimport com.sun.org.apache.xml.internal.security.exceptions.XMLSecurityException;
0N/Aimport com.sun.org.apache.xml.internal.security.transforms.Transforms;
0N/Aimport com.sun.org.apache.xml.internal.security.utils.Constants;
0N/Aimport com.sun.org.apache.xml.internal.security.utils.I18n;
0N/Aimport com.sun.org.apache.xml.internal.security.utils.IdResolver;
0N/Aimport com.sun.org.apache.xml.internal.security.utils.SignatureElementProxy;
0N/Aimport com.sun.org.apache.xml.internal.security.utils.XMLUtils;
0N/Aimport com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolver;
0N/Aimport com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverSpi;
6385N/Aimport org.w3c.dom.Attr;
0N/Aimport org.w3c.dom.DOMException;
0N/Aimport org.w3c.dom.Document;
0N/Aimport org.w3c.dom.Element;
0N/Aimport org.w3c.dom.Node;
0N/Aimport org.xml.sax.SAXException;
0N/A
0N/A
0N/A
0N/A/**
0N/A * Handles <code>&lt;ds:Manifest&gt;</code> elements.
0N/A * <p> This element holds the <code>Reference</code> elements</p>
0N/A * @author $author: $
0N/A */
0N/Apublic class Manifest extends SignatureElementProxy {
0N/A
0N/A /** {@link java.util.logging} logging facility */
0N/A static java.util.logging.Logger log =
0N/A java.util.logging.Logger.getLogger(Manifest.class.getName());
0N/A
0N/A /** Field _references */
0N/A List _references;
0N/A Element[] _referencesEl;
0N/A
0N/A /** Field verificationResults[] */
0N/A private boolean verificationResults[] = null;
0N/A
0N/A /** Field _resolverProperties */
661N/A HashMap _resolverProperties = null;
0N/A
0N/A /** Field _perManifestResolvers */
661N/A List _perManifestResolvers = null;
0N/A
0N/A /**
0N/A * Consturts {@link Manifest}
0N/A *
0N/A * @param doc the {@link Document} in which <code>XMLsignature</code> is placed
0N/A */
0N/A public Manifest(Document doc) {
0N/A
0N/A super(doc);
0N/A
0N/A XMLUtils.addReturnToElement(this._constructionElement);
0N/A
0N/A this._references = new ArrayList();
0N/A }
0N/A
0N/A /**
0N/A * Constructor Manifest
0N/A *
0N/A * @param element
0N/A * @param BaseURI
0N/A * @throws XMLSecurityException
0N/A */
0N/A public Manifest(Element element, String BaseURI)
0N/A throws XMLSecurityException {
0N/A
0N/A super(element, BaseURI);
0N/A
6385N/A Attr attr = element.getAttributeNodeNS(null, "Id");
6385N/A if (attr != null) {
6385N/A element.setIdAttributeNode(attr, true);
6385N/A }
6385N/A
0N/A // check out Reference children
0N/A this._referencesEl = XMLUtils.selectDsNodes(this._constructionElement.getFirstChild(),
0N/A Constants._TAG_REFERENCE);
0N/A int le = this._referencesEl.length;
0N/A {
0N/A if (le == 0) {
0N/A
0N/A // At least one Reference must be present. Bad.
0N/A Object exArgs[] = { Constants._TAG_REFERENCE,
0N/A Constants._TAG_MANIFEST };
0N/A
0N/A throw new DOMException(DOMException.WRONG_DOCUMENT_ERR,
0N/A I18n.translate("xml.WrongContent", exArgs));
0N/A }
0N/A }
0N/A
0N/A // create Vector
0N/A this._references = new ArrayList(le);
0N/A
0N/A for (int i = 0; i < le; i++) {
6385N/A Element refElem = this._referencesEl[i];
6385N/A Attr refAttr = refElem.getAttributeNodeNS(null, "Id");
6385N/A if (refAttr != null) {
6385N/A refElem.setIdAttributeNode(refAttr, true);
6385N/A }
0N/A this._references.add(null);
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * This <code>addDocument</code> method is used to add a new resource to the
0N/A * signed info. A {@link com.sun.org.apache.xml.internal.security.signature.Reference} is built
0N/A * from the supplied values.
0N/A *
0N/A * @param BaseURI the URI of the resource where the XML instance was stored
0N/A * @param referenceURI <code>URI</code> attribute in <code>Reference</code> for specifing where data is
0N/A * @param transforms com.sun.org.apache.xml.internal.security.signature.Transforms object with an ordered list of transformations to be performed.
0N/A * @param digestURI The digest algorthim URI to be used.
0N/A * @param ReferenceId
0N/A * @param ReferenceType
0N/A * @throws XMLSignatureException
0N/A */
0N/A public void addDocument(
0N/A String BaseURI, String referenceURI, Transforms transforms, String digestURI, String ReferenceId, String ReferenceType)
0N/A throws XMLSignatureException {
0N/A
0N/A // the this._doc is handed implicitly by the this.getOwnerDocument()
0N/A Reference ref = new Reference(this._doc, BaseURI, referenceURI, this,
0N/A transforms, digestURI);
0N/A
0N/A if (ReferenceId != null) {
0N/A ref.setId(ReferenceId);
0N/A }
0N/A
0N/A if (ReferenceType != null) {
0N/A ref.setType(ReferenceType);
0N/A }
0N/A
0N/A // add Reference object to our cache vector
0N/A this._references.add(ref);
0N/A
0N/A // add the Element of the Reference object to the Manifest/SignedInfo
0N/A this._constructionElement.appendChild(ref.getElement());
0N/A XMLUtils.addReturnToElement(this._constructionElement);
0N/A }
0N/A
0N/A /**
0N/A * The calculation of the DigestValues in the References must be after the
0N/A * References are already added to the document and during the signing
0N/A * process. This ensures that all neccesary data is in place.
0N/A *
0N/A * @throws ReferenceNotInitializedException
0N/A * @throws XMLSignatureException
0N/A */
0N/A public void generateDigestValues()
0N/A throws XMLSignatureException, ReferenceNotInitializedException {
0N/A
0N/A for (int i = 0; i < this.getLength(); i++) {
0N/A
0N/A // update the cached Reference object, the Element content is automatically updated
0N/A Reference currentRef = (Reference) this._references.get(i);
0N/A
0N/A currentRef.generateDigestValue();
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Return the nonnegative number of added references.
0N/A *
0N/A * @return the number of references
0N/A */
0N/A public int getLength() {
0N/A return this._references.size();
0N/A }
0N/A
0N/A /**
0N/A * Return the <it>i</it><sup>th</sup> reference. Valid <code>i</code>
0N/A * values are 0 to <code>{link@ getSize}-1</code>.
0N/A *
0N/A * @param i Index of the requested {@link Reference}
0N/A * @return the <it>i</it><sup>th</sup> reference
0N/A * @throws XMLSecurityException
0N/A */
0N/A public Reference item(int i) throws XMLSecurityException {
0N/A
0N/A if (this._references.get(i) == null) {
0N/A
0N/A // not yet constructed, so _we_ have to
0N/A Reference ref = new Reference(_referencesEl[i], this._baseURI, this);
0N/A
0N/A this._references.set(i, ref);
0N/A }
0N/A
0N/A return (Reference) this._references.get(i);
0N/A
0N/A }
0N/A
0N/A /**
0N/A * Sets the <code>Id</code> attribute
0N/A *
0N/A * @param Id the <code>Id</code> attribute in <code>ds:Manifest</code>
0N/A */
0N/A public void setId(String Id) {
0N/A
661N/A if (Id != null) {
6385N/A setLocalIdAttribute(Constants._ATT_ID, Id);
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Returns the <code>Id</code> attribute
0N/A *
0N/A * @return the <code>Id</code> attribute in <code>ds:Manifest</code>
0N/A */
0N/A public String getId() {
0N/A return this._constructionElement.getAttributeNS(null, Constants._ATT_ID);
0N/A }
0N/A
0N/A /**
0N/A * Used to do a <A HREF="http://www.w3.org/TR/xmldsig-core/#def-ValidationReference">reference
0N/A * validation</A> of all enclosed references using the {@link Reference#verify} method.
0N/A *
0N/A * <p>This step loops through all {@link Reference}s and does verify the hash
0N/A * values. If one or more verifications fail, the method returns
0N/A * <code>false</code>. If <i>all</i> verifications are successful,
0N/A * it returns <code>true</code>. The results of the individual reference
0N/A * validations are available by using the {@link #getVerificationResult(int)} method
0N/A *
0N/A * @return true if all References verify, false if one or more do not verify.
0N/A * @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}
0N/A * @see com.sun.org.apache.xml.internal.security.signature.Reference#verify
0N/A * @see com.sun.org.apache.xml.internal.security.signature.SignedInfo#verify()
0N/A * @see com.sun.org.apache.xml.internal.security.signature.MissingResourceFailureException
0N/A * @throws XMLSecurityException
0N/A */
0N/A public boolean verifyReferences()
0N/A throws MissingResourceFailureException, XMLSecurityException {
0N/A return this.verifyReferences(false);
0N/A }
0N/A
0N/A /**
0N/A * Used to do a <A HREF="http://www.w3.org/TR/xmldsig-core/#def-ValidationReference">reference
0N/A * validation</A> of all enclosed references using the {@link Reference#verify} method.
0N/A *
0N/A * <p>This step loops through all {@link Reference}s and does verify the hash
0N/A * values. If one or more verifications fail, the method returns
0N/A * <code>false</code>. If <i>all</i> verifications are successful,
0N/A * it returns <code>true</code>. The results of the individual reference
0N/A * validations are available by using the {@link #getVerificationResult(int)} method
0N/A *
0N/A * @param followManifests
0N/A * @return true if all References verify, false if one or more do not verify.
0N/A * @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}
0N/A * @see com.sun.org.apache.xml.internal.security.signature.Reference#verify
0N/A * @see com.sun.org.apache.xml.internal.security.signature.SignedInfo#verify(boolean)
0N/A * @see com.sun.org.apache.xml.internal.security.signature.MissingResourceFailureException
0N/A * @throws XMLSecurityException
0N/A */
0N/A public boolean verifyReferences(boolean followManifests)
0N/A throws MissingResourceFailureException, XMLSecurityException {
0N/A if (_referencesEl==null) {
0N/A this._referencesEl =
0N/A XMLUtils.selectDsNodes(this._constructionElement.getFirstChild(),
0N/A Constants._TAG_REFERENCE);
0N/A }
661N/A if (log.isLoggable(java.util.logging.Level.FINE)) {
661N/A log.log(java.util.logging.Level.FINE, "verify " +_referencesEl.length + " References");
661N/A log.log(java.util.logging.Level.FINE, "I am " + (followManifests
0N/A ? ""
0N/A : "not") + " requested to follow nested Manifests");
0N/A }
0N/A boolean verify = true;
0N/A
0N/A if (_referencesEl.length==0) {
0N/A throw new XMLSecurityException("empty");
0N/A }
0N/A
0N/A this.verificationResults =
0N/A new boolean[_referencesEl.length];
0N/A
0N/A for (int i =
0N/A 0; i < this._referencesEl.length; i++) {
0N/A Reference currentRef =
0N/A new Reference(_referencesEl[i], this._baseURI, this);
0N/A
0N/A this._references.set(i, currentRef);
0N/A
0N/A /* if only one item does not verify, the whole verification fails */
0N/A try {
0N/A boolean currentRefVerified = currentRef.verify();
0N/A
0N/A this.setVerificationResult(i, currentRefVerified);
0N/A
0N/A if (!currentRefVerified) {
0N/A verify = false;
0N/A }
661N/A if (log.isLoggable(java.util.logging.Level.FINE))
661N/A log.log(java.util.logging.Level.FINE, "The Reference has Type " + currentRef.getType());
0N/A
0N/A // was verification successful till now and do we want to verify the Manifest?
0N/A if (verify && followManifests
0N/A && currentRef.typeIsReferenceToManifest()) {
661N/A log.log(java.util.logging.Level.FINE, "We have to follow a nested Manifest");
0N/A
0N/A try {
0N/A XMLSignatureInput signedManifestNodes =
0N/A currentRef.dereferenceURIandPerformTransforms(null);
0N/A Set nl = signedManifestNodes.getNodeSet();
0N/A Manifest referencedManifest = null;
0N/A Iterator nlIterator = nl.iterator();
0N/A
0N/A findManifest: while (nlIterator.hasNext()) {
0N/A Node n = (Node) nlIterator.next();
0N/A
0N/A if ((n.getNodeType() == Node.ELEMENT_NODE) && ((Element) n)
0N/A .getNamespaceURI()
0N/A .equals(Constants.SignatureSpecNS) && ((Element) n)
0N/A .getLocalName().equals(Constants._TAG_MANIFEST)) {
0N/A try {
0N/A referencedManifest =
0N/A new Manifest((Element) n,
0N/A signedManifestNodes.getSourceURI());
0N/A
0N/A break findManifest;
0N/A } catch (XMLSecurityException ex) {
0N/A
0N/A // Hm, seems not to be a ds:Manifest
0N/A }
0N/A }
0N/A }
0N/A
0N/A if (referencedManifest == null) {
0N/A
0N/A // The Reference stated that it points to a ds:Manifest
0N/A // but we did not find a ds:Manifest in the signed area
0N/A throw new MissingResourceFailureException("empty",
0N/A currentRef);
0N/A }
0N/A
0N/A referencedManifest._perManifestResolvers =
0N/A this._perManifestResolvers;
0N/A referencedManifest._resolverProperties =
0N/A this._resolverProperties;
0N/A
0N/A boolean referencedManifestValid =
0N/A referencedManifest.verifyReferences(followManifests);
0N/A
0N/A if (!referencedManifestValid) {
0N/A verify = false;
0N/A
0N/A log.log(java.util.logging.Level.WARNING, "The nested Manifest was invalid (bad)");
0N/A } else {
661N/A log.log(java.util.logging.Level.FINE, "The nested Manifest was valid (good)");
0N/A }
0N/A } catch (IOException ex) {
0N/A throw new ReferenceNotInitializedException("empty", ex);
0N/A } catch (ParserConfigurationException ex) {
0N/A throw new ReferenceNotInitializedException("empty", ex);
0N/A } catch (SAXException ex) {
0N/A throw new ReferenceNotInitializedException("empty", ex);
0N/A }
0N/A }
0N/A } catch (ReferenceNotInitializedException ex) {
0N/A Object exArgs[] = { currentRef.getURI() };
0N/A
0N/A throw new MissingResourceFailureException(
0N/A "signature.Verification.Reference.NoInput", exArgs, ex,
0N/A currentRef);
0N/A }
0N/A }
0N/A
0N/A return verify;
0N/A }
0N/A
0N/A /**
0N/A * Method setVerificationResult
0N/A *
0N/A * @param index
0N/A * @param verify
0N/A */
0N/A private void setVerificationResult(int index, boolean verify)
0N/A {
0N/A
0N/A if (this.verificationResults == null) {
0N/A this.verificationResults = new boolean[this.getLength()];
0N/A }
0N/A
0N/A this.verificationResults[index] = verify;
0N/A }
0N/A
0N/A /**
0N/A * After verifying a {@link Manifest} or a {@link SignedInfo} using the
0N/A * {@link Manifest#verifyReferences()} or {@link SignedInfo#verify()} methods,
0N/A * the individual results can be retrieved with this method.
0N/A *
0N/A * @param index an index of into a {@link Manifest} or a {@link SignedInfo}
0N/A * @return the results of reference validation at the specified index
0N/A * @throws XMLSecurityException
0N/A */
0N/A public boolean getVerificationResult(int index) throws XMLSecurityException {
0N/A
0N/A if ((index < 0) || (index > this.getLength() - 1)) {
0N/A Object exArgs[] = { Integer.toString(index),
0N/A Integer.toString(this.getLength()) };
0N/A Exception e =
0N/A new IndexOutOfBoundsException(I18n
0N/A .translate("signature.Verification.IndexOutOfBounds", exArgs));
0N/A
0N/A throw new XMLSecurityException("generic.EmptyMessage", e);
0N/A }
0N/A
0N/A if (this.verificationResults == null) {
0N/A try {
0N/A this.verifyReferences();
0N/A } catch (Exception ex) {
0N/A throw new XMLSecurityException("generic.EmptyMessage", ex);
0N/A }
0N/A }
0N/A
0N/A return this.verificationResults[index];
0N/A }
0N/A
0N/A /**
0N/A * Adds Resource Resolver for retrieving resources at specified <code>URI</code> attribute in <code>reference</code> element
0N/A *
0N/A * @param resolver {@link ResourceResolver} can provide the implemenatin subclass of {@link ResourceResolverSpi} for retrieving resource.
0N/A */
0N/A public void addResourceResolver(ResourceResolver resolver) {
0N/A
661N/A if (resolver == null) {
661N/A return;
0N/A }
661N/A if (_perManifestResolvers==null)
661N/A _perManifestResolvers = new ArrayList();
661N/A this._perManifestResolvers.add(resolver);
661N/A
0N/A }
0N/A
0N/A /**
0N/A * Adds Resource Resolver for retrieving resources at specified <code>URI</code> attribute in <code>reference</code> element
0N/A *
0N/A * @param resolverSpi the implemenatin subclass of {@link ResourceResolverSpi} for retrieving resource.
0N/A */
0N/A public void addResourceResolver(ResourceResolverSpi resolverSpi) {
0N/A
661N/A if (resolverSpi == null) {
661N/A return;
0N/A }
661N/A if (_perManifestResolvers==null)
661N/A _perManifestResolvers = new ArrayList();
661N/A this._perManifestResolvers.add(new ResourceResolver(resolverSpi));
661N/A
0N/A }
0N/A
0N/A /**
0N/A * Used to pass parameters like proxy servers etc to the ResourceResolver
0N/A * implementation.
0N/A *
0N/A * @param key the key
0N/A * @param value the value
0N/A */
0N/A public void setResolverProperty(String key, String value) {
661N/A if (_resolverProperties==null) {
661N/A _resolverProperties=new HashMap(10);
661N/A }
0N/A this._resolverProperties.put(key, value);
0N/A }
0N/A
0N/A /**
0N/A * Returns the value at specified key
0N/A *
0N/A * @param key the key
0N/A * @return the value
0N/A */
0N/A public String getResolverProperty(String key) {
0N/A return (String) this._resolverProperties.get(key);
0N/A }
0N/A
0N/A /**
0N/A * Method getSignedContentItem
0N/A *
0N/A * @param i
0N/A * @return The signed content of the i reference.
0N/A *
0N/A * @throws XMLSignatureException
0N/A */
0N/A public byte[] getSignedContentItem(int i) throws XMLSignatureException {
0N/A
0N/A try {
0N/A return this.getReferencedContentAfterTransformsItem(i).getBytes();
0N/A } catch (IOException ex) {
0N/A throw new XMLSignatureException("empty", ex);
0N/A } catch (CanonicalizationException ex) {
0N/A throw new XMLSignatureException("empty", ex);
0N/A } catch (InvalidCanonicalizerException ex) {
0N/A throw new XMLSignatureException("empty", ex);
0N/A } catch (XMLSecurityException ex) {
0N/A throw new XMLSignatureException("empty", ex);
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Method getReferencedContentPriorTransformsItem
0N/A *
0N/A * @param i
0N/A * @return The contents before transformation of the reference i.
0N/A * @throws XMLSecurityException
0N/A */
0N/A public XMLSignatureInput getReferencedContentBeforeTransformsItem(int i)
0N/A throws XMLSecurityException {
0N/A return this.item(i).getContentsBeforeTransformation();
0N/A }
0N/A
0N/A /**
0N/A * Method getReferencedContentAfterTransformsItem
0N/A *
0N/A * @param i
0N/A * @return The contents after transformation of the reference i.
0N/A * @throws XMLSecurityException
0N/A */
0N/A public XMLSignatureInput getReferencedContentAfterTransformsItem(int i)
0N/A throws XMLSecurityException {
0N/A return this.item(i).getContentsAfterTransformation();
0N/A }
0N/A
0N/A /**
0N/A * Method getSignedContentLength
0N/A *
0N/A * @return The nu,ber of references contained in this reference.
0N/A */
0N/A public int getSignedContentLength() {
0N/A return this.getLength();
0N/A }
0N/A
0N/A /**
0N/A * Method getBaseLocalName
0N/A *
0N/A * @inheritDoc
0N/A */
0N/A public String getBaseLocalName() {
0N/A return Constants._TAG_MANIFEST;
0N/A }
0N/A}