KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > org > apache > xml > internal > security > signature > Manifest


1 /*
2  * Copyright 1999-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */

17 package com.sun.org.apache.xml.internal.security.signature;
18
19
20
21 import java.io.IOException JavaDoc;
22 import java.util.ArrayList JavaDoc;
23 import java.util.HashMap JavaDoc;
24 import java.util.Iterator JavaDoc;
25 import java.util.List JavaDoc;
26 import java.util.Set JavaDoc;
27
28 import javax.xml.parsers.ParserConfigurationException JavaDoc;
29
30 import com.sun.org.apache.xml.internal.security.c14n.CanonicalizationException;
31 import com.sun.org.apache.xml.internal.security.c14n.InvalidCanonicalizerException;
32 import com.sun.org.apache.xml.internal.security.exceptions.XMLSecurityException;
33 import com.sun.org.apache.xml.internal.security.transforms.Transforms;
34 import com.sun.org.apache.xml.internal.security.utils.Constants;
35 import com.sun.org.apache.xml.internal.security.utils.I18n;
36 import com.sun.org.apache.xml.internal.security.utils.IdResolver;
37 import com.sun.org.apache.xml.internal.security.utils.SignatureElementProxy;
38 import com.sun.org.apache.xml.internal.security.utils.XMLUtils;
39 import com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolver;
40 import com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverSpi;
41 import org.w3c.dom.DOMException JavaDoc;
42 import org.w3c.dom.Document JavaDoc;
43 import org.w3c.dom.Element JavaDoc;
44 import org.w3c.dom.Node JavaDoc;
45 import org.xml.sax.SAXException JavaDoc;
46
47
48
49 /**
50  * Handles <code>&lt;ds:Manifest&gt;</code> elements.
51  * <p> This element holds the <code>Reference</code> elements</p>
52  * @author $author: $
53  */

