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 */ 23package com.sun.org.apache.xml.internal.security.transforms; 24 25import java.io.IOException; 26import java.io.OutputStream; 27 28import com.sun.org.apache.xml.internal.security.c14n.CanonicalizationException; 29import com.sun.org.apache.xml.internal.security.c14n.Canonicalizer; 30import com.sun.org.apache.xml.internal.security.c14n.InvalidCanonicalizerException; 31import com.sun.org.apache.xml.internal.security.exceptions.XMLSecurityException; 32import com.sun.org.apache.xml.internal.security.signature.XMLSignatureException; 33import com.sun.org.apache.xml.internal.security.signature.XMLSignatureInput; 34import com.sun.org.apache.xml.internal.security.utils.Constants; 35import com.sun.org.apache.xml.internal.security.utils.SignatureElementProxy; 36import com.sun.org.apache.xml.internal.security.utils.XMLUtils; 37import org.w3c.dom.DOMException; 38import org.w3c.dom.Document; 39import org.w3c.dom.Element; 40import org.w3c.dom.NodeList; 41 42/** 43 * Holder of the {@link com.sun.org.apache.xml.internal.security.transforms.Transform} steps to 44 * be performed on the data. 45 * The input to the first Transform is the result of dereferencing the 46 * <code>URI</code> attribute of the <code>Reference</code> element. 47 * The output from the last Transform is the input for the 48 * <code>DigestMethod algorithm</code> 49 * 50 * @author Christian Geuer-Pollmann 51 * @see Transform 52 * @see com.sun.org.apache.xml.internal.security.signature.Reference 53 */ 54public class Transforms extends SignatureElementProxy { 55 56 /** Canonicalization - Required Canonical XML (omits comments) */ 57 public static final String TRANSFORM_C14N_OMIT_COMMENTS 58 = Canonicalizer.ALGO_ID_C14N_OMIT_COMMENTS; 59 60 /** Canonicalization - Recommended Canonical XML with Comments */ 61 public static final String TRANSFORM_C14N_WITH_COMMENTS 62 = Canonicalizer.ALGO_ID_C14N_WITH_COMMENTS; 63 64 /** Canonicalization - Required Canonical XML 1.1 (omits comments) */ 65 public static final String TRANSFORM_C14N11_OMIT_COMMENTS 66 = Canonicalizer.ALGO_ID_C14N11_OMIT_COMMENTS; 67 68 /** Canonicalization - Recommended Canonical XML 1.1 with Comments */ 69 public static final String TRANSFORM_C14N11_WITH_COMMENTS 70 = Canonicalizer.ALGO_ID_C14N11_WITH_COMMENTS; 71 72 /** Canonicalization - Required Exclusive Canonicalization (omits comments) */ 73 public static final String TRANSFORM_C14N_EXCL_OMIT_COMMENTS 74 = Canonicalizer.ALGO_ID_C14N_EXCL_OMIT_COMMENTS; 75 76 /** Canonicalization - Recommended Exclusive Canonicalization with Comments */ 77 public static final String TRANSFORM_C14N_EXCL_WITH_COMMENTS 78 = Canonicalizer.ALGO_ID_C14N_EXCL_WITH_COMMENTS; 79 80 /** Transform - Optional XSLT */ 81 public static final String TRANSFORM_XSLT 82 = "http://www.w3.org/TR/1999/REC-xslt-19991116"; 83 84 /** Transform - Required base64 decoding */ 85 public static final String TRANSFORM_BASE64_DECODE 86 = Constants.SignatureSpecNS + "base64"; 87 88 /** Transform - Recommended XPath */ 89 public static final String TRANSFORM_XPATH 90 = "http://www.w3.org/TR/1999/REC-xpath-19991116"; 91 92 /** Transform - Required Enveloped Signature */ 93 public static final String TRANSFORM_ENVELOPED_SIGNATURE 94 = Constants.SignatureSpecNS + "enveloped-signature"; 95 96 /** Transform - XPointer */ 97 public static final String TRANSFORM_XPOINTER 98 = "http://www.w3.org/TR/2001/WD-xptr-20010108"; 99 100 /** Transform - XPath Filter */ 101 public static final String TRANSFORM_XPATH2FILTER 102 = "http://www.w3.org/2002/06/xmldsig-filter2"; 103 104 /** {@link org.apache.commons.logging} logging facility */ 105 private static java.util.logging.Logger log = 106 java.util.logging.Logger.getLogger(Transforms.class.getName()); 107 108 private Element[] transforms; 109 110 protected Transforms() { }; 111 112 private boolean secureValidation; 113 114 /** 115 * Constructs {@link Transforms}. 116 * 117 * @param doc the {@link Document} in which <code>XMLSignature</code> will 118 * be placed 119 */ 120 public Transforms(Document doc) { 121 super(doc); 122 XMLUtils.addReturnToElement(this.constructionElement); 123 } 124 125 /** 126 * Constructs {@link Transforms} from {@link Element} which is 127 * <code>Transforms</code> Element 128 * 129 * @param element is <code>Transforms</code> element 130 * @param BaseURI the URI where the XML instance was stored 131 * @throws DOMException 132 * @throws InvalidTransformException 133 * @throws TransformationException 134 * @throws XMLSecurityException 135 * @throws XMLSignatureException 136 */ 137 public Transforms(Element element, String BaseURI) 138 throws DOMException, XMLSignatureException, InvalidTransformException, 139 TransformationException, XMLSecurityException { 140 super(element, BaseURI); 141 142 int numberOfTransformElems = this.getLength(); 143 144 if (numberOfTransformElems == 0) { 145 // At least one Transform element must be present. Bad. 146 Object exArgs[] = { Constants._TAG_TRANSFORM, Constants._TAG_TRANSFORMS }; 147 148 throw new TransformationException("xml.WrongContent", exArgs); 149 } 150 } 151 152 /** 153 * Set whether secure validation is enabled or not. The default is false. 154 */ 155 public void setSecureValidation(boolean secureValidation) { 156 this.secureValidation = secureValidation; 157 } 158 159 /** 160 * Adds the <code>Transform</code> with the specified <code>Transform 161 * algorithm URI</code> 162 * 163 * @param transformURI the URI form of transform that indicates which 164 * transformation is applied to data 165 * @throws TransformationException 166 */ 167 public void addTransform(String transformURI) throws TransformationException { 168 try { 169 if (log.isLoggable(java.util.logging.Level.FINE)) { 170 log.log(java.util.logging.Level.FINE, "Transforms.addTransform(" + transformURI + ")"); 171 } 172 173 Transform transform = new Transform(this.doc, transformURI); 174 175 this.addTransform(transform); 176 } catch (InvalidTransformException ex) { 177 throw new TransformationException("empty", ex); 178 } 179 } 180 181 /** 182 * Adds the <code>Transform</code> with the specified <code>Transform 183 * algorithm URI</code> 184 * 185 * @param transformURI the URI form of transform that indicates which 186 * transformation is applied to data 187 * @param contextElement 188 * @throws TransformationException 189 */ 190 public void addTransform(String transformURI, Element contextElement) 191 throws TransformationException { 192 try { 193 if (log.isLoggable(java.util.logging.Level.FINE)) { 194 log.log(java.util.logging.Level.FINE, "Transforms.addTransform(" + transformURI + ")"); 195 } 196 197 Transform transform = new Transform(this.doc, transformURI, contextElement); 198 199 this.addTransform(transform); 200 } catch (InvalidTransformException ex) { 201 throw new TransformationException("empty", ex); 202 } 203 } 204 205 /** 206 * Adds the <code>Transform</code> with the specified <code>Transform 207 * algorithm URI</code>. 208 * 209 * @param transformURI the URI form of transform that indicates which 210 * transformation is applied to data 211 * @param contextNodes 212 * @throws TransformationException 213 */ 214 public void addTransform(String transformURI, NodeList contextNodes) 215 throws TransformationException { 216 217 try { 218 Transform transform = new Transform(this.doc, transformURI, contextNodes); 219 this.addTransform(transform); 220 } catch (InvalidTransformException ex) { 221 throw new TransformationException("empty", ex); 222 } 223 } 224 225 /** 226 * Adds a user-provided Transform step. 227 * 228 * @param transform {@link Transform} object 229 */ 230 private void addTransform(Transform transform) { 231 if (log.isLoggable(java.util.logging.Level.FINE)) { 232 log.log(java.util.logging.Level.FINE, "Transforms.addTransform(" + transform.getURI() + ")"); 233 } 234 235 Element transformElement = transform.getElement(); 236 237 this.constructionElement.appendChild(transformElement); 238 XMLUtils.addReturnToElement(this.constructionElement); 239 } 240 241 /** 242 * Applies all included <code>Transform</code>s to xmlSignatureInput and 243 * returns the result of these transformations. 244 * 245 * @param xmlSignatureInput the input for the <code>Transform</code>s 246 * @return the result of the <code>Transforms</code> 247 * @throws TransformationException 248 */ 249 public XMLSignatureInput performTransforms( 250 XMLSignatureInput xmlSignatureInput 251 ) throws TransformationException { 252 return performTransforms(xmlSignatureInput, null); 253 } 254 255 /** 256 * Applies all included <code>Transform</code>s to xmlSignatureInput and 257 * returns the result of these transformations. 258 * 259 * @param xmlSignatureInput the input for the <code>Transform</code>s 260 * @param os where to output the last transformation. 261 * @return the result of the <code>Transforms</code> 262 * @throws TransformationException 263 */ 264 public XMLSignatureInput performTransforms( 265 XMLSignatureInput xmlSignatureInput, OutputStream os 266 ) throws TransformationException { 267 try { 268 int last = this.getLength() - 1; 269 for (int i = 0; i < last; i++) { 270 Transform t = this.item(i); 271 String uri = t.getURI(); 272 if (log.isLoggable(java.util.logging.Level.FINE)) { 273 log.log(java.util.logging.Level.FINE, "Perform the (" + i + ")th " + uri + " transform"); 274 } 275 checkSecureValidation(t); 276 xmlSignatureInput = t.performTransform(xmlSignatureInput); 277 } 278 if (last >= 0) { 279 Transform t = this.item(last); 280 checkSecureValidation(t); 281 xmlSignatureInput = t.performTransform(xmlSignatureInput, os); 282 } 283 284 return xmlSignatureInput; 285 } catch (IOException ex) { 286 throw new TransformationException("empty", ex); 287 } catch (CanonicalizationException ex) { 288 throw new TransformationException("empty", ex); 289 } catch (InvalidCanonicalizerException ex) { 290 throw new TransformationException("empty", ex); 291 } 292 } 293 294 private void checkSecureValidation(Transform transform) throws TransformationException { 295 String uri = transform.getURI(); 296 if (secureValidation && Transforms.TRANSFORM_XSLT.equals(uri)) { 297 Object exArgs[] = { uri }; 298 299 throw new TransformationException( 300 "signature.Transform.ForbiddenTransform", exArgs 301 ); 302 } 303 } 304 305 /** 306 * Return the nonnegative number of transformations. 307 * 308 * @return the number of transformations 309 */ 310 public int getLength() { 311 if (transforms == null) { 312 transforms = 313 XMLUtils.selectDsNodes(this.constructionElement.getFirstChild(), "Transform"); 314 } 315 return transforms.length; 316 } 317 318 /** 319 * Return the <it>i</it><sup>th</sup> <code>{@link Transform}</code>. 320 * Valid <code>i</code> values are 0 to <code>{@link #getLength}-1</code>. 321 * 322 * @param i index of {@link Transform} to return 323 * @return the <it>i</it><sup>th</sup> Transform 324 * @throws TransformationException 325 */ 326 public Transform item(int i) throws TransformationException { 327 try { 328 if (transforms == null) { 329 transforms = 330 XMLUtils.selectDsNodes(this.constructionElement.getFirstChild(), "Transform"); 331 } 332 return new Transform(transforms[i], this.baseURI); 333 } catch (XMLSecurityException ex) { 334 throw new TransformationException("empty", ex); 335 } 336 } 337 338 /** @inheritDoc */ 339 public String getBaseLocalName() { 340 return Constants._TAG_TRANSFORMS; 341 } 342} 343