1 /* 2 * reserved comment block 3 * DO NOT REMOVE OR ALTER! 4 */ 5 /* 6 * Copyright 1999-2004 The Apache Software Foundation. 7 * 8 * Licensed under the Apache License, Version 2.0 (the "License"); 9 * you may not use this file except in compliance with the License. 10 * You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 * 20 */ 21 package com.sun.org.apache.xml.internal.security.signature; 22 23 24 25 import java.io.IOException; 26 import java.util.ArrayList; 27 import java.util.HashMap; 28 import java.util.Iterator; 29 import java.util.List; 30 import java.util.Set; 31 import java.util.Map; 32 33 import javax.xml.parsers.ParserConfigurationException; 34 35 import com.sun.org.apache.xml.internal.security.c14n.CanonicalizationException; 36 import com.sun.org.apache.xml.internal.security.c14n.InvalidCanonicalizerException; 37 import com.sun.org.apache.xml.internal.security.exceptions.XMLSecurityException; 38 import com.sun.org.apache.xml.internal.security.transforms.Transforms; 39 import com.sun.org.apache.xml.internal.security.utils.Constants; 40 import com.sun.org.apache.xml.internal.security.utils.I18n; 41 import com.sun.org.apache.xml.internal.security.utils.IdResolver; 42 import com.sun.org.apache.xml.internal.security.utils.SignatureElementProxy; 43 import com.sun.org.apache.xml.internal.security.utils.XMLUtils; 44 import com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolver; 45 import com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverSpi; 46 import org.w3c.dom.Attr; 47 import org.w3c.dom.DOMException; 48 import org.w3c.dom.Document; 49 import org.w3c.dom.Element; 50 import org.w3c.dom.Node; 51 import org.xml.sax.SAXException; 52 53 54 55 /** 56 * Handles <code><ds:Manifest></code> elements. 57 * <p> This element holds the <code>Reference</code> elements</p> 58 * @author $author: $ 59 */ 60 public class Manifest extends SignatureElementProxy { 61 62 /** {@link java.util.logging} logging facility */ 63 static java.util.logging.Logger log = 64 java.util.logging.Logger.getLogger(Manifest.class.getName()); 65 66 /** Field _references */ 67 List<Reference> _references; 68 Element[] _referencesEl; 69 70 /** Field verificationResults[] */ 71 private boolean verificationResults[] = null; 72 73 /** Field _resolverProperties */ 74 Map<String,String> _resolverProperties = null; 75 76 /** Field _perManifestResolvers */ 77 List<ResourceResolver> _perManifestResolvers = null; 78 79 /** 80 * Consturts {@link Manifest} 81 * 82 * @param doc the {@link Document} in which <code>XMLsignature</code> is placed 83 */ 84 public Manifest(Document doc) { 85 86 super(doc); 87 88 XMLUtils.addReturnToElement(this._constructionElement); 89 90 this._references = new ArrayList<Reference>(); 91 } 92 93 /** 94 * Constructor Manifest 95 * 96 * @param element 97 * @param BaseURI 98 * @throws XMLSecurityException 99 */ 100 public Manifest(Element element, String BaseURI) 101 throws XMLSecurityException { 102 103 super(element, BaseURI); 104 105 Attr attr = element.getAttributeNodeNS(null, "Id"); 106 if (attr != null) { 107 element.setIdAttributeNode(attr, true); 108 } 109 110 // check out Reference children 111 this._referencesEl = XMLUtils.selectDsNodes(this._constructionElement.getFirstChild(), 112 Constants._TAG_REFERENCE); 113 int le = this._referencesEl.length; 114 { 115 if (le == 0) { 116 117 // At least one Reference must be present. Bad. 118 Object exArgs[] = { Constants._TAG_REFERENCE, 119 Constants._TAG_MANIFEST }; 120 121 throw new DOMException(DOMException.WRONG_DOCUMENT_ERR, 122 I18n.translate("xml.WrongContent", exArgs)); 123 } 124 } 125 126 // create Vector 127 this._references = new ArrayList<Reference>(le); 128 129 for (int i = 0; i < le; i++) { 130 Element refElem = this._referencesEl[i]; 131 Attr refAttr = refElem.getAttributeNodeNS(null, "Id"); 132 if (refAttr != null) { 133 refElem.setIdAttributeNode(refAttr, true); 134 } 135 this._references.add(null); 136 } 137 } 138 139 /** 140 * This <code>addDocument</code> method is used to add a new resource to the 141 * signed info. A {@link com.sun.org.apache.xml.internal.security.signature.Reference} is built 142 * from the supplied values. 143 * 144 * @param BaseURI the URI of the resource where the XML instance was stored 145 * @param referenceURI <code>URI</code> attribute in <code>Reference</code> for specifing where data is 146 * @param transforms com.sun.org.apache.xml.internal.security.signature.Transforms object with an ordered list of transformations to be performed. 147 * @param digestURI The digest algorthim URI to be used. 148 * @param ReferenceId 149 * @param ReferenceType 150 * @throws XMLSignatureException 151 */ 152 public void addDocument( 153 String BaseURI, String referenceURI, Transforms transforms, String digestURI, String ReferenceId, String ReferenceType) 154 throws XMLSignatureException { 155 156 // the this._doc is handed implicitly by the this.getOwnerDocument() 157 Reference ref = new Reference(this._doc, BaseURI, referenceURI, this, 158 transforms, digestURI); 159 160 if (ReferenceId != null) { 161 ref.setId(ReferenceId); 162 } 163 164 if (ReferenceType != null) { 165 ref.setType(ReferenceType); 166 } 167 168 // add Reference object to our cache vector 169 this._references.add(ref); 170 171 // add the Element of the Reference object to the Manifest/SignedInfo 172 this._constructionElement.appendChild(ref.getElement()); 173 XMLUtils.addReturnToElement(this._constructionElement); 174 } 175 176 /** 177 * The calculation of the DigestValues in the References must be after the 178 * References are already added to the document and during the signing 179 * process. This ensures that all neccesary data is in place. 180 * 181 * @throws ReferenceNotInitializedException 182 * @throws XMLSignatureException 183 */ 184 public void generateDigestValues() 185 throws XMLSignatureException, ReferenceNotInitializedException { 186 187 for (int i = 0; i < this.getLength(); i++) { 188 189 // update the cached Reference object, the Element content is automatically updated 190 Reference currentRef = this._references.get(i); 191 192 currentRef.generateDigestValue(); 193 } 194 } 195 196 /** 197 * Return the nonnegative number of added references. 198 * 199 * @return the number of references 200 */ 201 public int getLength() { 202 return this._references.size(); 203 } 204 205 /** 206 * Return the <it>i</it><sup>th</sup> reference. Valid <code>i</code> 207 * values are 0 to <code>{link@ getSize}-1</code>. 208 * 209 * @param i Index of the requested {@link Reference} 210 * @return the <it>i</it><sup>th</sup> reference 211 * @throws XMLSecurityException 212 */ 213 public Reference item(int i) throws XMLSecurityException { 214 215 if (this._references.get(i) == null) { 216 217 // not yet constructed, so _we_ have to 218 Reference ref = new Reference(_referencesEl[i], this._baseURI, this); 219 220 this._references.set(i, ref); 221 } 222 223 return this._references.get(i); 224 225 } 226 227 /** 228 * Sets the <code>Id</code> attribute 229 * 230 * @param Id the <code>Id</code> attribute in <code>ds:Manifest</code> 231 */ 232 public void setId(String Id) { 233 234 if (Id != null) { 235 setLocalIdAttribute(Constants._ATT_ID, Id); 236 } 237 } 238 239 /** 240 * Returns the <code>Id</code> attribute 241 * 242 * @return the <code>Id</code> attribute in <code>ds:Manifest</code> 243 */ 244 public String getId() { 245 return this._constructionElement.getAttributeNS(null, Constants._ATT_ID); 246 } 247 248 /** 249 * Used to do a <A HREF="http://www.w3.org/TR/xmldsig-core/#def-ValidationReference">reference 250 * validation</A> of all enclosed references using the {@link Reference#verify} method. 251 * 252 * <p>This step loops through all {@link Reference}s and does verify the hash 253 * values. If one or more verifications fail, the method returns 254 * <code>false</code>. If <i>all</i> verifications are successful, 255 * it returns <code>true</code>. The results of the individual reference 256 * validations are available by using the {@link #getVerificationResult(int)} method 257 * 258 * @return true if all References verify, false if one or more do not verify. 259 * @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} 260 * @see com.sun.org.apache.xml.internal.security.signature.Reference#verify 261 * @see com.sun.org.apache.xml.internal.security.signature.SignedInfo#verify() 262 * @see com.sun.org.apache.xml.internal.security.signature.MissingResourceFailureException 263 * @throws XMLSecurityException 264 */ 265 public boolean verifyReferences() 266 throws MissingResourceFailureException, XMLSecurityException { 267 return this.verifyReferences(false); 268 } 269 270 /** 271 * Used to do a <A HREF="http://www.w3.org/TR/xmldsig-core/#def-ValidationReference">reference 272 * validation</A> of all enclosed references using the {@link Reference#verify} method. 273 * 274 * <p>This step loops through all {@link Reference}s and does verify the hash 275 * values. If one or more verifications fail, the method returns 276 * <code>false</code>. If <i>all</i> verifications are successful, 277 * it returns <code>true</code>. The results of the individual reference 278 * validations are available by using the {@link #getVerificationResult(int)} method 279 * 280 * @param followManifests 281 * @return true if all References verify, false if one or more do not verify. 282 * @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} 283 * @see com.sun.org.apache.xml.internal.security.signature.Reference#verify 284 * @see com.sun.org.apache.xml.internal.security.signature.SignedInfo#verify(boolean) 285 * @see com.sun.org.apache.xml.internal.security.signature.MissingResourceFailureException 286 * @throws XMLSecurityException 287 */ 288 public boolean verifyReferences(boolean followManifests) 289 throws MissingResourceFailureException, XMLSecurityException { 290 if (_referencesEl==null) { 291 this._referencesEl = 292 XMLUtils.selectDsNodes(this._constructionElement.getFirstChild(), 293 Constants._TAG_REFERENCE); 294 } 295 if (log.isLoggable(java.util.logging.Level.FINE)) { 296 log.log(java.util.logging.Level.FINE, "verify " +_referencesEl.length + " References"); 297 log.log(java.util.logging.Level.FINE, "I am " + (followManifests 298 ? "" 299 : "not") + " requested to follow nested Manifests"); 300 } 301 boolean verify = true; 302 303 if (_referencesEl.length==0) { 304 throw new XMLSecurityException("empty"); 305 } 306 307 this.verificationResults = 308 new boolean[_referencesEl.length]; 309 310 for (int i = 311 0; i < this._referencesEl.length; i++) { 312 Reference currentRef = 313 new Reference(_referencesEl[i], this._baseURI, this); 314 315 this._references.set(i, currentRef); 316 317 /* if only one item does not verify, the whole verification fails */ 318 try { 319 boolean currentRefVerified = currentRef.verify(); 320 321 this.setVerificationResult(i, currentRefVerified); 322 323 if (!currentRefVerified) { 324 verify = false; 325 } 326 if (log.isLoggable(java.util.logging.Level.FINE)) 327 log.log(java.util.logging.Level.FINE, "The Reference has Type " + currentRef.getType()); 328 329 // was verification successful till now and do we want to verify the Manifest? 330 if (verify && followManifests 331 && currentRef.typeIsReferenceToManifest()) { 332 log.log(java.util.logging.Level.FINE, "We have to follow a nested Manifest"); 333 334 try { 335 XMLSignatureInput signedManifestNodes = 336 currentRef.dereferenceURIandPerformTransforms(null); 337 Set<Node> nl = signedManifestNodes.getNodeSet(); 338 Manifest referencedManifest = null; 339 Iterator<Node> nlIterator = nl.iterator(); 340 341 findManifest: while (nlIterator.hasNext()) { 342 Node n = nlIterator.next(); 343 344 if ((n.getNodeType() == Node.ELEMENT_NODE) && ((Element) n) 345 .getNamespaceURI() 346 .equals(Constants.SignatureSpecNS) && ((Element) n) 347 .getLocalName().equals(Constants._TAG_MANIFEST)) { 348 try { 349 referencedManifest = 350 new Manifest((Element) n, 351 signedManifestNodes.getSourceURI()); 352 353 break findManifest; 354 } catch (XMLSecurityException ex) { 355 356 // Hm, seems not to be a ds:Manifest 357 } 358 } 359 } 360 361 if (referencedManifest == null) { 362 363 // The Reference stated that it points to a ds:Manifest 364 // but we did not find a ds:Manifest in the signed area 365 throw new MissingResourceFailureException("empty", 366 currentRef); 367 } 368 369 referencedManifest._perManifestResolvers = 370 this._perManifestResolvers; 371 referencedManifest._resolverProperties = 372 this._resolverProperties; 373 374 boolean referencedManifestValid = 375 referencedManifest.verifyReferences(followManifests); 376 377 if (!referencedManifestValid) { 378 verify = false; 379 380 log.log(java.util.logging.Level.WARNING, "The nested Manifest was invalid (bad)"); 381 } else { 382 log.log(java.util.logging.Level.FINE, "The nested Manifest was valid (good)"); 383 } 384 } catch (IOException ex) { 385 throw new ReferenceNotInitializedException("empty", ex); 386 } catch (ParserConfigurationException ex) { 387 throw new ReferenceNotInitializedException("empty", ex); 388 } catch (SAXException ex) { 389 throw new ReferenceNotInitializedException("empty", ex); 390 } 391 } 392 } catch (ReferenceNotInitializedException ex) { 393 Object exArgs[] = { currentRef.getURI() }; 394 395 throw new MissingResourceFailureException( 396 "signature.Verification.Reference.NoInput", exArgs, ex, 397 currentRef); 398 } 399 } 400 401 return verify; 402 } 403 404 /** 405 * Method setVerificationResult 406 * 407 * @param index 408 * @param verify 409 */ 410 private void setVerificationResult(int index, boolean verify) 411 { 412 413 if (this.verificationResults == null) { 414 this.verificationResults = new boolean[this.getLength()]; 415 } 416 417 this.verificationResults[index] = verify; 418 } 419 420 /** 421 * After verifying a {@link Manifest} or a {@link SignedInfo} using the 422 * {@link Manifest#verifyReferences()} or {@link SignedInfo#verify()} methods, 423 * the individual results can be retrieved with this method. 424 * 425 * @param index an index of into a {@link Manifest} or a {@link SignedInfo} 426 * @return the results of reference validation at the specified index 427 * @throws XMLSecurityException 428 */ 429 public boolean getVerificationResult(int index) throws XMLSecurityException { 430 431 if ((index < 0) || (index > this.getLength() - 1)) { 432 Object exArgs[] = { Integer.toString(index), 433 Integer.toString(this.getLength()) }; 434 Exception e = 435 new IndexOutOfBoundsException(I18n 436 .translate("signature.Verification.IndexOutOfBounds", exArgs)); 437 438 throw new XMLSecurityException("generic.EmptyMessage", e); 439 } 440 441 if (this.verificationResults == null) { 442 try { 443 this.verifyReferences(); 444 } catch (Exception ex) { 445 throw new XMLSecurityException("generic.EmptyMessage", ex); 446 } 447 } 448 449 return this.verificationResults[index]; 450 } 451 452 /** 453 * Adds Resource Resolver for retrieving resources at specified <code>URI</code> attribute in <code>reference</code> element 454 * 455 * @param resolver {@link ResourceResolver} can provide the implemenatin subclass of {@link ResourceResolverSpi} for retrieving resource. 456 */ 457 public void addResourceResolver(ResourceResolver resolver) { 458 459 if (resolver == null) { 460 return; 461 } 462 if (_perManifestResolvers==null) 463 _perManifestResolvers = new ArrayList<ResourceResolver>(); 464 this._perManifestResolvers.add(resolver); 465 466 } 467 468 /** 469 * Adds Resource Resolver for retrieving resources at specified <code>URI</code> attribute in <code>reference</code> element 470 * 471 * @param resolverSpi the implemenatin subclass of {@link ResourceResolverSpi} for retrieving resource. 472 */ 473 public void addResourceResolver(ResourceResolverSpi resolverSpi) { 474 475 if (resolverSpi == null) { 476 return; 477 } 478 if (_perManifestResolvers==null) 479 _perManifestResolvers = new ArrayList<ResourceResolver>(); 480 this._perManifestResolvers.add(new ResourceResolver(resolverSpi)); 481 482 } 483 484 /** 485 * Used to pass parameters like proxy servers etc to the ResourceResolver 486 * implementation. 487 * 488 * @param key the key 489 * @param value the value 490 */ 491 public void setResolverProperty(String key, String value) { 492 if (_resolverProperties==null) { 493 _resolverProperties=new HashMap<String, String>(10); 494 } 495 this._resolverProperties.put(key, value); 496 } 497 498 /** 499 * Returns the value at specified key 500 * 501 * @param key the key 502 * @return the value 503 */ 504 public String getResolverProperty(String key) { 505 return this._resolverProperties.get(key); 506 } 507 508 /** 509 * Method getSignedContentItem 510 * 511 * @param i 512 * @return The signed content of the i reference. 513 * 514 * @throws XMLSignatureException 515 */ 516 public byte[] getSignedContentItem(int i) throws XMLSignatureException { 517 518 try { 519 return this.getReferencedContentAfterTransformsItem(i).getBytes(); 520 } catch (IOException ex) { 521 throw new XMLSignatureException("empty", ex); 522 } catch (CanonicalizationException ex) { 523 throw new XMLSignatureException("empty", ex); 524 } catch (InvalidCanonicalizerException ex) { 525 throw new XMLSignatureException("empty", ex); 526 } catch (XMLSecurityException ex) { 527 throw new XMLSignatureException("empty", ex); 528 } 529 } 530 531 /** 532 * Method getReferencedContentPriorTransformsItem 533 * 534 * @param i 535 * @return The contents before transformation of the reference i. 536 * @throws XMLSecurityException 537 */ 538 public XMLSignatureInput getReferencedContentBeforeTransformsItem(int i) 539 throws XMLSecurityException { 540 return this.item(i).getContentsBeforeTransformation(); 541 } 542 543 /** 544 * Method getReferencedContentAfterTransformsItem 545 * 546 * @param i 547 * @return The contents after transformation of the reference i. 548 * @throws XMLSecurityException 549 */ 550 public XMLSignatureInput getReferencedContentAfterTransformsItem(int i) 551 throws XMLSecurityException { 552 return this.item(i).getContentsAfterTransformation(); 553 } 554 555 /** 556 * Method getSignedContentLength 557 * 558 * @return The nu,ber of references contained in this reference. 559 */ 560 public int getSignedContentLength() { 561 return this.getLength(); 562 } 563 564 /** 565 * Method getBaseLocalName 566 * 567 * @inheritDoc 568 */ 569 public String getBaseLocalName() { 570 return Constants._TAG_MANIFEST; 571 } 572 } | 1 /* 2 * reserved comment block 3 * DO NOT REMOVE OR ALTER! 4 */ 5 /** 6 * Licensed to the Apache Software Foundation (ASF) under one 7 * or more contributor license agreements. See the NOTICE file 8 * distributed with this work for additional information 9 * regarding copyright ownership. The ASF licenses this file 10 * to you under the Apache License, Version 2.0 (the 11 * "License"); you may not use this file except in compliance 12 * with the License. You may obtain a copy of the License at 13 * 14 * http://www.apache.org/licenses/LICENSE-2.0 15 * 16 * Unless required by applicable law or agreed to in writing, 17 * software distributed under the License is distributed on an 18 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 19 * KIND, either express or implied. See the License for the 20 * specific language governing permissions and limitations 21 * under the License. 22 */ 23 package com.sun.org.apache.xml.internal.security.signature; 24 25 import java.io.IOException; 26 import java.util.ArrayList; 27 import java.util.HashMap; 28 import java.util.Iterator; 29 import java.util.List; 30 import java.util.Map; 31 import java.util.Set; 32 33 import javax.xml.parsers.ParserConfigurationException; 34 35 import com.sun.org.apache.xml.internal.security.c14n.CanonicalizationException; 36 import com.sun.org.apache.xml.internal.security.c14n.InvalidCanonicalizerException; 37 import com.sun.org.apache.xml.internal.security.exceptions.XMLSecurityException; 38 import com.sun.org.apache.xml.internal.security.transforms.Transforms; 39 import com.sun.org.apache.xml.internal.security.utils.Constants; 40 import com.sun.org.apache.xml.internal.security.utils.I18n; 41 import com.sun.org.apache.xml.internal.security.utils.SignatureElementProxy; 42 import com.sun.org.apache.xml.internal.security.utils.XMLUtils; 43 import com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolver; 44 import com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverSpi; 45 import org.w3c.dom.Attr; 46 import org.w3c.dom.DOMException; 47 import org.w3c.dom.Document; 48 import org.w3c.dom.Element; 49 import org.w3c.dom.Node; 50 import org.xml.sax.SAXException; 51 52 /** 53 * Handles <code><ds:Manifest></code> elements. 54 * <p> This element holds the <code>Reference</code> elements</p> 55 */ 56 public class Manifest extends SignatureElementProxy { 57 58 /** 59 * The maximum number of references per Manifest, if secure validation is enabled. 60 */ 61 public static final int MAXIMUM_REFERENCE_COUNT = 30; 62 63 /** {@link org.apache.commons.logging} logging facility */ 64 private static java.util.logging.Logger log = 65 java.util.logging.Logger.getLogger(Manifest.class.getName()); 66 67 /** Field references */ 68 private List<Reference> references; 69 private Element[] referencesEl; 70 71 /** Field verificationResults[] */ 72 private boolean verificationResults[] = null; 73 74 /** Field resolverProperties */ 75 private Map<String, String> resolverProperties = null; 76 77 /** Field perManifestResolvers */ 78 private List<ResourceResolver> perManifestResolvers = null; 79 80 private boolean secureValidation; 81 82 /** 83 * Constructs {@link Manifest} 84 * 85 * @param doc the {@link Document} in which <code>XMLsignature</code> is placed 86 */ 87 public Manifest(Document doc) { 88 super(doc); 89 90 XMLUtils.addReturnToElement(this.constructionElement); 91 92 this.references = new ArrayList<Reference>(); 93 } 94 95 /** 96 * Constructor Manifest 97 * 98 * @param element 99 * @param baseURI 100 * @throws XMLSecurityException 101 */ 102 public Manifest(Element element, String baseURI) throws XMLSecurityException { 103 this(element, baseURI, false); 104 105 } 106 /** 107 * Constructor Manifest 108 * 109 * @param element 110 * @param baseURI 111 * @param secureValidation 112 * @throws XMLSecurityException 113 */ 114 public Manifest( 115 Element element, String baseURI, boolean secureValidation 116 ) throws XMLSecurityException { 117 super(element, baseURI); 118 119 Attr attr = element.getAttributeNodeNS(null, "Id"); 120 if (attr != null) { 121 element.setIdAttributeNode(attr, true); 122 } 123 this.secureValidation = secureValidation; 124 125 // check out Reference children 126 this.referencesEl = 127 XMLUtils.selectDsNodes( 128 this.constructionElement.getFirstChild(), Constants._TAG_REFERENCE 129 ); 130 int le = this.referencesEl.length; 131 if (le == 0) { 132 // At least one Reference must be present. Bad. 133 Object exArgs[] = { Constants._TAG_REFERENCE, Constants._TAG_MANIFEST }; 134 135 throw new DOMException(DOMException.WRONG_DOCUMENT_ERR, 136 I18n.translate("xml.WrongContent", exArgs)); 137 } 138 139 if (secureValidation && le > MAXIMUM_REFERENCE_COUNT) { 140 Object exArgs[] = { le, MAXIMUM_REFERENCE_COUNT }; 141 142 throw new XMLSecurityException("signature.tooManyReferences", exArgs); 143 } 144 145 // create List 146 this.references = new ArrayList<Reference>(le); 147 148 for (int i = 0; i < le; i++) { 149 Element refElem = referencesEl[i]; 150 Attr refAttr = refElem.getAttributeNodeNS(null, "Id"); 151 if (refAttr != null) { 152 refElem.setIdAttributeNode(refAttr, true); 153 } 154 this.references.add(null); 155 } 156 } 157 158 /** 159 * This <code>addDocument</code> method is used to add a new resource to the 160 * signed info. A {@link com.sun.org.apache.xml.internal.security.signature.Reference} is built 161 * from the supplied values. 162 * 163 * @param baseURI the URI of the resource where the XML instance was stored 164 * @param referenceURI <code>URI</code> attribute in <code>Reference</code> for specifying 165 * where data is 166 * @param transforms com.sun.org.apache.xml.internal.security.signature.Transforms object with an ordered 167 * list of transformations to be performed. 168 * @param digestURI The digest algorithm URI to be used. 169 * @param referenceId 170 * @param referenceType 171 * @throws XMLSignatureException 172 */ 173 public void addDocument( 174 String baseURI, String referenceURI, Transforms transforms, 175 String digestURI, String referenceId, String referenceType 176 ) throws XMLSignatureException { 177 // the this.doc is handed implicitly by the this.getOwnerDocument() 178 Reference ref = 179 new Reference(this.doc, baseURI, referenceURI, this, transforms, digestURI); 180 181 if (referenceId != null) { 182 ref.setId(referenceId); 183 } 184 185 if (referenceType != null) { 186 ref.setType(referenceType); 187 } 188 189 // add Reference object to our cache vector 190 this.references.add(ref); 191 192 // add the Element of the Reference object to the Manifest/SignedInfo 193 this.constructionElement.appendChild(ref.getElement()); 194 XMLUtils.addReturnToElement(this.constructionElement); 195 } 196 197 /** 198 * The calculation of the DigestValues in the References must be after the 199 * References are already added to the document and during the signing 200 * process. This ensures that all necessary data is in place. 201 * 202 * @throws ReferenceNotInitializedException 203 * @throws XMLSignatureException 204 */ 205 public void generateDigestValues() 206 throws XMLSignatureException, ReferenceNotInitializedException { 207 for (int i = 0; i < this.getLength(); i++) { 208 // update the cached Reference object, the Element content is automatically updated 209 Reference currentRef = this.references.get(i); 210 currentRef.generateDigestValue(); 211 } 212 } 213 214 /** 215 * Return the nonnegative number of added references. 216 * 217 * @return the number of references 218 */ 219 public int getLength() { 220 return this.references.size(); 221 } 222 223 /** 224 * Return the <it>i</it><sup>th</sup> reference. Valid <code>i</code> 225 * values are 0 to <code>{link@ getSize}-1</code>. 226 * 227 * @param i Index of the requested {@link Reference} 228 * @return the <it>i</it><sup>th</sup> reference 229 * @throws XMLSecurityException 230 */ 231 public Reference item(int i) throws XMLSecurityException { 232 if (this.references.get(i) == null) { 233 // not yet constructed, so _we_ have to 234 Reference ref = 235 new Reference(referencesEl[i], this.baseURI, this, secureValidation); 236 237 this.references.set(i, ref); 238 } 239 240 return this.references.get(i); 241 } 242 243 /** 244 * Sets the <code>Id</code> attribute 245 * 246 * @param Id the <code>Id</code> attribute in <code>ds:Manifest</code> 247 */ 248 public void setId(String Id) { 249 if (Id != null) { 250 this.constructionElement.setAttributeNS(null, Constants._ATT_ID, Id); 251 this.constructionElement.setIdAttributeNS(null, Constants._ATT_ID, true); 252 } 253 } 254 255 /** 256 * Returns the <code>Id</code> attribute 257 * 258 * @return the <code>Id</code> attribute in <code>ds:Manifest</code> 259 */ 260 public String getId() { 261 return this.constructionElement.getAttributeNS(null, Constants._ATT_ID); 262 } 263 264 /** 265 * Used to do a <A HREF="http://www.w3.org/TR/xmldsig-core/#def-ValidationReference">reference 266 * validation</A> of all enclosed references using the {@link Reference#verify} method. 267 * 268 * <p>This step loops through all {@link Reference}s and does verify the hash 269 * values. If one or more verifications fail, the method returns 270 * <code>false</code>. If <i>all</i> verifications are successful, 271 * it returns <code>true</code>. The results of the individual reference 272 * validations are available by using the {@link #getVerificationResult(int)} method 273 * 274 * @return true if all References verify, false if one or more do not verify. 275 * @throws MissingResourceFailureException if a {@link Reference} does not verify 276 * (throws a {@link com.sun.org.apache.xml.internal.security.signature.ReferenceNotInitializedException} 277 * because of an uninitialized {@link XMLSignatureInput} 278 * @see com.sun.org.apache.xml.internal.security.signature.Reference#verify 279 * @see com.sun.org.apache.xml.internal.security.signature.SignedInfo#verify() 280 * @see com.sun.org.apache.xml.internal.security.signature.MissingResourceFailureException 281 * @throws XMLSecurityException 282 */ 283 public boolean verifyReferences() 284 throws MissingResourceFailureException, XMLSecurityException { 285 return this.verifyReferences(false); 286 } 287 288 /** 289 * Used to do a <A HREF="http://www.w3.org/TR/xmldsig-core/#def-ValidationReference">reference 290 * validation</A> of all enclosed references using the {@link Reference#verify} method. 291 * 292 * <p>This step loops through all {@link Reference}s and does verify the hash 293 * values. If one or more verifications fail, the method returns 294 * <code>false</code>. If <i>all</i> verifications are successful, 295 * it returns <code>true</code>. The results of the individual reference 296 * validations are available by using the {@link #getVerificationResult(int)} method 297 * 298 * @param followManifests 299 * @return true if all References verify, false if one or more do not verify. 300 * @throws MissingResourceFailureException if a {@link Reference} does not verify 301 * (throws a {@link com.sun.org.apache.xml.internal.security.signature.ReferenceNotInitializedException} 302 * because of an uninitialized {@link XMLSignatureInput} 303 * @see com.sun.org.apache.xml.internal.security.signature.Reference#verify 304 * @see com.sun.org.apache.xml.internal.security.signature.SignedInfo#verify(boolean) 305 * @see com.sun.org.apache.xml.internal.security.signature.MissingResourceFailureException 306 * @throws XMLSecurityException 307 */ 308 public boolean verifyReferences(boolean followManifests) 309 throws MissingResourceFailureException, XMLSecurityException { 310 if (referencesEl == null) { 311 this.referencesEl = 312 XMLUtils.selectDsNodes( 313 this.constructionElement.getFirstChild(), Constants._TAG_REFERENCE 314 ); 315 } 316 if (log.isLoggable(java.util.logging.Level.FINE)) { 317 log.log(java.util.logging.Level.FINE, "verify " + referencesEl.length + " References"); 318 log.log(java.util.logging.Level.FINE, "I am " + (followManifests 319 ? "" : "not") + " requested to follow nested Manifests"); 320 } 321 if (referencesEl.length == 0) { 322 throw new XMLSecurityException("empty"); 323 } 324 if (secureValidation && referencesEl.length > MAXIMUM_REFERENCE_COUNT) { 325 Object exArgs[] = { referencesEl.length, MAXIMUM_REFERENCE_COUNT }; 326 327 throw new XMLSecurityException("signature.tooManyReferences", exArgs); 328 } 329 330 this.verificationResults = new boolean[referencesEl.length]; 331 boolean verify = true; 332 for (int i = 0; i < this.referencesEl.length; i++) { 333 Reference currentRef = 334 new Reference(referencesEl[i], this.baseURI, this, secureValidation); 335 336 this.references.set(i, currentRef); 337 338 // if only one item does not verify, the whole verification fails 339 try { 340 boolean currentRefVerified = currentRef.verify(); 341 342 this.setVerificationResult(i, currentRefVerified); 343 344 if (!currentRefVerified) { 345 verify = false; 346 } 347 if (log.isLoggable(java.util.logging.Level.FINE)) { 348 log.log(java.util.logging.Level.FINE, "The Reference has Type " + currentRef.getType()); 349 } 350 351 // was verification successful till now and do we want to verify the Manifest? 352 if (verify && followManifests && currentRef.typeIsReferenceToManifest()) { 353 if (log.isLoggable(java.util.logging.Level.FINE)) { 354 log.log(java.util.logging.Level.FINE, "We have to follow a nested Manifest"); 355 } 356 357 try { 358 XMLSignatureInput signedManifestNodes = 359 currentRef.dereferenceURIandPerformTransforms(null); 360 Set<Node> nl = signedManifestNodes.getNodeSet(); 361 Manifest referencedManifest = null; 362 Iterator<Node> nlIterator = nl.iterator(); 363 364 findManifest: while (nlIterator.hasNext()) { 365 Node n = nlIterator.next(); 366 367 if ((n.getNodeType() == Node.ELEMENT_NODE) 368 && ((Element) n).getNamespaceURI().equals(Constants.SignatureSpecNS) 369 && ((Element) n).getLocalName().equals(Constants._TAG_MANIFEST) 370 ) { 371 try { 372 referencedManifest = 373 new Manifest( 374 (Element)n, signedManifestNodes.getSourceURI(), secureValidation 375 ); 376 break findManifest; 377 } catch (XMLSecurityException ex) { 378 if (log.isLoggable(java.util.logging.Level.FINE)) { 379 log.log(java.util.logging.Level.FINE, ex.getMessage(), ex); 380 } 381 // Hm, seems not to be a ds:Manifest 382 } 383 } 384 } 385 386 if (referencedManifest == null) { 387 // The Reference stated that it points to a ds:Manifest 388 // but we did not find a ds:Manifest in the signed area 389 throw new MissingResourceFailureException("empty", currentRef); 390 } 391 392 referencedManifest.perManifestResolvers = this.perManifestResolvers; 393 referencedManifest.resolverProperties = this.resolverProperties; 394 395 boolean referencedManifestValid = 396 referencedManifest.verifyReferences(followManifests); 397 398 if (!referencedManifestValid) { 399 verify = false; 400 401 log.log(java.util.logging.Level.WARNING, "The nested Manifest was invalid (bad)"); 402 } else { 403 if (log.isLoggable(java.util.logging.Level.FINE)) { 404 log.log(java.util.logging.Level.FINE, "The nested Manifest was valid (good)"); 405 } 406 } 407 } catch (IOException ex) { 408 throw new ReferenceNotInitializedException("empty", ex); 409 } catch (ParserConfigurationException ex) { 410 throw new ReferenceNotInitializedException("empty", ex); 411 } catch (SAXException ex) { 412 throw new ReferenceNotInitializedException("empty", ex); 413 } 414 } 415 } catch (ReferenceNotInitializedException ex) { 416 Object exArgs[] = { currentRef.getURI() }; 417 418 throw new MissingResourceFailureException( 419 "signature.Verification.Reference.NoInput", exArgs, ex, currentRef 420 ); 421 } 422 } 423 424 return verify; 425 } 426 427 /** 428 * Method setVerificationResult 429 * 430 * @param index 431 * @param verify 432 */ 433 private void setVerificationResult(int index, boolean verify) { 434 if (this.verificationResults == null) { 435 this.verificationResults = new boolean[this.getLength()]; 436 } 437 438 this.verificationResults[index] = verify; 439 } 440 441 /** 442 * After verifying a {@link Manifest} or a {@link SignedInfo} using the 443 * {@link Manifest#verifyReferences()} or {@link SignedInfo#verify()} methods, 444 * the individual results can be retrieved with this method. 445 * 446 * @param index an index of into a {@link Manifest} or a {@link SignedInfo} 447 * @return the results of reference validation at the specified index 448 * @throws XMLSecurityException 449 */ 450 public boolean getVerificationResult(int index) throws XMLSecurityException { 451 if ((index < 0) || (index > this.getLength() - 1)) { 452 Object exArgs[] = { Integer.toString(index), Integer.toString(this.getLength()) }; 453 Exception e = 454 new IndexOutOfBoundsException( 455 I18n.translate("signature.Verification.IndexOutOfBounds", exArgs) 456 ); 457 458 throw new XMLSecurityException("generic.EmptyMessage", e); 459 } 460 461 if (this.verificationResults == null) { 462 try { 463 this.verifyReferences(); 464 } catch (Exception ex) { 465 throw new XMLSecurityException("generic.EmptyMessage", ex); 466 } 467 } 468 469 return this.verificationResults[index]; 470 } 471 472 /** 473 * Adds Resource Resolver for retrieving resources at specified <code>URI</code> attribute 474 * in <code>reference</code> element 475 * 476 * @param resolver {@link ResourceResolver} can provide the implemenatin subclass of 477 * {@link ResourceResolverSpi} for retrieving resource. 478 */ 479 public void addResourceResolver(ResourceResolver resolver) { 480 if (resolver == null) { 481 return; 482 } 483 if (perManifestResolvers == null) { 484 perManifestResolvers = new ArrayList<ResourceResolver>(); 485 } 486 this.perManifestResolvers.add(resolver); 487 } 488 489 /** 490 * Adds Resource Resolver for retrieving resources at specified <code>URI</code> attribute 491 * in <code>reference</code> element 492 * 493 * @param resolverSpi the implementation subclass of {@link ResourceResolverSpi} for 494 * retrieving the resource. 495 */ 496 public void addResourceResolver(ResourceResolverSpi resolverSpi) { 497 if (resolverSpi == null) { 498 return; 499 } 500 if (perManifestResolvers == null) { 501 perManifestResolvers = new ArrayList<ResourceResolver>(); 502 } 503 perManifestResolvers.add(new ResourceResolver(resolverSpi)); 504 } 505 506 /** 507 * Get the Per-Manifest Resolver List 508 * @return the per-manifest Resolver List 509 */ 510 public List<ResourceResolver> getPerManifestResolvers() { 511 return perManifestResolvers; 512 } 513 514 /** 515 * Get the resolver property map 516 * @return the resolver property map 517 */ 518 public Map<String, String> getResolverProperties() { 519 return resolverProperties; 520 } 521 522 /** 523 * Used to pass parameters like proxy servers etc to the ResourceResolver 524 * implementation. 525 * 526 * @param key the key 527 * @param value the value 528 */ 529 public void setResolverProperty(String key, String value) { 530 if (resolverProperties == null) { 531 resolverProperties = new HashMap<String, String>(10); 532 } 533 this.resolverProperties.put(key, value); 534 } 535 536 /** 537 * Returns the value at specified key 538 * 539 * @param key the key 540 * @return the value 541 */ 542 public String getResolverProperty(String key) { 543 return this.resolverProperties.get(key); 544 } 545 546 /** 547 * Method getSignedContentItem 548 * 549 * @param i 550 * @return The signed content of the i reference. 551 * 552 * @throws XMLSignatureException 553 */ 554 public byte[] getSignedContentItem(int i) throws XMLSignatureException { 555 try { 556 return this.getReferencedContentAfterTransformsItem(i).getBytes(); 557 } catch (IOException ex) { 558 throw new XMLSignatureException("empty", ex); 559 } catch (CanonicalizationException ex) { 560 throw new XMLSignatureException("empty", ex); 561 } catch (InvalidCanonicalizerException ex) { 562 throw new XMLSignatureException("empty", ex); 563 } catch (XMLSecurityException ex) { 564 throw new XMLSignatureException("empty", ex); 565 } 566 } 567 568 /** 569 * Method getReferencedContentPriorTransformsItem 570 * 571 * @param i 572 * @return The contents before transformation of the reference i. 573 * @throws XMLSecurityException 574 */ 575 public XMLSignatureInput getReferencedContentBeforeTransformsItem(int i) 576 throws XMLSecurityException { 577 return this.item(i).getContentsBeforeTransformation(); 578 } 579 580 /** 581 * Method getReferencedContentAfterTransformsItem 582 * 583 * @param i 584 * @return The contents after transformation of the reference i. 585 * @throws XMLSecurityException 586 */ 587 public XMLSignatureInput getReferencedContentAfterTransformsItem(int i) 588 throws XMLSecurityException { 589 return this.item(i).getContentsAfterTransformation(); 590 } 591 592 /** 593 * Method getSignedContentLength 594 * 595 * @return The number of references contained in this reference. 596 */ 597 public int getSignedContentLength() { 598 return this.getLength(); 599 } 600 601 /** 602 * Method getBaseLocalName 603 * 604 * @inheritDoc 605 */ 606 public String getBaseLocalName() { 607 return Constants._TAG_MANIFEST; 608 } 609 } |