54 public class Manifest extends SignatureElementProxy {
55
56   /** {@link java.util.logging} logging facility */
57   static java.util.logging.Logger JavaDoc log =
58         java.util.logging.Logger.getLogger(Manifest.class.getName());
59
60    /** Field _references */
61    List JavaDoc _references;
62    Element JavaDoc[] _referencesEl;
63
64    /** Field verificationResults[] */
65    private boolean verificationResults[] = null;
66
67    /** Field _signedContents */
68    List JavaDoc _signedContents = new ArrayList JavaDoc();
69
70    /** Field _resolverProperties */
71    HashMap JavaDoc _resolverProperties = new HashMap JavaDoc(10);
72
73    /** Field _perManifestResolvers */
74    List JavaDoc _perManifestResolvers = new ArrayList JavaDoc();
75
76    /**
77     * Consturts {@link Manifest}
78     *
79     * @param doc the {@link Document} in which <code>XMLsignature</code> is placed
80     */

81    public Manifest(Document JavaDoc doc) {
82
83       super(doc);
84
85       XMLUtils.addReturnToElement(this._constructionElement);
86
87       this._references = new ArrayList JavaDoc();
88    }
89
90    /**
91     * Constructor Manifest
92     *
93     * @param element
94     * @param BaseURI
95     * @throws XMLSecurityException
96     */

97    public Manifest(Element JavaDoc element, String JavaDoc BaseURI)
98            throws XMLSecurityException {
99
100       super(element, BaseURI);
101
102       // check out Reference children
103
this._referencesEl = XMLUtils.selectDsNodes(this._constructionElement.getFirstChild(),
104          Constants._TAG_REFERENCE);
105       int le = this._referencesEl.length;
106       {
107          if (le == 0) {
108
109             // At least one Reference must be present. Bad.
110
Object JavaDoc exArgs[] = { Constants._TAG_REFERENCE,
111                                 Constants._TAG_MANIFEST };
112
113             throw new DOMException JavaDoc(DOMException.WRONG_DOCUMENT_ERR,
114                                    I18n.translate("xml.WrongContent", exArgs));
115          }
116       }
117
118       // create Vector
119
this._references = new ArrayList JavaDoc(le);
120
121       for (int i = 0; i < le; i++) {
122          this._references.add(null);
123       }
124    }
125
126    /**
127     * This <code>addDocument</code> method is used to add a new resource to the
128     * signed info. A {@link com.sun.org.apache.xml.internal.security.signature.Reference} is built
129     * from the supplied values.
130     *
131     * @param BaseURI the URI of the resource where the XML instance was stored
132     * @param referenceURI <code>URI</code> attribute in <code>Reference</code> for specifing where data is
133     * @param transforms com.sun.org.apache.xml.internal.security.signature.Transforms object with an ordered list of transformations to be performed.
134     * @param digestURI The digest algorthim URI to be used.
135     * @param ReferenceId
136     * @param ReferenceType
137     * @throws XMLSignatureException
138     */

139    public void addDocument(
140            String JavaDoc BaseURI, String JavaDoc referenceURI, Transforms transforms, String JavaDoc digestURI, String JavaDoc ReferenceId, String JavaDoc ReferenceType)
141               throws XMLSignatureException {
142
143       if (this._state == MODE_SIGN) {
144
145          // the this._doc is handed implicitly by the this.getOwnerDocument()
146
Reference ref = new Reference(this._doc, BaseURI, referenceURI, this,
147                                        transforms, digestURI);
148
149          if (ReferenceId != null) {
150             ref.setId(ReferenceId);
151          }
152
153          if (ReferenceType != null) {
154             ref.setType(ReferenceType);
155          }
156
157          // add Reference object to our cache vector
158
this._references.add(ref);
159
160          // add the Element of the Reference object to the Manifest/SignedInfo
161
this._constructionElement.appendChild(ref.getElement());
162          XMLUtils.addReturnToElement(this._constructionElement);
163       }
164    }
165
166    /**
167     * The calculation of the DigestValues in the References must be after the
168     * References are already added to the document and during the signing
169     * process. This ensures that all neccesary data is in place.
170     *
171     * @throws ReferenceNotInitializedException
172     * @throws XMLSignatureException
173     */

174    public void generateDigestValues()
175            throws XMLSignatureException, ReferenceNotInitializedException {
176
177       if (this._state == MODE_SIGN) {
178          for (int i = 0; i < this.getLength(); i++) {
179
180             // update the cached Reference object, the Element content is automatically updated
181
Reference currentRef = (Reference) this._references.get(i);
182
183             currentRef.generateDigestValue();
184          }
185       }
186    }
187
188    /**
189     * Return the nonnegative number of added references.
190     *
191     * @return the number of references
192     */

193    public int getLength() {
194       return this._references.size();
195    }
196
197    /**
198     * Return the <it>i</it><sup>th</sup> reference. Valid <code>i</code>
199     * values are 0 to <code>{link@ getSize}-1</code>.
200     *
201     * @param i Index of the requested {@link Reference}
202     * @return the <it>i</it><sup>th</sup> reference
203     * @throws XMLSecurityException
204     */

205    public Reference item(int i) throws XMLSecurityException {
206
207       if (this._state == MODE_SIGN) {
208
209          // we already have real objects
210
return (Reference) this._references.get(i);
211       }
212          if (this._references.get(i) == null) {
213
214             // not yet constructed, so _we_ have to
215
Reference ref = new Reference(_referencesEl[i], this._baseURI, this);
216
217             this._references.set(i, ref);
218          }
219
220          return (Reference) this._references.get(i);
221       
222    }
223
224    /**
225     * Sets the <code>Id</code> attribute
226     *
227     * @param Id the <code>Id</code> attribute in <code>ds:Manifest</code>
228     */

229    public void setId(String JavaDoc Id) {
230
231       if ((this._state == MODE_SIGN) && (Id != null)) {
232          this._constructionElement.setAttributeNS(null, Constants._ATT_ID, Id);
233          IdResolver.registerElementById(this._constructionElement, Id);
234       }
235    }
236
237    /**
238     * Returns the <code>Id</code> attribute
239     *
240     * @return the <code>Id</code> attribute in <code>ds:Manifest</code>
241     */

242    public String JavaDoc getId() {
243       return this._constructionElement.getAttributeNS(null, Constants._ATT_ID);
244    }
245
246    /**
247     * Used to do a <A HREF="http://www.w3.org/TR/xmldsig-core/#def-ValidationReference">reference
248     * validation</A> of all enclosed references using the {@link Reference#verify} method.
249     *
250     * <p>This step loops through all {@link Reference}s and does verify the hash
251     * values. If one or more verifications fail, the method returns
252     * <code>false</code>. If <i>all</i> verifications are successful,
253     * it returns <code>true</code>. The results of the individual reference
254     * validations are available by using the {@link #getVerificationResult(int)} method
255     *
256     * @return true if all References verify, false if one or more do not verify.
257     * @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}
258     * @see com.sun.org.apache.xml.internal.security.signature.Reference#verify
259     * @see com.sun.org.apache.xml.internal.security.signature.SignedInfo#verify()
260     * @see com.sun.org.apache.xml.internal.security.signature.MissingResourceFailureException
261     * @throws XMLSecurityException
262     */

263    public boolean verifyReferences()
264            throws MissingResourceFailureException, XMLSecurityException {
265       return this.verifyReferences(false);
266    }
267
268    /**
269     * Used to do a <A HREF="http://www.w3.org/TR/xmldsig-core/#def-ValidationReference">reference
270     * validation</A> of all enclosed references using the {@link Reference#verify} method.
271     *
272     * <p>This step loops through all {@link Reference}s and does verify the hash
273     * values. If one or more verifications fail, the method returns
274     * <code>false</code>. If <i>all</i> verifications are successful,
275     * it returns <code>true</code>. The results of the individual reference
276     * validations are available by using the {@link #getVerificationResult(int)} method
277     *
278     * @param followManifests
279     * @return true if all References verify, false if one or more do not verify.
280     * @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}
281     * @see com.sun.org.apache.xml.internal.security.signature.Reference#verify
282     * @see com.sun.org.apache.xml.internal.security.signature.SignedInfo#verify(boolean)
283     * @see com.sun.org.apache.xml.internal.security.signature.MissingResourceFailureException
284     * @throws XMLSecurityException
285     */

286    public boolean verifyReferences(boolean followManifests)
287            throws MissingResourceFailureException, XMLSecurityException {
288       if (_referencesEl==null) {
289         this._referencesEl =
290             XMLUtils.selectDsNodes(this._constructionElement.getFirstChild(),
291                          Constants._TAG_REFERENCE);
292       }
293       if (true) {
294         if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "verify " +_referencesEl.length + " References");
295         if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "I am " + (followManifests
296                            ? ""
297                            : "not") + " requested to follow nested Manifests");
298       }
299       boolean verify = true;
300
301       if (_referencesEl.length==0) {
302          throw new XMLSecurityException("empty");
303       }
304
305       this.verificationResults =
306          new boolean[_referencesEl.length];
307
308       for (int i =
309               0; i < this._referencesEl.length; i++) {
310          Reference currentRef =
311             new Reference(_referencesEl[i], this._baseURI, this);
312
313          this._references.set(i, currentRef);
314
315          /* if only one item does not verify, the whole verification fails */
316          try {
317             boolean currentRefVerified = currentRef.verify();
318
319             this.setVerificationResult(i, currentRefVerified);
320
321             if (!currentRefVerified) {
322                verify = false;
323             }
324             if (true)
325                 if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "The Reference has Type " + currentRef.getType());
326
327             // was verification successful till now and do we want to verify the Manifest?
328
if (verify && followManifests
329                     && currentRef.typeIsReferenceToManifest()) {
330                if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "We have to follow a nested Manifest");
331
332                 try {
333                   XMLSignatureInput signedManifestNodes =
334                     currentRef.dereferenceURIandPerformTransforms(null);
335                   Set JavaDoc nl = signedManifestNodes.getNodeSet();
336                   Manifest referencedManifest = null;
337                   Iterator JavaDoc nlIterator = nl.iterator();
338
339                   findManifest: while (nlIterator.hasNext()) {
340                      Node JavaDoc n = (Node JavaDoc) nlIterator.next();
341
342                      if ((n.getNodeType() == Node.ELEMENT_NODE) && ((Element JavaDoc) n)
343                              .getNamespaceURI()
344                              .equals(Constants.SignatureSpecNS) && ((Element JavaDoc) n)
345                              .getLocalName().equals(Constants._TAG_MANIFEST)) {
346                         try {
347                            referencedManifest =
348                               new Manifest((Element JavaDoc) n,
349                                            signedManifestNodes.getSourceURI());
350
351                            break findManifest;
352                         } catch (XMLSecurityException ex) {
353
354                            // Hm, seems not to be a ds:Manifest
355
}
356                      }
357                   }
358
359                   if (referencedManifest == null) {
360
361                      // The Reference stated that it points to a ds:Manifest
362
// but we did not find a ds:Manifest in the signed area
363
throw new MissingResourceFailureException("empty",
364                                                                currentRef);
365                   }
366
367                   referencedManifest._perManifestResolvers =
368                      this._perManifestResolvers;
369                   referencedManifest._resolverProperties =
370                      this._resolverProperties;
371
372                   boolean referencedManifestValid =
373                      referencedManifest.verifyReferences(followManifests);
374
375                   if (!referencedManifestValid) {
376                      verify = false;
377
378                      log.log(java.util.logging.Level.WARNING, "The nested Manifest was invalid (bad)");
379                   } else {
380                      if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "The nested Manifest was valid (good)");
381                   }
382                } catch (IOException JavaDoc ex) {
383                   throw new ReferenceNotInitializedException("empty", ex);
384                } catch (ParserConfigurationException JavaDoc ex) {
385                   throw new ReferenceNotInitializedException("empty", ex);
386                } catch (SAXException JavaDoc ex) {
387                   throw new ReferenceNotInitializedException("empty", ex);
388                }
389             }
390          } catch (ReferenceNotInitializedException ex) {
391             Object JavaDoc exArgs[] = { currentRef.getURI() };
392
393             throw new MissingResourceFailureException(
394                "signature.Verification.Reference.NoInput", exArgs, ex,
395                currentRef);
396          }
397       }
398
399       return verify;
400    }
401
402    /**
403     * Method setVerificationResult
404     *
405     * @param index
406     * @param verify
407     */

