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