1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.ws.security.transform;
19
20 import org.apache.commons.logging.Log;
21 import org.apache.commons.logging.LogFactory;
22 import org.apache.ws.security.WSConstants;
23 import org.apache.ws.security.WSDocInfo;
24 import org.apache.ws.security.WSDocInfoStore;
25 import org.apache.ws.security.WSSConfig;
26 import org.apache.ws.security.message.token.SecurityTokenReference;
27 import org.apache.ws.security.message.token.X509Security;
28 import org.apache.ws.security.util.WSSecurityUtil;
29 import org.apache.xml.security.c14n.CanonicalizationException;
30 import org.apache.xml.security.c14n.Canonicalizer;
31 import org.apache.xml.security.c14n.InvalidCanonicalizerException;
32 import org.apache.xml.security.exceptions.XMLSecurityException;
33 import org.apache.xml.security.signature.XMLSignatureInput;
34 import org.apache.xml.security.transforms.TransformSpi;
35 import org.apache.xml.security.utils.Base64;
36 import org.apache.xml.security.utils.XMLUtils;
37 import org.w3c.dom.Document;
38 import org.w3c.dom.Element;
39 import org.w3c.dom.Node;
40 import org.w3c.dom.NodeList;
41 import org.w3c.dom.Text;
42 import org.xml.sax.SAXException;
43
44 import javax.xml.parsers.DocumentBuilder;
45 import javax.xml.parsers.DocumentBuilderFactory;
46 import javax.xml.parsers.ParserConfigurationException;
47 import javax.xml.transform.TransformerException;
48 import java.io.ByteArrayInputStream;
49 import java.io.ByteArrayOutputStream;
50 import java.io.IOException;
51 import java.security.cert.X509Certificate;
52
53 /***
54 * Class STRTransform
55 *
56 * @author Werner Dittmann (Werner.Dittmann@siemens.com)
57 * @version 1.0
58 */
59 public class STRTransform extends TransformSpi {
60
61 /***
62 * Field implementedTransformURI
63 */
64 public static final String implementedTransformURI =
65 "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#STR-Transform";
66
67 private static Log log = LogFactory.getLog(STRTransform.class.getName());
68 private static boolean doDebug = false;
69
70 private WSDocInfo wsDocInfo = null;
71
72 public boolean wantsOctetStream() {
73 return false;
74 }
75
76 public boolean wantsNodeSet() {
77 return true;
78 }
79
80 public boolean returnsOctetStream() {
81 return true;
82 }
83
84 public boolean returnsNodeSet() {
85 return false;
86 }
87
88 /***
89 * Method engineGetURI
90 */
91 protected String engineGetURI() {
92 return STRTransform.implementedTransformURI;
93 }
94
95 /***
96 * Method enginePerformTransform
97 *
98 * @param input
99 * @throws CanonicalizationException
100 * @throws InvalidCanonicalizerException
101 */
102 protected XMLSignatureInput enginePerformTransform(XMLSignatureInput input)
103 throws IOException,
104 CanonicalizationException,
105 InvalidCanonicalizerException {
106
107 doDebug = log.isDebugEnabled();
108
109 if (doDebug) {
110 log.debug("Beginning STRTransform..." + input.toString());
111 }
112
113 try {
114
115
116
117
118
119 Document thisDoc = this._transformObject.getDocument();
120 int docHash = thisDoc.hashCode();
121 if (doDebug) {
122 log.debug("doc: " + thisDoc.toString() + ", " + docHash);
123 }
124
125
126
127
128
129
130 wsDocInfo = WSDocInfoStore.lookup(docHash);
131 if (wsDocInfo == null) {
132 throw (new CanonicalizationException("no WSDocInfo found"));
133 }
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149 String canonAlgo = null;
150 if (this._transformObject.length(WSConstants.WSSE_NS,
151 "TransformationParameters") == 1) {
152 Element tmpE = XMLUtils.selectNode(
153 this._transformObject.getElement().getFirstChild(),
154 WSConstants.WSSE_NS, "TransformationParameters", 0);
155 Element canonElem = (Element) WSSecurityUtil.getDirectChild(
156 tmpE, "CanonicalizationMethod", WSConstants.SIG_NS);
157 canonAlgo = canonElem.getAttribute("Algorithm");
158 if (doDebug) {
159 log.debug("CanonAlgo: " + canonAlgo);
160 }
161 }
162 Canonicalizer canon = Canonicalizer.getInstance(canonAlgo);
163 byte buf[] = canon.canonicalizeXPathNodeSet(input.getNodeSet());
164
165 ByteArrayOutputStream bos = new ByteArrayOutputStream(buf.length);
166 bos.write(buf, 0, buf.length);
167
168 if (doDebug) {
169 log.debug("canon bos: " + bos.toString());
170 }
171
172 DocumentBuilderFactory dfactory = DocumentBuilderFactory
173 .newInstance();
174 dfactory.setValidating(false);
175 dfactory.setNamespaceAware(true);
176
177 DocumentBuilder db = dfactory.newDocumentBuilder();
178
179 Document doc = db
180 .parse(new ByteArrayInputStream(bos.toByteArray()));
181
182
183
184
185
186
187 NodeList nodeList =
188 doc.getElementsByTagNameNS(WSConstants.WSSE_NS,
189 "SecurityTokenReference");
190
191 Element str = null;
192 Element tmpEl = (Element) nodeList.item(0);
193 if (doDebug) {
194 log.debug("STR: " + tmpEl.toString());
195 }
196
197
198
199 SecurityTokenReference secRef = new SecurityTokenReference(
200 WSSConfig.getDefaultWSConfig(), tmpEl);
201
202 str = dereferenceSTR(thisDoc, secRef);
203
204
205
206
207
208
209
210
211
212 str = (Element) doc.importNode(str, true);
213
214 Node parent = tmpEl.getParentNode();
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234 Element tmpEl1 = doc.createElement("temp");
235 tmpEl1.setAttributeNS(WSConstants.XMLNS_NS, "xmlns", "urn:X");
236 parent.replaceChild(tmpEl1, tmpEl);
237
238 tmpEl1.appendChild(str);
239
240
241
242
243
244
245
246 buf = canon.canonicalizeSubtree(doc, "#default");
247
248
249
250
251
252
253
254
255 bos = new ByteArrayOutputStream(buf.length);
256 bos.write(buf, 0, buf.length);
257
258 if (doDebug) {
259 log.debug("after c14n: " + bos.toString());
260 }
261
262
263
264
265
266 StringBuffer bf = new StringBuffer(bos.toString());
267 String bf1 = bf.substring("<temp xmlns=\"urn:X\">".length(), bf.length() - "</temp>".length());
268
269 if (doDebug) {
270 log.debug("last result: ");
271 log.debug(bf1.toString());
272 }
273 return new XMLSignatureInput(bf1.getBytes());
274
275
276 } catch (IOException ex) {
277 throw new CanonicalizationException("empty", ex);
278 } catch (ParserConfigurationException ex) {
279 throw new CanonicalizationException("empty", ex);
280 } catch (XMLSecurityException ex) {
281 throw new CanonicalizationException("empty", ex);
282 } catch (SAXException ex) {
283 throw new CanonicalizationException("empty", ex);
284 } catch (TransformerException ex) {
285 throw new CanonicalizationException("empty", ex);
286 } catch (Exception ex) {
287 throw new CanonicalizationException("empty", ex);
288 }
289 }
290
291 private Element dereferenceSTR(Document doc, SecurityTokenReference secRef)
292 throws Exception {
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312 Element tokElement = null;
313
314
315
316
317
318
319 if (secRef.containsReference()) {
320 if (doDebug) {
321 log.debug("STR: Reference");
322 }
323 tokElement = secRef.getTokenElement(doc, wsDocInfo);
324 if (tokElement == null) {
325 throw new CanonicalizationException("empty");
326 }
327 }
328
329
330
331
332
333 else if (secRef.containsX509IssuerSerial()) {
334 if (doDebug) {
335 log.debug("STR: IssuerSerial");
336 }
337 X509Certificate cert = null;
338 X509Security x509token = null;
339
340
341
342 if (x509token != null) {
343 cert = x509token.getX509Certificate(wsDocInfo.getCrypto());
344 } else {
345 X509Certificate[] certs = secRef.getX509IssuerSerial(wsDocInfo.getCrypto());
346 if (certs == null || certs.length == 0 || certs[0] == null) {
347 throw new CanonicalizationException("empty");
348 }
349 cert = certs[0];
350 }
351 tokElement = createBST(doc, cert, secRef.getElement());
352 }
353
354
355
356
357
358
359 else if (secRef.containsKeyIdentifier()) {
360 if (doDebug) {
361 log.debug("STR: KeyIdentifier");
362 }
363 X509Certificate cert = null;
364 X509Security x509token = null;
365
366
367
368 if (x509token != null) {
369 cert = x509token.getX509Certificate(wsDocInfo.getCrypto());
370 } else {
371 X509Certificate[] certs = secRef.getKeyIdentifier(wsDocInfo.getCrypto());
372 if (certs == null || certs.length == 0 || certs[0] == null) {
373 throw new CanonicalizationException("empty");
374 }
375 cert = certs[0];
376 }
377 tokElement = createBST(doc, cert, secRef.getElement());
378 }
379 return (Element) tokElement;
380 }
381
382 private Element createBST(Document doc,
383 X509Certificate cert,
384 Element secRefE)
385 throws Exception {
386 byte data[] = cert.getEncoded();
387 String prefix = WSSecurityUtil.getPrefixNS(WSConstants.WSSE_NS, secRefE);
388 Element elem =
389 doc.createElementNS(WSConstants.WSSE_NS,
390 prefix + ":BinarySecurityToken");
391 WSSecurityUtil.setNamespace(elem, WSConstants.WSSE_NS, prefix);
392 elem.setAttributeNS(WSConstants.XMLNS_NS, "xmlns", "");
393 elem.setAttributeNS(null, "ValueType", X509Security.getType(WSSConfig.getDefaultWSConfig()));
394 Text certText = doc.createTextNode(Base64.encode(data, 0));
395 elem.appendChild(certText);
396 return elem;
397 }
398 }