408    private void setVerificationResult(int index, boolean verify)
409    {
410
411       if (this.verificationResults == null) {
412          this.verificationResults = new boolean[this.getLength()];
413       }
414
415       this.verificationResults[index] = verify;
416    }
417
418    /**
419     * After verifying a {@link Manifest} or a {@link SignedInfo} using the
420     * {@link Manifest#verifyReferences()} or {@link SignedInfo#verify()} methods,
421     * the individual results can be retrieved with this method.
422     *
423     * @param index an index of into a {@link Manifest} or a {@link SignedInfo}
424     * @return the results of reference validation at the specified index
425     * @throws XMLSecurityException
426     */

427    public boolean getVerificationResult(int index) throws XMLSecurityException {
428
429       if ((index < 0) || (index > this.getLength() - 1)) {
430          Object JavaDoc exArgs[] = { Integer.toString(index),
431                              Integer.toString(this.getLength()) };
432          Exception JavaDoc e =
433             new IndexOutOfBoundsException JavaDoc(I18n
434                .translate("signature.Verification.IndexOutOfBounds", exArgs));
435
436          throw new XMLSecurityException("generic.EmptyMessage", e);
437       }
438
439       if (this.verificationResults == null) {
440          try {
441             this.verifyReferences();
442          } catch (Exception JavaDoc ex) {
443             throw new XMLSecurityException("generic.EmptyMessage", ex);
444          }
445       }
446
447       return this.verificationResults[index];
448    }
449
450    /**
451     * Adds Resource Resolver for retrieving resources at specified <code>URI</code> attribute in <code>reference</code> element
452     *
453     * @param resolver {@link ResourceResolver} can provide the implemenatin subclass of {@link ResourceResolverSpi} for retrieving resource.
454     */

