author | mullan |
Mon, 22 Apr 2013 11:23:33 +0100 | |
changeset 18240 | cda839ac048f |
parent 10694 | cf59e2badd14 |
child 18780 | f47b920867e7 |
permissions | -rw-r--r-- |
2 | 1 |
/* |
2 |
* reserved comment block |
|
3 |
* DO NOT REMOVE OR ALTER! |
|
4 |
*/ |
|
18240 | 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 |
|
2 | 13 |
* |
18240 | 14 |
* http://www.apache.org/licenses/LICENSE-2.0 |
2 | 15 |
* |
18240 | 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. |
|
2 | 22 |
*/ |
23 |
package com.sun.org.apache.xml.internal.security.c14n; |
|
24 |
||
25 |
import java.io.ByteArrayInputStream; |
|
18240 | 26 |
import java.io.InputStream; |
2 | 27 |
import java.io.OutputStream; |
28 |
import java.util.Map; |
|
29 |
import java.util.Set; |
|
18240 | 30 |
import java.util.concurrent.ConcurrentHashMap; |
2 | 31 |
|
18240 | 32 |
import javax.xml.XMLConstants; |
2 | 33 |
import javax.xml.parsers.DocumentBuilder; |
34 |
import javax.xml.parsers.DocumentBuilderFactory; |
|
35 |
||
18240 | 36 |
import com.sun.org.apache.xml.internal.security.c14n.implementations.Canonicalizer11_OmitComments; |
37 |
import com.sun.org.apache.xml.internal.security.c14n.implementations.Canonicalizer11_WithComments; |
|
38 |
import com.sun.org.apache.xml.internal.security.c14n.implementations.Canonicalizer20010315ExclOmitComments; |
|
39 |
import com.sun.org.apache.xml.internal.security.c14n.implementations.Canonicalizer20010315ExclWithComments; |
|
40 |
import com.sun.org.apache.xml.internal.security.c14n.implementations.Canonicalizer20010315OmitComments; |
|
41 |
import com.sun.org.apache.xml.internal.security.c14n.implementations.Canonicalizer20010315WithComments; |
|
2 | 42 |
import com.sun.org.apache.xml.internal.security.exceptions.AlgorithmAlreadyRegisteredException; |
43 |
import org.w3c.dom.Document; |
|
44 |
import org.w3c.dom.Node; |
|
45 |
import org.w3c.dom.NodeList; |
|
46 |
import org.xml.sax.InputSource; |
|
47 |
||
48 |
/** |
|
49 |
* |
|
50 |
* @author Christian Geuer-Pollmann |
|
51 |
*/ |
|
52 |
public class Canonicalizer { |
|
53 |
||
1337 | 54 |
/** The output encoding of canonicalized data */ |
55 |
public static final String ENCODING = "UTF8"; |
|
2 | 56 |
|
1337 | 57 |
/** |
18240 | 58 |
* XPath Expression for selecting every node and continuous comments joined |
1337 | 59 |
* in only one node |
2 | 60 |
*/ |
1337 | 61 |
public static final String XPATH_C14N_WITH_COMMENTS_SINGLE_NODE = |
62 |
"(.//. | .//@* | .//namespace::*)"; |
|
2 | 63 |
|
1337 | 64 |
/** |
2 | 65 |
* The URL defined in XML-SEC Rec for inclusive c14n <b>without</b> comments. |
66 |
*/ |
|
1337 | 67 |
public static final String ALGO_ID_C14N_OMIT_COMMENTS = |
68 |
"http://www.w3.org/TR/2001/REC-xml-c14n-20010315"; |
|
69 |
/** |
|
70 |
* The URL defined in XML-SEC Rec for inclusive c14n <b>with</b> comments. |
|
71 |
*/ |
|
72 |
public static final String ALGO_ID_C14N_WITH_COMMENTS = |
|
73 |
ALGO_ID_C14N_OMIT_COMMENTS + "#WithComments"; |
|
74 |
/** |
|
75 |
* The URL defined in XML-SEC Rec for exclusive c14n <b>without</b> comments. |
|
76 |
*/ |
|
77 |
public static final String ALGO_ID_C14N_EXCL_OMIT_COMMENTS = |
|
78 |
"http://www.w3.org/2001/10/xml-exc-c14n#"; |
|
79 |
/** |
|
80 |
* The URL defined in XML-SEC Rec for exclusive c14n <b>with</b> comments. |
|
81 |
*/ |
|
82 |
public static final String ALGO_ID_C14N_EXCL_WITH_COMMENTS = |
|
83 |
ALGO_ID_C14N_EXCL_OMIT_COMMENTS + "WithComments"; |
|
84 |
/** |
|
85 |
* The URI for inclusive c14n 1.1 <b>without</b> comments. |
|
86 |
*/ |
|
87 |
public static final String ALGO_ID_C14N11_OMIT_COMMENTS = |
|
88 |
"http://www.w3.org/2006/12/xml-c14n11"; |
|
89 |
/** |
|
90 |
* The URI for inclusive c14n 1.1 <b>with</b> comments. |
|
91 |
*/ |
|
92 |
public static final String ALGO_ID_C14N11_WITH_COMMENTS = |
|
93 |
ALGO_ID_C14N11_OMIT_COMMENTS + "#WithComments"; |
|
2 | 94 |
|
18240 | 95 |
private static Map<String, Class<? extends CanonicalizerSpi>> canonicalizerHash = |
96 |
new ConcurrentHashMap<String, Class<? extends CanonicalizerSpi>>(); |
|
1337 | 97 |
|
18240 | 98 |
private final CanonicalizerSpi canonicalizerSpi; |
2 | 99 |
|
1337 | 100 |
/** |
101 |
* Constructor Canonicalizer |
|
102 |
* |
|
103 |
* @param algorithmURI |
|
104 |
* @throws InvalidCanonicalizerException |
|
105 |
*/ |
|
18240 | 106 |
private Canonicalizer(String algorithmURI) throws InvalidCanonicalizerException { |
1337 | 107 |
try { |
10694
cf59e2badd14
7088502: Security libraries don't build with javac -Werror
mullan
parents:
1337
diff
changeset
|
108 |
Class<? extends CanonicalizerSpi> implementingClass = |
18240 | 109 |
canonicalizerHash.get(algorithmURI); |
2 | 110 |
|
18240 | 111 |
canonicalizerSpi = implementingClass.newInstance(); |
112 |
canonicalizerSpi.reset = true; |
|
1337 | 113 |
} catch (Exception e) { |
114 |
Object exArgs[] = { algorithmURI }; |
|
115 |
throw new InvalidCanonicalizerException( |
|
18240 | 116 |
"signature.Canonicalizer.UnknownCanonicalizer", exArgs, e |
117 |
); |
|
1337 | 118 |
} |
119 |
} |
|
2 | 120 |
|
1337 | 121 |
/** |
122 |
* Method getInstance |
|
123 |
* |
|
124 |
* @param algorithmURI |
|
18240 | 125 |
* @return a Canonicalizer instance ready for the job |
1337 | 126 |
* @throws InvalidCanonicalizerException |
127 |
*/ |
|
128 |
public static final Canonicalizer getInstance(String algorithmURI) |
|
18240 | 129 |
throws InvalidCanonicalizerException { |
130 |
return new Canonicalizer(algorithmURI); |
|
1337 | 131 |
} |
2 | 132 |
|
1337 | 133 |
/** |
134 |
* Method register |
|
135 |
* |
|
136 |
* @param algorithmURI |
|
137 |
* @param implementingClass |
|
138 |
* @throws AlgorithmAlreadyRegisteredException |
|
139 |
*/ |
|
10694
cf59e2badd14
7088502: Security libraries don't build with javac -Werror
mullan
parents:
1337
diff
changeset
|
140 |
@SuppressWarnings("unchecked") |
1337 | 141 |
public static void register(String algorithmURI, String implementingClass) |
18240 | 142 |
throws AlgorithmAlreadyRegisteredException, ClassNotFoundException { |
143 |
// check whether URI is already registered |
|
144 |
Class<? extends CanonicalizerSpi> registeredClass = |
|
145 |
canonicalizerHash.get(algorithmURI); |
|
146 |
||
147 |
if (registeredClass != null) { |
|
148 |
Object exArgs[] = { algorithmURI, registeredClass }; |
|
149 |
throw new AlgorithmAlreadyRegisteredException("algorithm.alreadyRegistered", exArgs); |
|
150 |
} |
|
2 | 151 |
|
18240 | 152 |
canonicalizerHash.put( |
153 |
algorithmURI, (Class<? extends CanonicalizerSpi>)Class.forName(implementingClass) |
|
154 |
); |
|
155 |
} |
|
156 |
||
157 |
/** |
|
158 |
* Method register |
|
159 |
* |
|
160 |
* @param algorithmURI |
|
161 |
* @param implementingClass |
|
162 |
* @throws AlgorithmAlreadyRegisteredException |
|
163 |
*/ |
|
164 |
public static void register(String algorithmURI, Class<CanonicalizerSpi> implementingClass) |
|
165 |
throws AlgorithmAlreadyRegisteredException, ClassNotFoundException { |
|
1337 | 166 |
// check whether URI is already registered |
18240 | 167 |
Class<? extends CanonicalizerSpi> registeredClass = canonicalizerHash.get(algorithmURI); |
2 | 168 |
|
1337 | 169 |
if (registeredClass != null) { |
170 |
Object exArgs[] = { algorithmURI, registeredClass }; |
|
18240 | 171 |
throw new AlgorithmAlreadyRegisteredException("algorithm.alreadyRegistered", exArgs); |
1337 | 172 |
} |
2 | 173 |
|
18240 | 174 |
canonicalizerHash.put(algorithmURI, implementingClass); |
175 |
} |
|
176 |
||
177 |
/** |
|
178 |
* This method registers the default algorithms. |
|
179 |
*/ |
|
180 |
public static void registerDefaultAlgorithms() { |
|
181 |
canonicalizerHash.put( |
|
182 |
Canonicalizer.ALGO_ID_C14N_OMIT_COMMENTS, |
|
183 |
Canonicalizer20010315OmitComments.class |
|
184 |
); |
|
185 |
canonicalizerHash.put( |
|
186 |
Canonicalizer.ALGO_ID_C14N_WITH_COMMENTS, |
|
187 |
Canonicalizer20010315WithComments.class |
|
188 |
); |
|
189 |
canonicalizerHash.put( |
|
190 |
Canonicalizer.ALGO_ID_C14N_EXCL_OMIT_COMMENTS, |
|
191 |
Canonicalizer20010315ExclOmitComments.class |
|
192 |
); |
|
193 |
canonicalizerHash.put( |
|
194 |
Canonicalizer.ALGO_ID_C14N_EXCL_WITH_COMMENTS, |
|
195 |
Canonicalizer20010315ExclWithComments.class |
|
196 |
); |
|
197 |
canonicalizerHash.put( |
|
198 |
Canonicalizer.ALGO_ID_C14N11_OMIT_COMMENTS, |
|
199 |
Canonicalizer11_OmitComments.class |
|
200 |
); |
|
201 |
canonicalizerHash.put( |
|
202 |
Canonicalizer.ALGO_ID_C14N11_WITH_COMMENTS, |
|
203 |
Canonicalizer11_WithComments.class |
|
204 |
); |
|
1337 | 205 |
} |
2 | 206 |
|
1337 | 207 |
/** |
208 |
* Method getURI |
|
209 |
* |
|
210 |
* @return the URI defined for this c14n instance. |
|
211 |
*/ |
|
212 |
public final String getURI() { |
|
18240 | 213 |
return canonicalizerSpi.engineGetURI(); |
1337 | 214 |
} |
2 | 215 |
|
1337 | 216 |
/** |
217 |
* Method getIncludeComments |
|
218 |
* |
|
219 |
* @return true if the c14n respect the comments. |
|
220 |
*/ |
|
221 |
public boolean getIncludeComments() { |
|
18240 | 222 |
return canonicalizerSpi.engineGetIncludeComments(); |
1337 | 223 |
} |
2 | 224 |
|
1337 | 225 |
/** |
226 |
* This method tries to canonicalize the given bytes. It's possible to even |
|
227 |
* canonicalize non-wellformed sequences if they are well-formed after being |
|
228 |
* wrapped with a <CODE>>a<...>/a<</CODE>. |
|
229 |
* |
|
230 |
* @param inputBytes |
|
18240 | 231 |
* @return the result of the canonicalization. |
1337 | 232 |
* @throws CanonicalizationException |
233 |
* @throws java.io.IOException |
|
234 |
* @throws javax.xml.parsers.ParserConfigurationException |
|
235 |
* @throws org.xml.sax.SAXException |
|
236 |
*/ |
|
237 |
public byte[] canonicalize(byte[] inputBytes) |
|
18240 | 238 |
throws javax.xml.parsers.ParserConfigurationException, |
239 |
java.io.IOException, org.xml.sax.SAXException, CanonicalizationException { |
|
240 |
InputStream bais = new ByteArrayInputStream(inputBytes); |
|
1337 | 241 |
InputSource in = new InputSource(bais); |
242 |
DocumentBuilderFactory dfactory = DocumentBuilderFactory.newInstance(); |
|
18240 | 243 |
dfactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, Boolean.TRUE); |
2 | 244 |
|
1337 | 245 |
dfactory.setNamespaceAware(true); |
2 | 246 |
|
18240 | 247 |
// needs to validate for ID attribute normalization |
1337 | 248 |
dfactory.setValidating(true); |
2 | 249 |
|
1337 | 250 |
DocumentBuilder db = dfactory.newDocumentBuilder(); |
2 | 251 |
|
1337 | 252 |
/* |
253 |
* for some of the test vectors from the specification, |
|
18240 | 254 |
* there has to be a validating parser for ID attributes, default |
1337 | 255 |
* attribute values, NMTOKENS, etc. |
18240 | 256 |
* Unfortunately, the test vectors do use different DTDs or |
1337 | 257 |
* even no DTD. So Xerces 1.3.1 fires many warnings about using |
258 |
* ErrorHandlers. |
|
259 |
* |
|
260 |
* Text from the spec: |
|
261 |
* |
|
262 |
* The input octet stream MUST contain a well-formed XML document, |
|
263 |
* but the input need not be validated. However, the attribute |
|
264 |
* value normalization and entity reference resolution MUST be |
|
265 |
* performed in accordance with the behaviors of a validating |
|
266 |
* XML processor. As well, nodes for default attributes (declared |
|
267 |
* in the ATTLIST with an AttValue but not specified) are created |
|
268 |
* in each element. Thus, the declarations in the document type |
|
269 |
* declaration are used to help create the canonical form, even |
|
270 |
* though the document type declaration is not retained in the |
|
271 |
* canonical form. |
|
272 |
*/ |
|
18240 | 273 |
db.setErrorHandler(new com.sun.org.apache.xml.internal.security.utils.IgnoreAllErrorHandler()); |
2 | 274 |
|
1337 | 275 |
Document document = db.parse(in); |
18240 | 276 |
return this.canonicalizeSubtree(document); |
1337 | 277 |
} |
2 | 278 |
|
1337 | 279 |
/** |
280 |
* Canonicalizes the subtree rooted by <CODE>node</CODE>. |
|
281 |
* |
|
18240 | 282 |
* @param node The node to canonicalize |
1337 | 283 |
* @return the result of the c14n. |
284 |
* |
|
285 |
* @throws CanonicalizationException |
|
286 |
*/ |
|
18240 | 287 |
public byte[] canonicalizeSubtree(Node node) throws CanonicalizationException { |
288 |
return canonicalizerSpi.engineCanonicalizeSubTree(node); |
|
1337 | 289 |
} |
2 | 290 |
|
1337 | 291 |
/** |
292 |
* Canonicalizes the subtree rooted by <CODE>node</CODE>. |
|
293 |
* |
|
294 |
* @param node |
|
295 |
* @param inclusiveNamespaces |
|
296 |
* @return the result of the c14n. |
|
297 |
* @throws CanonicalizationException |
|
298 |
*/ |
|
299 |
public byte[] canonicalizeSubtree(Node node, String inclusiveNamespaces) |
|
18240 | 300 |
throws CanonicalizationException { |
301 |
return canonicalizerSpi.engineCanonicalizeSubTree(node, inclusiveNamespaces); |
|
1337 | 302 |
} |
2 | 303 |
|
1337 | 304 |
/** |
305 |
* Canonicalizes an XPath node set. The <CODE>xpathNodeSet</CODE> is treated |
|
306 |
* as a list of XPath nodes, not as a list of subtrees. |
|
307 |
* |
|
308 |
* @param xpathNodeSet |
|
309 |
* @return the result of the c14n. |
|
310 |
* @throws CanonicalizationException |
|
311 |
*/ |
|
312 |
public byte[] canonicalizeXPathNodeSet(NodeList xpathNodeSet) |
|
18240 | 313 |
throws CanonicalizationException { |
314 |
return canonicalizerSpi.engineCanonicalizeXPathNodeSet(xpathNodeSet); |
|
1337 | 315 |
} |
2 | 316 |
|
1337 | 317 |
/** |
318 |
* Canonicalizes an XPath node set. The <CODE>xpathNodeSet</CODE> is treated |
|
319 |
* as a list of XPath nodes, not as a list of subtrees. |
|
320 |
* |
|
321 |
* @param xpathNodeSet |
|
322 |
* @param inclusiveNamespaces |
|
323 |
* @return the result of the c14n. |
|
324 |
* @throws CanonicalizationException |
|
325 |
*/ |
|
326 |
public byte[] canonicalizeXPathNodeSet( |
|
18240 | 327 |
NodeList xpathNodeSet, String inclusiveNamespaces |
328 |
) throws CanonicalizationException { |
|
329 |
return |
|
330 |
canonicalizerSpi.engineCanonicalizeXPathNodeSet(xpathNodeSet, inclusiveNamespaces); |
|
1337 | 331 |
} |
2 | 332 |
|
1337 | 333 |
/** |
334 |
* Canonicalizes an XPath node set. |
|
335 |
* |
|
336 |
* @param xpathNodeSet |
|
337 |
* @return the result of the c14n. |
|
338 |
* @throws CanonicalizationException |
|
339 |
*/ |
|
10694
cf59e2badd14
7088502: Security libraries don't build with javac -Werror
mullan
parents:
1337
diff
changeset
|
340 |
public byte[] canonicalizeXPathNodeSet(Set<Node> xpathNodeSet) |
18240 | 341 |
throws CanonicalizationException { |
342 |
return canonicalizerSpi.engineCanonicalizeXPathNodeSet(xpathNodeSet); |
|
1337 | 343 |
} |
2 | 344 |
|
1337 | 345 |
/** |
346 |
* Canonicalizes an XPath node set. |
|
347 |
* |
|
348 |
* @param xpathNodeSet |
|
349 |
* @param inclusiveNamespaces |
|
350 |
* @return the result of the c14n. |
|
351 |
* @throws CanonicalizationException |
|
352 |
*/ |
|
18240 | 353 |
public byte[] canonicalizeXPathNodeSet( |
354 |
Set<Node> xpathNodeSet, String inclusiveNamespaces |
|
355 |
) throws CanonicalizationException { |
|
356 |
return |
|
357 |
canonicalizerSpi.engineCanonicalizeXPathNodeSet(xpathNodeSet, inclusiveNamespaces); |
|
1337 | 358 |
} |
2 | 359 |
|
1337 | 360 |
/** |
361 |
* Sets the writer where the canonicalization ends. ByteArrayOutputStream |
|
362 |
* if none is set. |
|
363 |
* @param os |
|
364 |
*/ |
|
365 |
public void setWriter(OutputStream os) { |
|
18240 | 366 |
canonicalizerSpi.setWriter(os); |
1337 | 367 |
} |
2 | 368 |
|
1337 | 369 |
/** |
370 |
* Returns the name of the implementing {@link CanonicalizerSpi} class |
|
371 |
* |
|
372 |
* @return the name of the implementing {@link CanonicalizerSpi} class |
|
373 |
*/ |
|
374 |
public String getImplementingCanonicalizerClass() { |
|
18240 | 375 |
return canonicalizerSpi.getClass().getName(); |
1337 | 376 |
} |
2 | 377 |
|
1337 | 378 |
/** |
379 |
* Set the canonicalizer behaviour to not reset. |
|
380 |
*/ |
|
381 |
public void notReset() { |
|
18240 | 382 |
canonicalizerSpi.reset = false; |
1337 | 383 |
} |
18240 | 384 |
|
2 | 385 |
} |