--- old/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMReference.java 2013-06-28 11:34:54.463910620 -0400 +++ new/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMReference.java 2013-06-28 11:34:54.291915974 -0400 @@ -2,34 +2,36 @@ * reserved comment block * DO NOT REMOVE OR ALTER! */ -/* - * Copyright 2005 The Apache Software Foundation. - * - * Licensed 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 +/** + * 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 * - * 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. + * 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. */ /* * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. */ /* - * =========================================================================== + * =========================================================================== * * (C) Copyright IBM Corp. 2003 All Rights Reserved. * * =========================================================================== */ /* - * $Id: DOMReference.java,v 1.2 2008/07/24 15:20:32 mullan Exp $ + * $Id: DOMReference.java 1334007 2012-05-04 14:59:46Z coheigea $ */ package org.jcp.xml.dsig.internal.dom; @@ -43,8 +45,6 @@ import java.net.URISyntaxException; import java.security.*; import java.util.*; -import java.util.logging.Level; -import java.util.logging.Logger; import org.w3c.dom.Attr; import org.w3c.dom.Document; import org.w3c.dom.Element; @@ -63,14 +63,13 @@ * @author Sean Mullan * @author Joyce Leung */ -public final class DOMReference extends DOMStructure +public final class DOMReference extends DOMStructure implements Reference, DOMURIReference { - - /** - * The maximum number of transforms per reference, if secure validation - * is enabled. - */ - public static final int MAXIMUM_TRANSFORM_COUNT = 5; + + /** + * The maximum number of transforms per reference, if secure validation is enabled. + */ + public static final int MAXIMUM_TRANSFORM_COUNT = 5; /** * Look up useC14N11 system property. If true, an explicit C14N11 transform @@ -82,17 +81,18 @@ private static boolean useC14N11 = AccessController.doPrivileged(new PrivilegedAction() { public Boolean run() { - return Boolean.getBoolean - ("com.sun.org.apache.xml.internal.security.useC14N11"); + return Boolean.valueOf(Boolean.getBoolean + ("com.sun.org.apache.xml.internal.security.useC14N11")); } }); - private static Logger log = Logger.getLogger("org.jcp.xml.dsig.internal.dom"); - + private static java.util.logging.Logger log = + java.util.logging.Logger.getLogger("org.jcp.xml.dsig.internal.dom"); + private final DigestMethod digestMethod; private final String id; - private final List transforms; - private List allTransforms; + private final List transforms; + private List allTransforms; private final Data appliedTransformData; private Attr here; private final String uri; @@ -124,46 +124,51 @@ * not of type Transform */ public DOMReference(String uri, String type, DigestMethod dm, - List transforms, String id, Provider provider) { + List transforms, String id, + Provider provider) + { this(uri, type, dm, null, null, transforms, id, null, provider); } public DOMReference(String uri, String type, DigestMethod dm, - List appliedTransforms, Data result, List transforms, String id, - Provider provider) { + List appliedTransforms, + Data result, List transforms, + String id, Provider provider) + { this(uri, type, dm, appliedTransforms, result, transforms, id, null, provider); } public DOMReference(String uri, String type, DigestMethod dm, - List appliedTransforms, Data result, List transforms, String id, - byte[] digestValue, Provider provider) { + List appliedTransforms, + Data result, List transforms, + String id, byte[] digestValue, Provider provider) + { if (dm == null) { throw new NullPointerException("DigestMethod must be non-null"); } - this.allTransforms = new ArrayList(); - if (appliedTransforms != null) { - List transformsCopy = new ArrayList(appliedTransforms); - for (int i = 0, size = transformsCopy.size(); i < size; i++) { - if (!(transformsCopy.get(i) instanceof Transform)) { + if (appliedTransforms == null) { + this.allTransforms = new ArrayList(); + } else { + this.allTransforms = new ArrayList(appliedTransforms); + for (int i = 0, size = this.allTransforms.size(); i < size; i++) { + if (!(this.allTransforms.get(i) instanceof Transform)) { throw new ClassCastException ("appliedTransforms["+i+"] is not a valid type"); } } - this.allTransforms = transformsCopy; } if (transforms == null) { - this.transforms = Collections.EMPTY_LIST; + this.transforms = Collections.emptyList(); } else { - List transformsCopy = new ArrayList(transforms); - for (int i = 0, size = transformsCopy.size(); i < size; i++) { - if (!(transformsCopy.get(i) instanceof Transform)) { + this.transforms = new ArrayList(transforms); + for (int i = 0, size = this.transforms.size(); i < size; i++) { + if (!(this.transforms.get(i) instanceof Transform)) { throw new ClassCastException ("transforms["+i+"] is not a valid type"); } } - this.transforms = transformsCopy; - this.allTransforms.addAll(transformsCopy); + this.allTransforms.addAll(this.transforms); } this.digestMethod = dm; this.uri = uri; @@ -177,39 +182,40 @@ this.type = type; this.id = id; if (digestValue != null) { - this.digestValue = (byte[]) digestValue.clone(); + this.digestValue = (byte[])digestValue.clone(); this.digested = true; } this.appliedTransformData = result; this.provider = provider; } - + /** * Creates a DOMReference from an element. * * @param refElem a Reference element */ - public DOMReference(Element refElem, XMLCryptoContext context, - Provider provider) throws MarshalException { + public DOMReference(Element refElem, XMLCryptoContext context, + Provider provider) + throws MarshalException + { boolean secVal = Utils.secureValidation(context); - + // unmarshal Transforms, if specified Element nextSibling = DOMUtils.getFirstChildElement(refElem); - List transforms = new ArrayList(5); + List transforms = new ArrayList(5); if (nextSibling.getLocalName().equals("Transforms")) { Element transformElem = DOMUtils.getFirstChildElement(nextSibling); - + int transformCount = 0; while (transformElem != null) { transforms.add (new DOMTransform(transformElem, context, provider)); transformElem = DOMUtils.getNextSiblingElement(transformElem); - + transformCount++; if (secVal && (transformCount > MAXIMUM_TRANSFORM_COUNT)) { - String error = "A maxiumum of " + MAXIMUM_TRANSFORM_COUNT + - " transforms per Reference are allowed" + - " with secure validation"; + String error = "A maxiumum of " + MAXIMUM_TRANSFORM_COUNT + " " + + "transforms per Reference are allowed with secure validation"; throw new MarshalException(error); } } @@ -220,12 +226,11 @@ Element dmElem = nextSibling; this.digestMethod = DOMDigestMethod.unmarshal(dmElem); String digestMethodAlgorithm = this.digestMethod.getAlgorithm(); - if (secVal - && MessageDigestAlgorithm.ALGO_ID_DIGEST_NOT_RECOMMENDED_MD5.equals(digestMethodAlgorithm)) - { - throw new MarshalException("It is forbidden to use algorithm " + - digestMethod + - " when secure validation is enabled"); + if (secVal + && MessageDigestAlgorithm.ALGO_ID_DIGEST_NOT_RECOMMENDED_MD5.equals(digestMethodAlgorithm)) { + throw new MarshalException( + "It is forbidden to use algorithm " + digestMethod + " when secure validation is enabled" + ); } // unmarshal DigestValue @@ -238,7 +243,7 @@ // unmarshal attributes this.uri = DOMUtils.getAttributeValue(refElem, "URI"); - + Attr attr = refElem.getAttributeNodeNS(null, "Id"); if (attr != null) { this.id = attr.getValue(); @@ -277,23 +282,24 @@ } public byte[] getDigestValue() { - return (digestValue == null ? null : (byte[]) digestValue.clone()); + return (digestValue == null ? null : (byte[])digestValue.clone()); } public byte[] getCalculatedDigestValue() { - return (calcDigestValue == null ? null - : (byte[]) calcDigestValue.clone()); + return (calcDigestValue == null ? null + : (byte[])calcDigestValue.clone()); } public void marshal(Node parent, String dsPrefix, DOMCryptoContext context) - throws MarshalException { - if (log.isLoggable(Level.FINE)) { - log.log(Level.FINE, "Marshalling Reference"); + throws MarshalException + { + if (log.isLoggable(java.util.logging.Level.FINE)) { + log.log(java.util.logging.Level.FINE, "Marshalling Reference"); } Document ownerDoc = DOMUtils.getOwnerDocument(parent); - refElem = DOMUtils.createElement - (ownerDoc, "Reference", XMLSignature.XMLNS, dsPrefix); + refElem = DOMUtils.createElement(ownerDoc, "Reference", + XMLSignature.XMLNS, dsPrefix); // set attributes DOMUtils.setAttributeID(refElem, "Id", id); @@ -302,25 +308,28 @@ // create and append Transforms element if (!allTransforms.isEmpty()) { - Element transformsElem = DOMUtils.createElement - (ownerDoc, "Transforms", XMLSignature.XMLNS, dsPrefix); + Element transformsElem = DOMUtils.createElement(ownerDoc, + "Transforms", + XMLSignature.XMLNS, + dsPrefix); refElem.appendChild(transformsElem); - for (int i = 0, size = allTransforms.size(); i < size; i++) { - DOMStructure transform = - (DOMStructure) allTransforms.get(i); - transform.marshal(transformsElem, dsPrefix, context); + for (Transform transform : allTransforms) { + ((DOMStructure)transform).marshal(transformsElem, + dsPrefix, context); } } // create and append DigestMethod element - ((DOMDigestMethod) digestMethod).marshal(refElem, dsPrefix, context); + ((DOMDigestMethod)digestMethod).marshal(refElem, dsPrefix, context); // create and append DigestValue element - if (log.isLoggable(Level.FINE)) { - log.log(Level.FINE, "Adding digestValueElem"); + if (log.isLoggable(java.util.logging.Level.FINE)) { + log.log(java.util.logging.Level.FINE, "Adding digestValueElem"); } - Element digestValueElem = DOMUtils.createElement - (ownerDoc, "DigestValue", XMLSignature.XMLNS, dsPrefix); + Element digestValueElem = DOMUtils.createElement(ownerDoc, + "DigestValue", + XMLSignature.XMLNS, + dsPrefix); if (digestValue != null) { digestValueElem.appendChild (ownerDoc.createTextNode(Base64.encode(digestValue))); @@ -331,8 +340,9 @@ here = refElem.getAttributeNodeNS(null, "URI"); } - public void digest(XMLSignContext signContext) - throws XMLSignatureException { + public void digest(XMLSignContext signContext) + throws XMLSignatureException + { Data data = null; if (appliedTransformData == null) { data = dereference(signContext); @@ -343,8 +353,8 @@ // insert digestValue into DigestValue element String encodedDV = Base64.encode(digestValue); - if (log.isLoggable(Level.FINE)) { - log.log(Level.FINE, "Reference object uri = " + uri); + if (log.isLoggable(java.util.logging.Level.FINE)) { + log.log(java.util.logging.Level.FINE, "Reference object uri = " + uri); } Element digestElem = DOMUtils.getLastChildElement(refElem); if (digestElem == null) { @@ -355,13 +365,14 @@ (refElem.getOwnerDocument().createTextNode(encodedDV)); digested = true; - if (log.isLoggable(Level.FINE)) { - log.log(Level.FINE, "Reference digesting completed"); + if (log.isLoggable(java.util.logging.Level.FINE)) { + log.log(java.util.logging.Level.FINE, "Reference digesting completed"); } } public boolean validate(XMLValidateContext validateContext) - throws XMLSignatureException { + throws XMLSignatureException + { if (validateContext == null) { throw new NullPointerException("validateContext cannot be null"); } @@ -371,11 +382,9 @@ Data data = dereference(validateContext); calcDigestValue = transform(data, validateContext); - if (log.isLoggable(Level.FINE)) { - log.log(Level.FINE, "Expected digest: " - + Base64.encode(digestValue)); - log.log(Level.FINE, "Actual digest: " - + Base64.encode(calcDigestValue)); + if (log.isLoggable(java.util.logging.Level.FINE)) { + log.log(java.util.logging.Level.FINE, "Expected digest: " + Base64.encode(digestValue)); + log.log(java.util.logging.Level.FINE, "Actual digest: " + Base64.encode(calcDigestValue)); } validationStatus = Arrays.equals(digestValue, calcDigestValue); @@ -391,8 +400,9 @@ return dis; } - private Data dereference(XMLCryptoContext context) - throws XMLSignatureException { + private Data dereference(XMLCryptoContext context) + throws XMLSignatureException + { Data data = null; // use user-specified URIDereferencer if specified; otherwise use deflt @@ -402,11 +412,9 @@ } try { data = deref.dereference(this, context); - if (log.isLoggable(Level.FINE)) { - log.log(Level.FINE, "URIDereferencer class name: " - + deref.getClass().getName()); - log.log(Level.FINE, "Data class name: " - + data.getClass().getName()); + if (log.isLoggable(java.util.logging.Level.FINE)) { + log.log(java.util.logging.Level.FINE, "URIDereferencer class name: " + deref.getClass().getName()); + log.log(java.util.logging.Level.FINE, "Data class name: " + data.getClass().getName()); } } catch (URIReferenceException ure) { throw new XMLSignatureException(ure); @@ -415,13 +423,14 @@ return data; } - private byte[] transform(Data dereferencedData, - XMLCryptoContext context) throws XMLSignatureException { - + private byte[] transform(Data dereferencedData, + XMLCryptoContext context) + throws XMLSignatureException + { if (md == null) { try { md = MessageDigest.getInstance - (((DOMDigestMethod) digestMethod).getMessageDigestAlgorithm()); + (((DOMDigestMethod)digestMethod).getMessageDigestAlgorithm()); } catch (NoSuchAlgorithmException nsae) { throw new XMLSignatureException(nsae); } @@ -430,28 +439,25 @@ DigesterOutputStream dos; Boolean cache = (Boolean) context.getProperty("javax.xml.crypto.dsig.cacheReference"); - if (cache != null && cache.booleanValue() == true) { + if (cache != null && cache.booleanValue()) { this.derefData = copyDerefData(dereferencedData); dos = new DigesterOutputStream(md, true); } else { dos = new DigesterOutputStream(md); } - OutputStream os = new UnsyncBufferedOutputStream(dos); + OutputStream os = null; Data data = dereferencedData; - for (int i = 0, size = transforms.size(); i < size; i++) { - DOMTransform transform = (DOMTransform) transforms.get(i); - try { + try { + os = new UnsyncBufferedOutputStream(dos); + for (int i = 0, size = transforms.size(); i < size; i++) { + DOMTransform transform = (DOMTransform)transforms.get(i); if (i < size - 1) { data = transform.transform(data, context); } else { data = transform.transform(data, context, os); } - } catch (TransformException te) { - throw new XMLSignatureException(te); } - } - - try { + if (data != null) { XMLSignatureInput xi; // explicitly use C14N 1.1 when generating signature @@ -460,9 +466,9 @@ String c14nalg = CanonicalizationMethod.INCLUSIVE; if (context instanceof XMLSignContext) { if (!c14n11) { - Boolean prop = (Boolean) context.getProperty + Boolean prop = (Boolean)context.getProperty ("com.sun.org.apache.xml.internal.security.useC14N11"); - c14n11 = (prop != null && prop.booleanValue() == true); + c14n11 = (prop != null && prop.booleanValue()); if (c14n11) { c14nalg = "http://www.w3.org/2006/12/xml-c14n11"; } @@ -471,17 +477,20 @@ } } if (data instanceof ApacheData) { - xi = ((ApacheData) data).getXMLSignatureInput(); + xi = ((ApacheData)data).getXMLSignatureInput(); } else if (data instanceof OctetStreamData) { xi = new XMLSignatureInput (((OctetStreamData)data).getOctetStream()); } else if (data instanceof NodeSetData) { TransformService spi = null; - try { + if (provider == null) { spi = TransformService.getInstance(c14nalg, "DOM"); - } catch (NoSuchAlgorithmException nsae) { - spi = TransformService.getInstance - (c14nalg, "DOM", provider); + } else { + try { + spi = TransformService.getInstance(c14nalg, "DOM", provider); + } catch (NoSuchAlgorithmException nsae) { + spi = TransformService.getInstance(c14nalg, "DOM"); + } } data = spi.transform(data, context); xi = new XMLSignatureInput @@ -491,20 +500,31 @@ } if (context instanceof XMLSignContext && c14n11 && !xi.isOctetStream() && !xi.isOutputStreamSet()) { - DOMTransform t = new DOMTransform - (TransformService.getInstance(c14nalg, "DOM")); + TransformService spi = null; + if (provider == null) { + spi = TransformService.getInstance(c14nalg, "DOM"); + } else { + try { + spi = TransformService.getInstance(c14nalg, "DOM", provider); + } catch (NoSuchAlgorithmException nsae) { + spi = TransformService.getInstance(c14nalg, "DOM"); + } + } + + DOMTransform t = new DOMTransform(spi); Element transformsElem = null; String dsPrefix = DOMUtils.getSignaturePrefix(context); if (allTransforms.isEmpty()) { transformsElem = DOMUtils.createElement( - refElem.getOwnerDocument(), + refElem.getOwnerDocument(), "Transforms", XMLSignature.XMLNS, dsPrefix); - refElem.insertBefore(transformsElem, + refElem.insertBefore(transformsElem, DOMUtils.getFirstChildElement(refElem)); } else { transformsElem = DOMUtils.getFirstChildElement(refElem); } - t.marshal(transformsElem, dsPrefix, (DOMCryptoContext) context); + t.marshal(transformsElem, dsPrefix, + (DOMCryptoContext)context); allTransforms.add(t); xi.updateOutputStream(os, true); } else { @@ -512,12 +532,35 @@ } } os.flush(); - if (cache != null && cache.booleanValue() == true) { + if (cache != null && cache.booleanValue()) { this.dis = dos.getInputStream(); } return dos.getDigestValue(); - } catch (Exception e) { + } catch (NoSuchAlgorithmException e) { + throw new XMLSignatureException(e); + } catch (TransformException e) { + throw new XMLSignatureException(e); + } catch (MarshalException e) { + throw new XMLSignatureException(e); + } catch (IOException e) { throw new XMLSignatureException(e); + } catch (com.sun.org.apache.xml.internal.security.c14n.CanonicalizationException e) { + throw new XMLSignatureException(e); + } finally { + if (os != null) { + try { + os.close(); + } catch (IOException e) { + throw new XMLSignatureException(e); + } + } + if (dos != null) { + try { + dos.close(); + } catch (IOException e) { + throw new XMLSignatureException(e); + } + } } } @@ -525,6 +568,7 @@ return here; } + @Override public boolean equals(Object o) { if (this == o) { return true; @@ -533,19 +577,41 @@ if (!(o instanceof Reference)) { return false; } - Reference oref = (Reference) o; + Reference oref = (Reference)o; - boolean idsEqual = (id == null ? oref.getId() == null : - id.equals(oref.getId())); - boolean urisEqual = (uri == null ? oref.getURI() == null : - uri.equals(oref.getURI())); - boolean typesEqual = (type == null ? oref.getType() == null : - type.equals(oref.getType())); + boolean idsEqual = (id == null ? oref.getId() == null + : id.equals(oref.getId())); + boolean urisEqual = (uri == null ? oref.getURI() == null + : uri.equals(oref.getURI())); + boolean typesEqual = (type == null ? oref.getType() == null + : type.equals(oref.getType())); boolean digestValuesEqual = Arrays.equals(digestValue, oref.getDigestValue()); - return (digestMethod.equals(oref.getDigestMethod()) && idsEqual && - urisEqual && typesEqual && allTransforms.equals(oref.getTransforms())); + return digestMethod.equals(oref.getDigestMethod()) && idsEqual && + urisEqual && typesEqual && + allTransforms.equals(oref.getTransforms()) && digestValuesEqual; + } + + @Override + public int hashCode() { + int result = 17; + if (id != null) { + result = 31 * result + id.hashCode(); + } + if (uri != null) { + result = 31 * result + uri.hashCode(); + } + if (type != null) { + result = 31 * result + type.hashCode(); + } + if (digestValue != null) { + result = 31 * result + Arrays.hashCode(digestValue); + } + result = 31 * result + digestMethod.hashCode(); + result = 31 * result + allTransforms.hashCode(); + + return result; } boolean isDigested() { @@ -555,18 +621,17 @@ private static Data copyDerefData(Data dereferencedData) { if (dereferencedData instanceof ApacheData) { // need to make a copy of the Data - ApacheData ad = (ApacheData) dereferencedData; + ApacheData ad = (ApacheData)dereferencedData; XMLSignatureInput xsi = ad.getXMLSignatureInput(); if (xsi.isNodeSet()) { try { - final Set s = xsi.getNodeSet(); + final Set s = xsi.getNodeSet(); return new NodeSetData() { public Iterator iterator() { return s.iterator(); } }; } catch (Exception e) { // log a warning - log.log(Level.WARNING, - "cannot cache dereferenced data: " + e); + log.log(java.util.logging.Level.WARNING, "cannot cache dereferenced data: " + e); return null; } } else if (xsi.isElement()) { @@ -574,12 +639,12 @@ (xsi.getSubNode(), xsi.isExcludeComments()); } else if (xsi.isOctetStream() || xsi.isByteArray()) { try { - return new OctetStreamData - (xsi.getOctetStream(), xsi.getSourceURI(), xsi.getMIMEType()); + return new OctetStreamData + (xsi.getOctetStream(), xsi.getSourceURI(), + xsi.getMIMEType()); } catch (IOException ioe) { // log a warning - log.log(Level.WARNING, - "cannot cache dereferenced data: " + ioe); + log.log(java.util.logging.Level.WARNING, "cannot cache dereferenced data: " + ioe); return null; } }