455    public void addResourceResolver(ResourceResolver resolver) {
456
457       if (resolver != null) {
458          this._perManifestResolvers.add(resolver);
459       }
460    }
461
462    /**
463     * Adds Resource Resolver for retrieving resources at specified <code>URI</code> attribute in <code>reference</code> element
464     *
465     * @param resolverSpi the implemenatin subclass of {@link ResourceResolverSpi} for retrieving resource.
466     */

467    public void addResourceResolver(ResourceResolverSpi resolverSpi) {
468
469       if (resolverSpi != null) {
470          this._perManifestResolvers.add(new ResourceResolver(resolverSpi));
471       }
472    }
473
474    /**
475     * Used to pass parameters like proxy servers etc to the ResourceResolver
476     * implementation.
477     *
478     * @param key the key
479     * @param value the value
480     */

481    public void setResolverProperty(String JavaDoc key, String JavaDoc value) {
482       this._resolverProperties.put(key, value);
483    }
484
485    /**
486     * Returns the value at specified key
487     *
488     * @param key the key
489     * @return the value
490     */

491    public String JavaDoc getResolverProperty(String JavaDoc key) {
492       return (String JavaDoc) this._resolverProperties.get(key);
493    }
494
495    /**
496     * Method getSignedContentItem
497     *
498     * @param i
499     * @return The signed content of the i reference.
500     *
501     * @throws XMLSignatureException
502     */

