1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.wss4j.dom.message;
21
22 import java.io.IOException;
23 import java.util.Iterator;
24 import java.util.LinkedList;
25 import java.util.List;
26
27 import javax.xml.namespace.QName;
28 import javax.xml.transform.TransformerException;
29
30 import org.apache.wss4j.common.util.XMLUtils;
31
32
33 import org.w3c.dom.Document;
34 import org.w3c.dom.Element;
35 import org.w3c.dom.Node;
36 import org.w3c.dom.NodeList;
37
38
39
40
41
42 public class TestMessageTransformer {
43 private static final org.slf4j.Logger LOG = org.slf4j.LoggerFactory.getLogger(TestMessageTransformer.class);
44
45 public static Element duplicateEncryptedDataInWsseHeader(Element saaj, boolean moveReferenceList) throws TransformerException, IOException {
46 if (moveReferenceList) {
47 moveReferenceList(saaj);
48 }
49 Element body = getFirstChildElement(saaj, new QName("http://schemas.xmlsoap.org/soap/envelope/",
50 "Body"), true);
51 Element encData = getFirstChildElement(body, new QName("http://www.w3.org/2001/04/xmlenc#",
52 "EncryptedData"), true);
53 Element newEncData = createNewEncryptedData(encData);
54 Element sh = getFirstChildElement(saaj, new QName("http://schemas.xmlsoap.org/soap/envelope/",
55 "Header"), true);
56 Element wsseHeader = getFirstChildElement(sh,
57 new QName(
58 "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd",
59 "Security"), true);
60
61 Node newWsseHeader = wsseHeader.cloneNode(false);
62 Node cur = wsseHeader.getFirstChild();
63
64 String newId = newEncData.getAttributeNS(null, "Id");
65 while (cur != null) {
66 cur = copyHeadersAndUpdateRefList(cur, newWsseHeader, newId);
67 }
68 newWsseHeader.appendChild(newEncData);
69
70 if (!moveReferenceList) {
71 updateEncryptedKeyRefList(newWsseHeader, newId);
72 }
73
74 Node parent = wsseHeader.getParentNode();
75 parent.removeChild(wsseHeader);
76 parent.appendChild(newWsseHeader);
77 print(saaj.getOwnerDocument());
78 return newEncData;
79 }
80
81 public static Element duplicateEncryptedDataInWsseWrapperHeader(Element saaj, boolean moveReferenceList) throws TransformerException, IOException {
82 if (moveReferenceList) {
83 moveReferenceList(saaj);
84 }
85 Element body = getFirstChildElement(saaj, new QName("http://schemas.xmlsoap.org/soap/envelope/",
86 "Body"), true);
87 Element encData = getFirstChildElement(body, new QName("http://www.w3.org/2001/04/xmlenc#",
88 "EncryptedData"), true);
89 Element newEncData = createNewEncryptedData(encData);
90 Element sh = getFirstChildElement(saaj, new QName("http://schemas.xmlsoap.org/soap/envelope/",
91 "Header"), true);
92 Element signature = getFirstChildElement(sh, new QName("http://www.w3.org/2000/09/xmldsig#",
93 "Signature"), true);
94
95 Node wsseHeader = signature.getParentNode();
96 Node newWsseHeader = wsseHeader.cloneNode(false);
97 Node cur = wsseHeader.getFirstChild();
98 String newId = newEncData.getAttributeNS(null, "Id");
99 while (!cur.isSameNode(signature)) {
100 cur = copyHeadersAndUpdateRefList(cur, newWsseHeader, newId);
101 }
102 Element wrapper = encData.getOwnerDocument().createElementNS(null, "a");
103 wrapper.appendChild(newEncData);
104 newWsseHeader.appendChild(wrapper);
105 while (cur != null) {
106 cur = copyHeadersAndUpdateRefList(cur, newWsseHeader, newId);
107 }
108
109 if (!moveReferenceList) {
110 updateEncryptedKeyRefList(newWsseHeader, newId);
111 }
112
113 Node parent = wsseHeader.getParentNode();
114 parent.removeChild(wsseHeader);
115 parent.appendChild(newWsseHeader);
116 print(saaj.getOwnerDocument());
117 return newEncData;
118 }
119
120 public static Element duplicateEncryptedDataInWrapperBody(Element saaj) throws TransformerException, IOException {
121 Element body = getFirstChildElement(saaj, new QName("http://schemas.xmlsoap.org/soap/envelope/",
122 "Body"), true);
123 Element encData = getFirstChildElement(body, new QName("http://www.w3.org/2001/04/xmlenc#",
124 "EncryptedData"), true);
125 Element newEncData = createNewEncryptedData(encData);
126 Element sh = getFirstChildElement(saaj, new QName("http://schemas.xmlsoap.org/soap/envelope/",
127 "Header"), true);
128 Element signature = getFirstChildElement(sh, new QName("http://www.w3.org/2000/09/xmldsig#",
129 "Signature"), true);
130
131 Node wsseHeader = signature.getParentNode();
132 Node newWsseHeader = wsseHeader.cloneNode(false);
133 Node cur = wsseHeader.getFirstChild();
134 String newId = newEncData.getAttributeNS(null, "Id");
135 while (!cur.isSameNode(signature)) {
136 cur = copyHeadersAndUpdateRefList(cur, newWsseHeader, newId);
137 }
138 Element wrapper = encData.getOwnerDocument().createElementNS(null, "a");
139 wrapper.appendChild(newEncData);
140
141 body.appendChild(wrapper);
142 while (cur != null) {
143 cur = copyHeadersAndUpdateRefList(cur, newWsseHeader, newId);
144 }
145
146 updateEncryptedKeyRefList(newWsseHeader, newId);
147
148 Node parent = wsseHeader.getParentNode();
149 parent.removeChild(wsseHeader);
150 parent.appendChild(newWsseHeader);
151 print(saaj.getOwnerDocument());
152 return newEncData;
153 }
154
155 public static Element duplicateEncryptedDataAfterWrapperBody(Element saaj) throws TransformerException, IOException {
156 Element body = getFirstChildElement(saaj, new QName("http://schemas.xmlsoap.org/soap/envelope/",
157 "Body"), true);
158 Element encData = getFirstChildElement(body, new QName("http://www.w3.org/2001/04/xmlenc#",
159 "EncryptedData"), true);
160 Element newEncData = createNewEncryptedData(encData);
161 Element sh = getFirstChildElement(saaj, new QName("http://schemas.xmlsoap.org/soap/envelope/",
162 "Header"), true);
163 Element signature = getFirstChildElement(sh, new QName("http://www.w3.org/2000/09/xmldsig#",
164 "Signature"), true);
165
166 Node wsseHeader = signature.getParentNode();
167 Node newWsseHeader = wsseHeader.cloneNode(false);
168 Node cur = wsseHeader.getFirstChild();
169 String newId = newEncData.getAttributeNS(null, "Id");
170 while (!cur.isSameNode(signature)) {
171 cur = copyHeadersAndUpdateRefList(cur, newWsseHeader, newId);
172 }
173 Element wrapper = encData.getOwnerDocument().createElementNS(null, "a");
174 Node clonedBody = body.cloneNode(false);
175 clonedBody.appendChild(newEncData);
176 wrapper.appendChild(clonedBody);
177
178 body.getParentNode().appendChild(wrapper);
179 while (cur != null) {
180 cur = copyHeadersAndUpdateRefList(cur, newWsseHeader, newId);
181 }
182
183 updateEncryptedKeyRefList(newWsseHeader, newId);
184
185 Node parent = wsseHeader.getParentNode();
186 parent.removeChild(wsseHeader);
187 parent.appendChild(newWsseHeader);
188 print(saaj.getOwnerDocument());
189 return newEncData;
190 }
191
192 public static Element duplicateEncryptedDataInExternalWrapperElement(Element saaj,
193 boolean moveReferenceList) throws TransformerException, IOException {
194 if (moveReferenceList) {
195 moveReferenceList(saaj);
196 }
197 Element body = getFirstChildElement(saaj, new QName("http://schemas.xmlsoap.org/soap/envelope/",
198 "Body"), true);
199 Element encData = getFirstChildElement(body, new QName("http://www.w3.org/2001/04/xmlenc#",
200 "EncryptedData"), true);
201 Element newEncData = createNewEncryptedData(encData);
202 Element sh = getFirstChildElement(saaj, new QName("http://schemas.xmlsoap.org/soap/envelope/",
203 "Header"), true);
204 Element wsseHeader = getFirstChildElement(sh,
205 new QName(
206 "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd",
207 "Security"), true);
208
209 Node newWsseHeader = wsseHeader.cloneNode(false);
210 Node cur = wsseHeader.getFirstChild();
211 String newId = newEncData.getAttributeNS(null, "Id");
212 while (cur != null) {
213 cur = copyHeadersAndUpdateRefList(cur, newWsseHeader, newId);
214 }
215 sh.removeChild(wsseHeader);
216 sh.appendChild(newWsseHeader);
217
218 if (!moveReferenceList) {
219 updateEncryptedKeyRefList(newWsseHeader, newId);
220 }
221
222 Element wrapper = encData.getOwnerDocument().createElementNS(null, "a");
223 wrapper.setAttributeNS("http://schemas.xmlsoap.org/soap/envelope/", "mustUnderstand", "0");
224 wrapper.setAttributeNS("http://schemas.xmlsoap.org/soap/envelope/", "actor", "foo");
225 wrapper.appendChild(newEncData);
226 sh.appendChild(wrapper);
227 print(saaj.getOwnerDocument());
228 return newEncData;
229 }
230
231 public static Element addEncryptedDataWithEmbeddedEncryptedKeyInWsseHeader(Element saaj) throws TransformerException, IOException {
232 moveReferenceList(saaj);
233 Element body = getFirstChildElement(saaj, new QName("http://schemas.xmlsoap.org/soap/envelope/",
234 "Body"), true);
235 Element encData = getFirstChildElement(body, new QName("http://www.w3.org/2001/04/xmlenc#",
236 "EncryptedData"), true);
237
238 Element newEncData = (Element)encData.cloneNode(true);
239 String newId = newEncData.getAttributeNS(null, "Id") + "b";
240 newEncData.setAttributeNS(null, "Id", newId);
241
242 Element encKey = getFirstChildElement(saaj, new QName("http://www.w3.org/2001/04/xmlenc#",
243 "EncryptedKey"), true);
244 Element newEncKey = (Element)encKey.cloneNode(true);
245 String newEcId = newEncKey.getAttributeNS(null, "Id") + "b";
246 newEncKey.setAttributeNS(null, "Id", newEcId);
247
248 Element keyInfo = getFirstChildElement(newEncData, new QName("http://www.w3.org/2000/09/xmldsig#",
249 "KeyInfo"), true);
250 Element str = getFirstChildElement(newEncData,
251 new QName(
252 "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd",
253 "SecurityTokenReference"), true);
254 keyInfo.replaceChild(newEncKey, str);
255
256 Element wsseHeader = getFirstChildElement(saaj,
257 new QName(
258 "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd",
259 "Security"), true);
260
261 Node newWsseHeader = wsseHeader.cloneNode(false);
262 Node cur = wsseHeader.getFirstChild();
263
264 while (cur != null) {
265 cur = copyHeadersAndUpdateRefList(cur, newWsseHeader, newId);
266 }
267 newWsseHeader.appendChild(newEncData);
268
269 Node parent = wsseHeader.getParentNode();
270 parent.removeChild(wsseHeader);
271 parent.appendChild(newWsseHeader);
272 print(saaj.getOwnerDocument());
273 return newEncData;
274
275 }
276
277 private static void moveReferenceList(Element saaj) {
278 Element sh = getFirstChildElement(saaj, new QName("http://schemas.xmlsoap.org/soap/envelope/",
279 "Header"), true);
280 Element encKey = getFirstChildElement(sh, new QName("http://www.w3.org/2001/04/xmlenc#",
281 "EncryptedKey"), true);
282 Element refList = getFirstChildElement(encKey, new QName("http://www.w3.org/2001/04/xmlenc#",
283 "ReferenceList"), true);
284
285 Node wsseHeader = encKey.getParentNode();
286 encKey.removeChild(refList);
287 wsseHeader.appendChild(refList);
288 }
289
290 private static void updateEncryptedKeyRefList(Node wsseHeader, String newId) {
291 Element encryptedKey = getFirstChildElement(wsseHeader,
292 new QName("http://www.w3.org/2001/04/xmlenc#",
293 "EncryptedKey"), true);
294 Element ref = getFirstChildElement(encryptedKey, new QName("http://www.w3.org/2001/04/xmlenc#",
295 "DataReference"), true);
296 Element newRef = (Element)ref.cloneNode(true);
297 newRef.setAttributeNS(null, "URI", "#" + newId);
298 ref.getParentNode().appendChild(newRef);
299 }
300
301 private static void print(Document doc) throws TransformerException, IOException {
302 if (LOG.isDebugEnabled()) {
303 LOG.debug("After transformation....");
304 String outputString = XMLUtils.prettyDocumentToString(doc);
305 LOG.debug(outputString);
306 }
307 }
308
309 private static Element createNewEncryptedData(Element encData) {
310 Element newEncData = (Element)encData.cloneNode(true);
311 String id = newEncData.getAttributeNS(null, "Id");
312 String newId = id + "b";
313 newEncData.setAttributeNS(null, "Id", newId);
314 return newEncData;
315 }
316
317 private static Node copyHeadersAndUpdateRefList(Node cur, Node dest, String newId) {
318 Node temp = cur.cloneNode(true);
319 dest.appendChild(temp);
320 if (newId != null && temp.getNodeType() == Node.ELEMENT_NODE) {
321 Element t = (Element)temp;
322 if (t.getLocalName().equals("ReferenceList")) {
323 Element ref = getFirstChildElement(t, new QName("http://www.w3.org/2001/04/xmlenc#",
324 "DataReference"), true);
325 Element newRef = (Element)ref.cloneNode(true);
326 newRef.setAttributeNS(null, "URI", "#" + newId);
327 t.appendChild(newRef);
328 }
329 }
330 return cur.getNextSibling();
331 }
332
333 private static Element getFirstChildElement(Node node, QName nodeName, boolean recursive) {
334 Element childElement = null;
335 Iterator<Element> it = getChildElements(node, nodeName, recursive).iterator();
336 if (it.hasNext()) {
337 childElement = it.next();
338 }
339 return childElement;
340 }
341
342 private static List<Element> getChildElements(Node node, QName nodeName, boolean recursive) {
343 List<Element> list = new LinkedList<>();
344
345 NodeList nlist = node.getChildNodes();
346 int len = nlist.getLength();
347 for (int i = 0; i < len; i++) {
348 Node child = nlist.item(i);
349 if (child.getNodeType() == Node.ELEMENT_NODE) {
350 search(list, (Element)child, nodeName, recursive);
351 }
352 }
353 return list;
354 }
355
356 private static void search(List<Element> list, Element baseElement, QName nodeName, boolean recursive) {
357 if (nodeName == null) {
358 list.add(baseElement);
359 } else {
360 QName qname;
361 if (nodeName.getNamespaceURI().length() > 0) {
362 qname = new QName(baseElement.getNamespaceURI(), baseElement.getLocalName());
363 } else {
364 qname = new QName(baseElement.getLocalName());
365 }
366 if (qname.equals(nodeName)) {
367 list.add(baseElement);
368 }
369 }
370 if (recursive) {
371 NodeList nlist = baseElement.getChildNodes();
372 int len = nlist.getLength();
373 for (int i = 0; i < len; i++) {
374 Node child = nlist.item(i);
375 if (child.getNodeType() == Node.ELEMENT_NODE) {
376 search(list, (Element)child, nodeName, recursive);
377 }
378 }
379 }
380 }
381
382 }