503    public byte[] getSignedContentItem(int i) throws XMLSignatureException {
504
505       try {
506          return this.getReferencedContentAfterTransformsItem(i).getBytes();
507       } catch (IOException JavaDoc ex) {
508          throw new XMLSignatureException("empty", ex);
509       } catch (CanonicalizationException ex) {
510          throw new XMLSignatureException("empty", ex);
511       } catch (InvalidCanonicalizerException ex) {
512          throw new XMLSignatureException("empty", ex);
513       } catch (XMLSecurityException ex) {
514          throw new XMLSignatureException("empty", ex);
515       }
516    }
517
518    /**
519     * Method getReferencedContentPriorTransformsItem
520     *
521     * @param i
522     * @return The contents before transformation of the reference i.
523     * @throws XMLSecurityException
524     */

525    public XMLSignatureInput getReferencedContentBeforeTransformsItem(int i)
526            throws XMLSecurityException {
527       return this.item(i).getContentsBeforeTransformation();
528    }
529
530    /**
531     * Method getReferencedContentAfterTransformsItem
532     *
533     * @param i
534     * @return The contents after transformation of the reference i.
535     * @throws XMLSecurityException
536     */

537    public XMLSignatureInput getReferencedContentAfterTransformsItem(int i)
538            throws XMLSecurityException {
539       return this.item(i).getContentsAfterTransformation();
540    }
541
542    /**
543     * Method getSignedContentLength
544     *
545     * @return The nu,ber of references contained in this reference.
546     */

547    public int getSignedContentLength() {
548       return this.getLength();
549    }
550
551    /**
552     * Method getBaseLocalName
553     *
554     * @inheritDoc
555     */

556    public String JavaDoc getBaseLocalName() {
557       return Constants._TAG_MANIFEST;
558    }
559 }
560
Popular Tags