1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.wss4j.stax.test;
20
21 import java.io.ByteArrayInputStream;
22 import java.io.ByteArrayOutputStream;
23 import java.io.IOException;
24 import java.io.InputStream;
25 import java.io.PushbackInputStream;
26 import java.nio.charset.StandardCharsets;
27 import java.util.ArrayList;
28 import java.util.Arrays;
29 import java.util.Collections;
30 import java.util.HashMap;
31 import java.util.List;
32 import java.util.Map;
33 import java.util.UUID;
34
35 import javax.crypto.KeyGenerator;
36 import javax.crypto.SecretKey;
37 import javax.security.auth.callback.Callback;
38 import javax.security.auth.callback.CallbackHandler;
39 import javax.security.auth.callback.UnsupportedCallbackException;
40 import javax.xml.namespace.QName;
41 import javax.xml.stream.XMLStreamException;
42 import javax.xml.stream.XMLStreamReader;
43 import javax.xml.stream.XMLStreamWriter;
44 import javax.xml.transform.dom.DOMSource;
45 import javax.xml.transform.stream.StreamResult;
46
47 import org.apache.wss4j.common.WSEncryptionPart;
48 import org.apache.wss4j.common.crypto.CryptoFactory;
49 import org.apache.wss4j.common.ext.Attachment;
50 import org.apache.wss4j.common.ext.AttachmentRequestCallback;
51 import org.apache.wss4j.common.ext.AttachmentResultCallback;
52 import org.apache.wss4j.common.ext.WSSecurityException;
53 import org.apache.wss4j.common.util.AttachmentUtils;
54 import org.apache.wss4j.common.util.KeyUtils;
55 import org.apache.wss4j.common.util.SOAPUtil;
56 import org.apache.wss4j.dom.WSConstants;
57 import org.apache.wss4j.dom.message.WSSecEncrypt;
58 import org.apache.wss4j.dom.message.WSSecHeader;
59 import org.apache.wss4j.stax.ext.WSSConstants;
60 import org.apache.wss4j.stax.ext.WSSSecurityProperties;
61 import org.apache.wss4j.stax.setup.InboundWSSec;
62 import org.apache.wss4j.stax.setup.OutboundWSSec;
63 import org.apache.wss4j.stax.setup.WSSec;
64 import org.apache.wss4j.stax.test.utils.StAX2DOM;
65 import org.apache.wss4j.stax.test.utils.XmlReaderToWriter;
66 import org.apache.xml.security.exceptions.XMLSecurityException;
67 import org.apache.xml.security.stax.ext.SecurePart;
68 import org.apache.xml.security.stax.securityEvent.SecurityEvent;
69 import org.junit.jupiter.api.Test;
70 import org.w3c.dom.Document;
71 import org.w3c.dom.Element;
72 import org.w3c.dom.NodeList;
73
74 import static org.junit.jupiter.api.Assertions.assertEquals;
75 import static org.junit.jupiter.api.Assertions.assertFalse;
76 import static org.junit.jupiter.api.Assertions.assertNotNull;
77 import static org.junit.jupiter.api.Assertions.assertTrue;
78 import static org.junit.jupiter.api.Assertions.fail;
79 import static org.junit.jupiter.api.Assumptions.assumeFalse;
80
81 public class AttachmentTest extends AbstractTestBase {
82
83 private boolean isIBMJdK = System.getProperty("java.vendor").contains("IBM");
84
85 public AttachmentTest() throws Exception {
86 }
87
88 protected Map<String, String> getHeaders(String attachmentId) {
89 Map<String, String> headers = new HashMap<>();
90 headers.put(AttachmentUtils.MIME_HEADER_CONTENT_DESCRIPTION, "Attachment");
91 headers.put(AttachmentUtils.MIME_HEADER_CONTENT_DISPOSITION, "attachment; filename=\"fname.ext\"");
92 headers.put(AttachmentUtils.MIME_HEADER_CONTENT_ID, "<attachment=" + attachmentId + ">");
93 headers.put(AttachmentUtils.MIME_HEADER_CONTENT_LOCATION, "http://ws.apache.org");
94 headers.put(AttachmentUtils.MIME_HEADER_CONTENT_TYPE, "text/xml; charset=UTF-8");
95 headers.put("TestHeader", "testHeaderValue");
96 return headers;
97 }
98
99 protected byte[] readInputStream(InputStream inputStream) throws IOException {
100 ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
101 int read = 0;
102 byte[] buf = new byte[4096];
103 while ((read = inputStream.read(buf)) != -1) {
104 byteArrayOutputStream.write(buf, 0, read);
105 }
106 return byteArrayOutputStream.toByteArray();
107 }
108
109 @Test
110 public void testXMLAttachmentContentSignature() throws Exception {
111
112 final String attachmentId = UUID.randomUUID().toString();
113 final Attachment attachment = new Attachment();
114 attachment.setMimeType("text/xml");
115 attachment.addHeaders(getHeaders(attachmentId));
116 attachment.setId(attachmentId);
117 attachment.setSourceStream(new ByteArrayInputStream(SOAPUtil.SAMPLE_SOAP_MSG.getBytes(StandardCharsets.UTF_8)));
118
119 ByteArrayOutputStream baos = new ByteArrayOutputStream();
120 {
121 WSSSecurityProperties securityProperties = new WSSSecurityProperties();
122 List<WSSConstants.Action> actions = new ArrayList<>();
123 actions.add(WSSConstants.SIGNATURE);
124 securityProperties.setActions(actions);
125 securityProperties.loadSignatureKeyStore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
126 securityProperties.setSignatureUser("transmitter");
127 securityProperties.addSignaturePart(new SecurePart(new QName("http://schemas.xmlsoap.org/soap/envelope/", "Body"), SecurePart.Modifier.Element));
128 securityProperties.addSignaturePart(new SecurePart("cid:Attachments", SecurePart.Modifier.Content));
129 securityProperties.setCallbackHandler(new CallbackHandlerImpl());
130
131 AttachmentCallbackHandler attachmentCallbackHandler =
132 new AttachmentCallbackHandler(Collections.singletonList(attachment));
133 securityProperties.setAttachmentCallbackHandler(attachmentCallbackHandler);
134
135 OutboundWSSec wsSecOut = WSSec.getOutboundWSSec(securityProperties);
136 XMLStreamWriter xmlStreamWriter = wsSecOut.processOutMessage(baos, StandardCharsets.UTF_8.name(), new ArrayList<SecurityEvent>());
137 XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml"));
138 XmlReaderToWriter.writeAll(xmlStreamReader, xmlStreamWriter);
139 xmlStreamWriter.close();
140 }
141
142
143 AttachmentCallbackHandler attachmentCallbackHandler =
144 new AttachmentCallbackHandler(Collections.singletonList(attachment));
145 {
146 WSSSecurityProperties securityProperties = new WSSSecurityProperties();
147 securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
148 securityProperties.setAttachmentCallbackHandler(attachmentCallbackHandler);
149
150 InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
151 XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
152 Document document = StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
153
154 NodeList sigReferences = document.getElementsByTagNameNS(WSConstants.SIG_NS, "Reference");
155 assertEquals(2, sigReferences.getLength());
156 }
157 assertFalse(attachmentCallbackHandler.getResponseAttachments().isEmpty());
158 Attachment responseAttachment = attachmentCallbackHandler.getResponseAttachments().get(0);
159
160 byte[] attachmentBytes = readInputStream(responseAttachment.getSourceStream());
161 assertTrue(Arrays.equals(attachmentBytes, SOAPUtil.SAMPLE_SOAP_MSG.getBytes(StandardCharsets.UTF_8)));
162 assertEquals("text/xml", responseAttachment.getMimeType());
163 }
164
165 @Test
166 public void testInvalidXMLAttachmentContentSignature() throws Exception {
167
168 final String attachmentId = UUID.randomUUID().toString();
169 final Attachment attachment = new Attachment();
170 attachment.setMimeType("text/xml");
171 attachment.addHeaders(getHeaders(attachmentId));
172 attachment.setId(attachmentId);
173 attachment.setSourceStream(new ByteArrayInputStream(SOAPUtil.SAMPLE_SOAP_MSG.getBytes(StandardCharsets.UTF_8)));
174
175 ByteArrayOutputStream baos = new ByteArrayOutputStream();
176 {
177 WSSSecurityProperties securityProperties = new WSSSecurityProperties();
178 List<WSSConstants.Action> actions = new ArrayList<>();
179 actions.add(WSSConstants.SIGNATURE);
180 securityProperties.setActions(actions);
181 securityProperties.loadSignatureKeyStore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
182 securityProperties.setSignatureUser("transmitter");
183 securityProperties.addSignaturePart(new SecurePart(new QName("http://schemas.xmlsoap.org/soap/envelope/", "Body"), SecurePart.Modifier.Element));
184 securityProperties.addSignaturePart(new SecurePart("cid:Attachments", SecurePart.Modifier.Content));
185 securityProperties.setCallbackHandler(new CallbackHandlerImpl());
186
187 AttachmentCallbackHandler attachmentCallbackHandler =
188 new AttachmentCallbackHandler(Collections.singletonList(attachment));
189 securityProperties.setAttachmentCallbackHandler(attachmentCallbackHandler);
190
191 OutboundWSSec wsSecOut = WSSec.getOutboundWSSec(securityProperties);
192 XMLStreamWriter xmlStreamWriter = wsSecOut.processOutMessage(baos, StandardCharsets.UTF_8.name(), new ArrayList<SecurityEvent>());
193 XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml"));
194 XmlReaderToWriter.writeAll(xmlStreamReader, xmlStreamWriter);
195 xmlStreamWriter.close();
196 }
197
198
199 {
200 WSSSecurityProperties securityProperties = new WSSSecurityProperties();
201 securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
202 securityProperties.setAttachmentCallbackHandler(new CallbackHandler() {
203 @Override
204 public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
205 if (callbacks[0] instanceof AttachmentRequestCallback) {
206 AttachmentRequestCallback attachmentRequestCallback = (AttachmentRequestCallback) callbacks[0];
207
208 if (!attachment.getId().equals(attachmentRequestCallback.getAttachmentId())) {
209 throw new RuntimeException("wrong attachment requested");
210 }
211
212 List<Attachment> attachments = new ArrayList<>();
213 attachment.setSourceStream(new ByteArrayInputStream(
214 SOAPUtil.SAMPLE_SOAP_MSG.replace("15", "16").getBytes(StandardCharsets.UTF_8)));
215 attachments.add(attachment);
216 attachmentRequestCallback.setAttachments(attachments);
217 }
218 }
219 });
220
221 InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
222 XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
223 try {
224 StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
225 fail("Exception expected");
226 } catch (XMLStreamException e) {
227 assertTrue(e.getCause() instanceof XMLSecurityException);
228 assertTrue(e.getCause().getMessage().startsWith("Invalid digest of reference cid:"));
229 }
230 }
231 }
232
233 @Test
234 public void testXMLAttachmentCompleteSignature() throws Exception {
235
236 final String attachmentId = UUID.randomUUID().toString();
237 final Attachment attachment = new Attachment();
238 attachment.setMimeType("text/xml");
239 attachment.addHeaders(getHeaders(attachmentId));
240 attachment.setId(attachmentId);
241 attachment.setSourceStream(new ByteArrayInputStream(SOAPUtil.SAMPLE_SOAP_MSG.getBytes(StandardCharsets.UTF_8)));
242
243 ByteArrayOutputStream baos = new ByteArrayOutputStream();
244 {
245 WSSSecurityProperties securityProperties = new WSSSecurityProperties();
246 List<WSSConstants.Action> actions = new ArrayList<>();
247 actions.add(WSSConstants.SIGNATURE);
248 securityProperties.setActions(actions);
249 securityProperties.loadSignatureKeyStore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
250 securityProperties.setSignatureUser("transmitter");
251 securityProperties.addSignaturePart(new SecurePart(new QName("http://schemas.xmlsoap.org/soap/envelope/", "Body"), SecurePart.Modifier.Element));
252 securityProperties.addSignaturePart(new SecurePart("cid:Attachments", SecurePart.Modifier.Element));
253 securityProperties.setCallbackHandler(new CallbackHandlerImpl());
254
255 AttachmentCallbackHandler attachmentCallbackHandler =
256 new AttachmentCallbackHandler(Collections.singletonList(attachment));
257 securityProperties.setAttachmentCallbackHandler(attachmentCallbackHandler);
258
259 OutboundWSSec wsSecOut = WSSec.getOutboundWSSec(securityProperties);
260 XMLStreamWriter xmlStreamWriter = wsSecOut.processOutMessage(baos, StandardCharsets.UTF_8.name(), new ArrayList<SecurityEvent>());
261 XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml"));
262 XmlReaderToWriter.writeAll(xmlStreamReader, xmlStreamWriter);
263 xmlStreamWriter.close();
264 }
265
266
267 AttachmentCallbackHandler attachmentCallbackHandler =
268 new AttachmentCallbackHandler(Collections.singletonList(attachment));
269 {
270 WSSSecurityProperties securityProperties = new WSSSecurityProperties();
271 securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
272 securityProperties.setAttachmentCallbackHandler(attachmentCallbackHandler);
273
274 InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
275 XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
276 Document document = StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
277
278 NodeList sigReferences = document.getElementsByTagNameNS(WSConstants.SIG_NS, "Reference");
279 assertEquals(2, sigReferences.getLength());
280 }
281
282 assertFalse(attachmentCallbackHandler.getResponseAttachments().isEmpty());
283 Attachment responseAttachment = attachmentCallbackHandler.getResponseAttachments().get(0);
284
285 byte[] attachmentBytes = readInputStream(responseAttachment.getSourceStream());
286 assertTrue(Arrays.equals(attachmentBytes, SOAPUtil.SAMPLE_SOAP_MSG.getBytes(StandardCharsets.UTF_8)));
287 assertEquals("text/xml", responseAttachment.getMimeType());
288 }
289
290 @Test
291 public void testInvalidXMLAttachmentCompleteSignature() throws Exception {
292
293 final String attachmentId = UUID.randomUUID().toString();
294 final Attachment attachment = new Attachment();
295 attachment.setMimeType("text/xml");
296 attachment.addHeaders(getHeaders(attachmentId));
297 attachment.setId(attachmentId);
298 attachment.setSourceStream(new ByteArrayInputStream(SOAPUtil.SAMPLE_SOAP_MSG.getBytes(StandardCharsets.UTF_8)));
299
300 ByteArrayOutputStream baos = new ByteArrayOutputStream();
301 {
302 WSSSecurityProperties securityProperties = new WSSSecurityProperties();
303 List<WSSConstants.Action> actions = new ArrayList<>();
304 actions.add(WSSConstants.SIGNATURE);
305 securityProperties.setActions(actions);
306 securityProperties.loadSignatureKeyStore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
307 securityProperties.setSignatureUser("transmitter");
308 securityProperties.addSignaturePart(new SecurePart(new QName("http://schemas.xmlsoap.org/soap/envelope/", "Body"), SecurePart.Modifier.Element));
309 securityProperties.addSignaturePart(new SecurePart("cid:Attachments", SecurePart.Modifier.Element));
310 securityProperties.setCallbackHandler(new CallbackHandlerImpl());
311
312 AttachmentCallbackHandler attachmentCallbackHandler =
313 new AttachmentCallbackHandler(Collections.singletonList(attachment));
314 securityProperties.setAttachmentCallbackHandler(attachmentCallbackHandler);
315
316 OutboundWSSec wsSecOut = WSSec.getOutboundWSSec(securityProperties);
317 XMLStreamWriter xmlStreamWriter = wsSecOut.processOutMessage(baos, StandardCharsets.UTF_8.name(), new ArrayList<SecurityEvent>());
318 XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml"));
319 XmlReaderToWriter.writeAll(xmlStreamReader, xmlStreamWriter);
320 xmlStreamWriter.close();
321 }
322
323
324 {
325 attachment.addHeader(AttachmentUtils.MIME_HEADER_CONTENT_DESCRIPTION, "Kaputt");
326
327 WSSSecurityProperties securityProperties = new WSSSecurityProperties();
328 securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
329 securityProperties.setAttachmentCallbackHandler(new CallbackHandler() {
330 @Override
331 public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
332 if (callbacks[0] instanceof AttachmentRequestCallback) {
333 AttachmentRequestCallback attachmentRequestCallback = (AttachmentRequestCallback) callbacks[0];
334
335 if (!attachment.getId().equals(attachmentRequestCallback.getAttachmentId())) {
336 throw new RuntimeException("wrong attachment requested");
337 }
338
339 List<Attachment> attachments = new ArrayList<>();
340 attachments.add(attachment);
341 attachmentRequestCallback.setAttachments(attachments);
342 }
343 }
344 });
345
346 InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
347 XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
348 try {
349 StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
350 fail("Exception expected");
351 } catch (XMLStreamException e) {
352 assertTrue(e.getCause() instanceof XMLSecurityException);
353 assertTrue(e.getCause().getMessage().startsWith("Invalid digest of reference cid:"));
354 }
355 }
356 }
357
358 @Test
359 public void testMultipleAttachmentCompleteSignature() throws Exception {
360
361 final String attachment1Id = UUID.randomUUID().toString();
362 final Attachment[] attachment = new Attachment[2];
363 attachment[0] = new Attachment();
364 attachment[0].setMimeType("text/xml");
365 attachment[0].addHeaders(getHeaders(attachment1Id));
366 attachment[0].setId(attachment1Id);
367 attachment[0].setSourceStream(new ByteArrayInputStream(SOAPUtil.SAMPLE_SOAP_MSG.getBytes(StandardCharsets.UTF_8)));
368
369 final String attachment2Id = UUID.randomUUID().toString();
370 attachment[1] = new Attachment();
371 attachment[1].setMimeType("text/plain");
372 attachment[1].addHeaders(getHeaders(attachment2Id));
373 attachment[1].setId(attachment2Id);
374 attachment[1].setSourceStream(new ByteArrayInputStream(SOAPUtil.SAMPLE_SOAP_MSG.getBytes(StandardCharsets.UTF_8)));
375
376 ByteArrayOutputStream baos = new ByteArrayOutputStream();
377 {
378 WSSSecurityProperties securityProperties = new WSSSecurityProperties();
379 List<WSSConstants.Action> actions = new ArrayList<>();
380 actions.add(WSSConstants.SIGNATURE);
381 securityProperties.setActions(actions);
382 securityProperties.loadSignatureKeyStore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
383 securityProperties.setSignatureUser("transmitter");
384 securityProperties.addSignaturePart(new SecurePart(new QName("http://schemas.xmlsoap.org/soap/envelope/", "Body"), SecurePart.Modifier.Element));
385 securityProperties.addSignaturePart(new SecurePart("cid:Attachments", SecurePart.Modifier.Element));
386 securityProperties.setCallbackHandler(new CallbackHandlerImpl());
387
388 AttachmentCallbackHandler attachmentCallbackHandler =
389 new AttachmentCallbackHandler(Arrays.asList(attachment));
390 securityProperties.setAttachmentCallbackHandler(attachmentCallbackHandler);
391
392 OutboundWSSec wsSecOut = WSSec.getOutboundWSSec(securityProperties);
393 XMLStreamWriter xmlStreamWriter = wsSecOut.processOutMessage(baos, StandardCharsets.UTF_8.name(), new ArrayList<SecurityEvent>());
394 XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml"));
395 XmlReaderToWriter.writeAll(xmlStreamReader, xmlStreamWriter);
396 xmlStreamWriter.close();
397 }
398
399
400 AttachmentCallbackHandler attachmentCallbackHandler =
401 new AttachmentCallbackHandler(Arrays.asList(attachment));
402 {
403 WSSSecurityProperties securityProperties = new WSSSecurityProperties();
404 securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
405 securityProperties.setAttachmentCallbackHandler(attachmentCallbackHandler);
406
407 InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
408 XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
409 Document document = StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
410
411 NodeList sigReferences = document.getElementsByTagNameNS(WSConstants.SIG_NS, "Reference");
412 assertEquals(3, sigReferences.getLength());
413 }
414
415 assertFalse(attachmentCallbackHandler.getResponseAttachments().isEmpty());
416 Attachment responseAttachment = attachmentCallbackHandler.getResponseAttachments().get(0);
417
418 byte[] attachmentBytes = readInputStream(responseAttachment.getSourceStream());
419 assertTrue(Arrays.equals(attachmentBytes, SOAPUtil.SAMPLE_SOAP_MSG.getBytes(StandardCharsets.UTF_8)));
420 assertEquals("text/xml", responseAttachment.getMimeType());
421 }
422
423 @Test
424 public void testXMLAttachmentContentEncryption() throws Exception {
425
426 final String attachmentId = UUID.randomUUID().toString();
427 final Attachment attachment = new Attachment();
428 attachment.setMimeType("text/xml");
429 attachment.addHeaders(getHeaders(attachmentId));
430 attachment.setId(attachmentId);
431 attachment.setSourceStream(new ByteArrayInputStream(SOAPUtil.SAMPLE_SOAP_MSG.getBytes(StandardCharsets.UTF_8)));
432 AttachmentCallbackHandler attachmentCallbackHandler =
433 new AttachmentCallbackHandler(Collections.singletonList(attachment));
434 List<Attachment> encryptedAttachments = attachmentCallbackHandler.getResponseAttachments();
435
436 ByteArrayOutputStream baos = new ByteArrayOutputStream();
437 {
438 WSSSecurityProperties securityProperties = new WSSSecurityProperties();
439 List<WSSConstants.Action> actions = new ArrayList<>();
440 actions.add(WSSConstants.ENCRYPTION);
441 securityProperties.setActions(actions);
442 securityProperties.loadEncryptionKeystore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
443 securityProperties.setEncryptionUser("receiver");
444 securityProperties.addEncryptionPart(new SecurePart(new QName("http://schemas.xmlsoap.org/soap/envelope/", "Body"), SecurePart.Modifier.Content));
445 securityProperties.addEncryptionPart(new SecurePart("cid:Attachments", SecurePart.Modifier.Content));
446 securityProperties.setAttachmentCallbackHandler(attachmentCallbackHandler);
447
448 OutboundWSSec wsSecOut = WSSec.getOutboundWSSec(securityProperties);
449 XMLStreamWriter xmlStreamWriter = wsSecOut.processOutMessage(baos, StandardCharsets.UTF_8.name(), new ArrayList<SecurityEvent>());
450 XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml"));
451 XmlReaderToWriter.writeAll(xmlStreamReader, xmlStreamWriter);
452 xmlStreamWriter.close();
453
454 Document securedDoc = documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray()));
455
456 NodeList references = securedDoc.getElementsByTagNameNS(WSConstants.ENC_NS, "DataReference");
457 assertEquals(2, references.getLength());
458 NodeList cipherReferences = securedDoc.getElementsByTagNameNS(WSConstants.ENC_NS, "CipherReference");
459 assertEquals(1, cipherReferences.getLength());
460 NodeList encDatas = securedDoc.getElementsByTagNameNS(WSConstants.ENC_NS, "EncryptedData");
461 assertEquals(2, encDatas.getLength());
462
463 NodeList securityHeaderElement = securedDoc.getElementsByTagNameNS(WSConstants.WSSE_NS, "Security");
464 assertEquals(1, securityHeaderElement.getLength());
465 NodeList childs = securityHeaderElement.item(0).getChildNodes();
466 assertEquals(2, childs.getLength());
467 assertEquals(childs.item(0).getLocalName(), "EncryptedKey");
468 assertEquals(childs.item(1).getLocalName(), "EncryptedData");
469 }
470
471 attachmentCallbackHandler = new AttachmentCallbackHandler(encryptedAttachments);
472 {
473 WSSSecurityProperties securityProperties = new WSSSecurityProperties();
474 securityProperties.loadDecryptionKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
475 securityProperties.setCallbackHandler(new CallbackHandlerImpl());
476 securityProperties.setAttachmentCallbackHandler(attachmentCallbackHandler);
477
478 InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
479 XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
480 StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
481 }
482
483 assertFalse(attachmentCallbackHandler.getResponseAttachments().isEmpty());
484 Attachment responseAttachment = attachmentCallbackHandler.getResponseAttachments().get(0);
485
486 byte[] attachmentBytes = readInputStream(responseAttachment.getSourceStream());
487 assertTrue(Arrays.equals(attachmentBytes, SOAPUtil.SAMPLE_SOAP_MSG.getBytes(StandardCharsets.UTF_8)));
488 assertEquals("text/xml", responseAttachment.getMimeType());
489
490 Map<String, String> attHeaders = responseAttachment.getHeaders();
491 assertEquals(6, attHeaders.size());
492 }
493
494 @Test
495 public void testXMLAttachmentContentEncryptionGCM() throws Exception {
496 assumeFalse(isIBMJdK);
497
498 final String attachmentId = UUID.randomUUID().toString();
499 final Attachment attachment = new Attachment();
500 attachment.setMimeType("text/xml");
501 attachment.addHeaders(getHeaders(attachmentId));
502 attachment.setId(attachmentId);
503 attachment.setSourceStream(new ByteArrayInputStream(SOAPUtil.SAMPLE_SOAP_MSG.getBytes(StandardCharsets.UTF_8)));
504 AttachmentCallbackHandler attachmentCallbackHandler =
505 new AttachmentCallbackHandler(Collections.singletonList(attachment));
506 List<Attachment> encryptedAttachments = attachmentCallbackHandler.getResponseAttachments();
507
508 ByteArrayOutputStream baos = new ByteArrayOutputStream();
509 {
510 WSSSecurityProperties securityProperties = new WSSSecurityProperties();
511 List<WSSConstants.Action> actions = new ArrayList<>();
512 actions.add(WSSConstants.ENCRYPTION);
513 securityProperties.setActions(actions);
514 securityProperties.loadEncryptionKeystore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
515 securityProperties.setEncryptionUser("receiver");
516 securityProperties.addEncryptionPart(new SecurePart(new QName("http://schemas.xmlsoap.org/soap/envelope/", "Body"), SecurePart.Modifier.Content));
517 securityProperties.addEncryptionPart(new SecurePart("cid:Attachments", SecurePart.Modifier.Content));
518 securityProperties.setAttachmentCallbackHandler(attachmentCallbackHandler);
519 securityProperties.setEncryptionSymAlgorithm(WSSConstants.NS_XENC11_AES128_GCM);
520
521 OutboundWSSec wsSecOut = WSSec.getOutboundWSSec(securityProperties);
522 XMLStreamWriter xmlStreamWriter = wsSecOut.processOutMessage(baos, StandardCharsets.UTF_8.name(), new ArrayList<SecurityEvent>());
523 XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml"));
524 XmlReaderToWriter.writeAll(xmlStreamReader, xmlStreamWriter);
525 xmlStreamWriter.close();
526
527 Document securedDoc = documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray()));
528
529 NodeList references = securedDoc.getElementsByTagNameNS(WSConstants.ENC_NS, "DataReference");
530 assertEquals(2, references.getLength());
531 NodeList cipherReferences = securedDoc.getElementsByTagNameNS(WSConstants.ENC_NS, "CipherReference");
532 assertEquals(1, cipherReferences.getLength());
533 NodeList encDatas = securedDoc.getElementsByTagNameNS(WSConstants.ENC_NS, "EncryptedData");
534 assertEquals(2, encDatas.getLength());
535
536 NodeList securityHeaderElement = securedDoc.getElementsByTagNameNS(WSConstants.WSSE_NS, "Security");
537 assertEquals(1, securityHeaderElement.getLength());
538 NodeList childs = securityHeaderElement.item(0).getChildNodes();
539 assertEquals(2, childs.getLength());
540 assertEquals(childs.item(0).getLocalName(), "EncryptedKey");
541 assertEquals(childs.item(1).getLocalName(), "EncryptedData");
542 }
543
544 attachmentCallbackHandler = new AttachmentCallbackHandler(encryptedAttachments);
545 {
546 WSSSecurityProperties securityProperties = new WSSSecurityProperties();
547 securityProperties.loadDecryptionKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
548 securityProperties.setCallbackHandler(new CallbackHandlerImpl());
549 securityProperties.setAttachmentCallbackHandler(attachmentCallbackHandler);
550
551 InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
552 XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
553 StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
554 }
555
556 assertFalse(attachmentCallbackHandler.getResponseAttachments().isEmpty());
557 Attachment responseAttachment = attachmentCallbackHandler.getResponseAttachments().get(0);
558
559 byte[] attachmentBytes = readInputStream(responseAttachment.getSourceStream());
560 assertTrue(Arrays.equals(attachmentBytes, SOAPUtil.SAMPLE_SOAP_MSG.getBytes(StandardCharsets.UTF_8)));
561 assertEquals("text/xml", responseAttachment.getMimeType());
562
563 Map<String, String> attHeaders = responseAttachment.getHeaders();
564 assertEquals(6, attHeaders.size());
565 }
566
567 @Test
568 public void testInvalidXMLAttachmentContentEncryption() throws Exception {
569 final String attachmentId = UUID.randomUUID().toString();
570 final Attachment attachment = new Attachment();
571 attachment.setMimeType("text/xml");
572 attachment.addHeaders(getHeaders(attachmentId));
573 attachment.setId(attachmentId);
574 attachment.setSourceStream(new ByteArrayInputStream(SOAPUtil.SAMPLE_SOAP_MSG.getBytes(StandardCharsets.UTF_8)));
575 AttachmentCallbackHandler attachmentCallbackHandler =
576 new AttachmentCallbackHandler(Collections.singletonList(attachment));
577 List<Attachment> encryptedAttachments = attachmentCallbackHandler.getResponseAttachments();
578
579 ByteArrayOutputStream baos = new ByteArrayOutputStream();
580 {
581 WSSSecurityProperties securityProperties = new WSSSecurityProperties();
582 List<WSSConstants.Action> actions = new ArrayList<>();
583 actions.add(WSSConstants.ENCRYPTION);
584 securityProperties.setActions(actions);
585 securityProperties.loadEncryptionKeystore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
586 securityProperties.setEncryptionUser("receiver");
587 securityProperties.addEncryptionPart(new SecurePart(new QName("http://schemas.xmlsoap.org/soap/envelope/", "Body"), SecurePart.Modifier.Content));
588 securityProperties.addEncryptionPart(new SecurePart("cid:Attachments", SecurePart.Modifier.Content));
589 securityProperties.setAttachmentCallbackHandler(attachmentCallbackHandler);
590
591 OutboundWSSec wsSecOut = WSSec.getOutboundWSSec(securityProperties);
592 XMLStreamWriter xmlStreamWriter = wsSecOut.processOutMessage(baos, StandardCharsets.UTF_8.name(), new ArrayList<SecurityEvent>());
593 XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml"));
594 XmlReaderToWriter.writeAll(xmlStreamReader, xmlStreamWriter);
595 xmlStreamWriter.close();
596
597 Document securedDoc = documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray()));
598
599 NodeList references = securedDoc.getElementsByTagNameNS(WSConstants.ENC_NS, "DataReference");
600 assertEquals(2, references.getLength());
601 NodeList cipherReferences = securedDoc.getElementsByTagNameNS(WSConstants.ENC_NS, "CipherReference");
602 assertEquals(1, cipherReferences.getLength());
603 NodeList encDatas = securedDoc.getElementsByTagNameNS(WSConstants.ENC_NS, "EncryptedData");
604 assertEquals(2, encDatas.getLength());
605
606 NodeList securityHeaderElement = securedDoc.getElementsByTagNameNS(WSConstants.WSSE_NS, "Security");
607 assertEquals(1, securityHeaderElement.getLength());
608 NodeList childs = securityHeaderElement.item(0).getChildNodes();
609 assertEquals(2, childs.getLength());
610 assertEquals(childs.item(0).getLocalName(), "EncryptedKey");
611 assertEquals(childs.item(1).getLocalName(), "EncryptedData");
612 }
613
614 final PushbackInputStream pis = new PushbackInputStream(encryptedAttachments.get(0).getSourceStream(), 1);
615 pis.unread('K');
616 encryptedAttachments.get(0).setSourceStream(pis);
617 attachmentCallbackHandler = new AttachmentCallbackHandler(encryptedAttachments);
618 {
619 WSSSecurityProperties securityProperties = new WSSSecurityProperties();
620 securityProperties.loadDecryptionKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
621 securityProperties.setCallbackHandler(new CallbackHandlerImpl());
622 securityProperties.setAttachmentCallbackHandler(attachmentCallbackHandler);
623
624 InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
625 XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
626 StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
627 }
628
629 assertFalse(attachmentCallbackHandler.getResponseAttachments().isEmpty());
630 Attachment responseAttachment = attachmentCallbackHandler.getResponseAttachments().get(0);
631
632
633 try {
634 byte[] attachmentBytes = readInputStream(responseAttachment.getSourceStream());
635 assertFalse(Arrays.equals(attachmentBytes, SOAPUtil.SAMPLE_SOAP_MSG.getBytes(StandardCharsets.UTF_8)));
636 assertEquals("text/xml", responseAttachment.getMimeType());
637
638 Map<String, String> attHeaders = responseAttachment.getHeaders();
639 assertEquals(6, attHeaders.size());
640 } catch (IOException ex) {
641
642 }
643 }
644
645 @Test
646 public void testXMLAttachmentContentEncryptionExternalReferenceList() throws Exception {
647
648 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
649 WSSecHeader secHeader = new WSSecHeader(doc);
650 secHeader.insertSecurityHeader();
651
652 WSSecEncrypt encrypt = new WSSecEncrypt(secHeader);
653 encrypt.setUserInfo("receiver", "default");
654 encrypt.setKeyIdentifierType(WSConstants.ISSUER_SERIAL);
655
656 encrypt.getParts().add(new WSEncryptionPart("Body", "http://schemas.xmlsoap.org/soap/envelope/", "Content"));
657 encrypt.getParts().add(new WSEncryptionPart("cid:Attachments", "Content"));
658
659 String attachmentId = UUID.randomUUID().toString();
660 final Attachment attachment = new Attachment();
661 attachment.setMimeType("text/xml");
662 attachment.addHeaders(getHeaders(attachmentId));
663 attachment.setId(attachmentId);
664 attachment.setSourceStream(new ByteArrayInputStream(SOAPUtil.SAMPLE_SOAP_MSG.getBytes(StandardCharsets.UTF_8)));
665 AttachmentCallbackHandler attachmentCallbackHandler =
666 new AttachmentCallbackHandler(Collections.singletonList(attachment));
667 List<Attachment> encryptedAttachments = attachmentCallbackHandler.getResponseAttachments();
668
669 encrypt.setAttachmentCallbackHandler(attachmentCallbackHandler);
670
671 KeyGenerator keyGen = KeyUtils.getKeyGenerator(WSConstants.AES_128);
672 SecretKey symmetricKey = keyGen.generateKey();
673 encrypt.prepare(CryptoFactory.getInstance("transmitter-crypto.properties"), symmetricKey);
674 Element refs = encrypt.encrypt(symmetricKey);
675 encrypt.addAttachmentEncryptedDataElements();
676 encrypt.addExternalRefElement(refs);
677 encrypt.prependToHeader();
678
679 NodeList references = doc.getElementsByTagNameNS(WSConstants.ENC_NS, "DataReference");
680 assertEquals(2, references.getLength());
681 NodeList cipherReferences = doc.getElementsByTagNameNS(WSConstants.ENC_NS, "CipherReference");
682 assertEquals(1, cipherReferences.getLength());
683 NodeList encDatas = doc.getElementsByTagNameNS(WSConstants.ENC_NS, "EncryptedData");
684 assertEquals(2, encDatas.getLength());
685
686 NodeList securityHeaderElement = doc.getElementsByTagNameNS(WSConstants.WSSE_NS, "Security");
687 assertEquals(1, securityHeaderElement.getLength());
688 NodeList childs = securityHeaderElement.item(0).getChildNodes();
689 assertEquals(3, childs.getLength());
690 assertEquals(childs.item(0).getLocalName(), "EncryptedKey");
691 assertEquals(childs.item(1).getLocalName(), "ReferenceList");
692 assertEquals(childs.item(2).getLocalName(), "EncryptedData");
693
694 ByteArrayOutputStream baos = new ByteArrayOutputStream();
695
696 javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
697 transformer.transform(new DOMSource(doc), new StreamResult(baos));
698 attachmentCallbackHandler = new AttachmentCallbackHandler(encryptedAttachments);
699 {
700 WSSSecurityProperties securityProperties = new WSSSecurityProperties();
701 securityProperties.loadDecryptionKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
702 securityProperties.setCallbackHandler(new CallbackHandlerImpl());
703 securityProperties.setAttachmentCallbackHandler(attachmentCallbackHandler);
704
705 InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
706 XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
707 StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
708 }
709
710 assertFalse(attachmentCallbackHandler.getResponseAttachments().isEmpty());
711 Attachment responseAttachment = attachmentCallbackHandler.getResponseAttachments().get(0);
712 byte[] attachmentBytes = readInputStream(responseAttachment.getSourceStream());
713 assertTrue(Arrays.equals(attachmentBytes, SOAPUtil.SAMPLE_SOAP_MSG.getBytes(StandardCharsets.UTF_8)));
714 assertEquals("text/xml", responseAttachment.getMimeType());
715
716 Map<String, String> attHeaders = responseAttachment.getHeaders();
717 assertEquals(6, attHeaders.size());
718 }
719
720 @Test
721 public void testXMLAttachmentCompleteEncryption() throws Exception {
722
723 final String attachmentId = UUID.randomUUID().toString();
724 final Attachment attachment = new Attachment();
725 attachment.setMimeType("text/xml");
726 attachment.addHeaders(getHeaders(attachmentId));
727 attachment.setId(attachmentId);
728 attachment.setSourceStream(new ByteArrayInputStream(SOAPUtil.SAMPLE_SOAP_MSG.getBytes(StandardCharsets.UTF_8)));
729
730 AttachmentCallbackHandler attachmentCallbackHandler =
731 new AttachmentCallbackHandler(Collections.singletonList(attachment));
732 List<Attachment> encryptedAttachments = attachmentCallbackHandler.getResponseAttachments();
733
734 ByteArrayOutputStream baos = new ByteArrayOutputStream();
735 {
736 WSSSecurityProperties securityProperties = new WSSSecurityProperties();
737 List<WSSConstants.Action> actions = new ArrayList<>();
738 actions.add(WSSConstants.ENCRYPTION);
739 securityProperties.setActions(actions);
740 securityProperties.loadEncryptionKeystore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
741 securityProperties.setEncryptionUser("receiver");
742 securityProperties.addEncryptionPart(new SecurePart(new QName("http://schemas.xmlsoap.org/soap/envelope/", "Body"), SecurePart.Modifier.Content));
743 securityProperties.addEncryptionPart(new SecurePart("cid:Attachments", SecurePart.Modifier.Element));
744 securityProperties.setAttachmentCallbackHandler(attachmentCallbackHandler);
745
746 OutboundWSSec wsSecOut = WSSec.getOutboundWSSec(securityProperties);
747 XMLStreamWriter xmlStreamWriter = wsSecOut.processOutMessage(baos, StandardCharsets.UTF_8.name(), new ArrayList<SecurityEvent>());
748 XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml"));
749 XmlReaderToWriter.writeAll(xmlStreamReader, xmlStreamWriter);
750 xmlStreamWriter.close();
751
752 Document securedDoc = documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray()));
753
754 NodeList references = securedDoc.getElementsByTagNameNS(WSConstants.ENC_NS, "DataReference");
755 assertEquals(2, references.getLength());
756 NodeList cipherReferences = securedDoc.getElementsByTagNameNS(WSConstants.ENC_NS, "CipherReference");
757 assertEquals(1, cipherReferences.getLength());
758 NodeList encDatas = securedDoc.getElementsByTagNameNS(WSConstants.ENC_NS, "EncryptedData");
759 assertEquals(2, encDatas.getLength());
760
761 NodeList securityHeaderElement = securedDoc.getElementsByTagNameNS(WSConstants.WSSE_NS, "Security");
762 assertEquals(1, securityHeaderElement.getLength());
763 NodeList childs = securityHeaderElement.item(0).getChildNodes();
764 assertEquals(2, childs.getLength());
765 assertEquals(childs.item(0).getLocalName(), "EncryptedKey");
766 assertEquals(childs.item(1).getLocalName(), "EncryptedData");
767
768 assertEquals(1, encryptedAttachments.get(0).getHeaders().size());
769 }
770
771 attachmentCallbackHandler = new AttachmentCallbackHandler(encryptedAttachments);
772 {
773 WSSSecurityProperties securityProperties = new WSSSecurityProperties();
774 securityProperties.loadDecryptionKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
775 securityProperties.setCallbackHandler(new CallbackHandlerImpl());
776 securityProperties.setAttachmentCallbackHandler(attachmentCallbackHandler);
777
778 InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
779 XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
780 StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
781 }
782
783 assertFalse(attachmentCallbackHandler.getResponseAttachments().isEmpty());
784 Attachment responseAttachment = attachmentCallbackHandler.getResponseAttachments().get(0);
785 byte[] attachmentBytes = readInputStream(responseAttachment.getSourceStream());
786 assertTrue(Arrays.equals(attachmentBytes, SOAPUtil.SAMPLE_SOAP_MSG.getBytes(StandardCharsets.UTF_8)));
787 assertEquals("text/xml", responseAttachment.getMimeType());
788
789 Map<String, String> attHeaders = responseAttachment.getHeaders();
790 assertEquals(6, attHeaders.size());
791 }
792
793 @Test
794 public void testInvalidXMLAttachmentCompleteEncryption() throws Exception {
795
796 final String attachmentId = UUID.randomUUID().toString();
797 final Attachment attachment = new Attachment();
798 attachment.setMimeType("text/xml");
799 attachment.addHeaders(getHeaders(attachmentId));
800 attachment.setId(attachmentId);
801 attachment.setSourceStream(new ByteArrayInputStream(SOAPUtil.SAMPLE_SOAP_MSG.getBytes(StandardCharsets.UTF_8)));
802
803 AttachmentCallbackHandler attachmentCallbackHandler =
804 new AttachmentCallbackHandler(Collections.singletonList(attachment));
805 List<Attachment> encryptedAttachments = attachmentCallbackHandler.getResponseAttachments();
806
807 ByteArrayOutputStream baos = new ByteArrayOutputStream();
808 {
809 WSSSecurityProperties securityProperties = new WSSSecurityProperties();
810 List<WSSConstants.Action> actions = new ArrayList<>();
811 actions.add(WSSConstants.ENCRYPTION);
812 securityProperties.setActions(actions);
813 securityProperties.loadEncryptionKeystore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
814 securityProperties.setEncryptionUser("receiver");
815 securityProperties.addEncryptionPart(new SecurePart(new QName("http://schemas.xmlsoap.org/soap/envelope/", "Body"), SecurePart.Modifier.Content));
816 securityProperties.addEncryptionPart(new SecurePart("cid:Attachments", SecurePart.Modifier.Element));
817 securityProperties.setAttachmentCallbackHandler(attachmentCallbackHandler);
818
819 OutboundWSSec wsSecOut = WSSec.getOutboundWSSec(securityProperties);
820 XMLStreamWriter xmlStreamWriter = wsSecOut.processOutMessage(baos, StandardCharsets.UTF_8.name(), new ArrayList<SecurityEvent>());
821 XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml"));
822 XmlReaderToWriter.writeAll(xmlStreamReader, xmlStreamWriter);
823 xmlStreamWriter.close();
824
825 Document securedDoc = documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray()));
826
827 NodeList references = securedDoc.getElementsByTagNameNS(WSConstants.ENC_NS, "DataReference");
828 assertEquals(2, references.getLength());
829 NodeList cipherReferences = securedDoc.getElementsByTagNameNS(WSConstants.ENC_NS, "CipherReference");
830 assertEquals(1, cipherReferences.getLength());
831 NodeList encDatas = securedDoc.getElementsByTagNameNS(WSConstants.ENC_NS, "EncryptedData");
832 assertEquals(2, encDatas.getLength());
833
834 NodeList securityHeaderElement = securedDoc.getElementsByTagNameNS(WSConstants.WSSE_NS, "Security");
835 assertEquals(1, securityHeaderElement.getLength());
836 NodeList childs = securityHeaderElement.item(0).getChildNodes();
837 assertEquals(2, childs.getLength());
838 assertEquals(childs.item(0).getLocalName(), "EncryptedKey");
839 assertEquals(childs.item(1).getLocalName(), "EncryptedData");
840
841 assertEquals(1, encryptedAttachments.get(0).getHeaders().size());
842 }
843
844 final PushbackInputStream pis = new PushbackInputStream(encryptedAttachments.get(0).getSourceStream(), 1);
845 pis.unread('K');
846 encryptedAttachments.get(0).setSourceStream(pis);
847 attachmentCallbackHandler = new AttachmentCallbackHandler(encryptedAttachments);
848 {
849 WSSSecurityProperties securityProperties = new WSSSecurityProperties();
850 securityProperties.loadDecryptionKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
851 securityProperties.setCallbackHandler(new CallbackHandlerImpl());
852 securityProperties.setAttachmentCallbackHandler(attachmentCallbackHandler);
853
854 InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
855 XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
856 try {
857 StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
858 } catch (XMLStreamException e) {
859 assertTrue(e.getCause() instanceof WSSecurityException);
860
861 return;
862 }
863
864 assertFalse(attachmentCallbackHandler.getResponseAttachments().isEmpty());
865 Attachment responseAttachment = attachmentCallbackHandler.getResponseAttachments().get(0);
866 byte[] attachmentBytes = readInputStream(responseAttachment.getSourceStream());
867 assertFalse(Arrays.equals(attachmentBytes, SOAPUtil.SAMPLE_SOAP_MSG.getBytes(StandardCharsets.UTF_8)));
868 assertEquals("text/xml", responseAttachment.getMimeType());
869
870 }
871 }
872
873 @Test
874 public void testMultipleAttachmentCompleteEncryption() throws Exception {
875
876 final String attachment1Id = UUID.randomUUID().toString();
877 final Attachment[] attachment = new Attachment[2];
878 attachment[0] = new Attachment();
879 attachment[0].setMimeType("text/xml");
880 attachment[0].addHeaders(getHeaders(attachment1Id));
881 attachment[0].setId(attachment1Id);
882 attachment[0].setSourceStream(new ByteArrayInputStream(SOAPUtil.SAMPLE_SOAP_MSG.getBytes(StandardCharsets.UTF_8)));
883
884 final String attachment2Id = UUID.randomUUID().toString();
885 attachment[1] = new Attachment();
886 attachment[1].setMimeType("text/plain");
887 attachment[1].addHeaders(getHeaders(attachment2Id));
888 attachment[1].setId(attachment2Id);
889 attachment[1].setSourceStream(new ByteArrayInputStream(SOAPUtil.SAMPLE_SOAP_MSG.getBytes(StandardCharsets.UTF_8)));
890
891 AttachmentCallbackHandler attachmentCallbackHandler =
892 new AttachmentCallbackHandler(Arrays.asList(attachment));
893 List<Attachment> encryptedAttachments = attachmentCallbackHandler.getResponseAttachments();
894
895 ByteArrayOutputStream baos = new ByteArrayOutputStream();
896 {
897 WSSSecurityProperties securityProperties = new WSSSecurityProperties();
898 List<WSSConstants.Action> actions = new ArrayList<>();
899 actions.add(WSSConstants.ENCRYPTION);
900 securityProperties.setActions(actions);
901 securityProperties.loadEncryptionKeystore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
902 securityProperties.setEncryptionUser("receiver");
903 securityProperties.addEncryptionPart(new SecurePart(new QName("http://schemas.xmlsoap.org/soap/envelope/", "Body"), SecurePart.Modifier.Content));
904 securityProperties.addEncryptionPart(new SecurePart("cid:Attachments", SecurePart.Modifier.Element));
905 securityProperties.setAttachmentCallbackHandler(attachmentCallbackHandler);
906
907 OutboundWSSec wsSecOut = WSSec.getOutboundWSSec(securityProperties);
908 XMLStreamWriter xmlStreamWriter = wsSecOut.processOutMessage(baos, StandardCharsets.UTF_8.name(), new ArrayList<SecurityEvent>());
909 XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml"));
910 XmlReaderToWriter.writeAll(xmlStreamReader, xmlStreamWriter);
911 xmlStreamWriter.close();
912 }
913
914 attachmentCallbackHandler = new AttachmentCallbackHandler(encryptedAttachments);
915 {
916 WSSSecurityProperties securityProperties = new WSSSecurityProperties();
917 securityProperties.loadDecryptionKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
918 securityProperties.setCallbackHandler(new CallbackHandlerImpl());
919 securityProperties.setAttachmentCallbackHandler(attachmentCallbackHandler);
920
921 InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
922 XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
923 StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
924 }
925
926 assertFalse(attachmentCallbackHandler.getResponseAttachments().isEmpty());
927 Attachment responseAttachment = attachmentCallbackHandler.getResponseAttachments().get(0);
928
929 byte[] attachment1Bytes = readInputStream(responseAttachment.getSourceStream());
930 assertTrue(Arrays.equals(attachment1Bytes, SOAPUtil.SAMPLE_SOAP_MSG.getBytes(StandardCharsets.UTF_8)));
931 assertEquals("text/xml", responseAttachment.getMimeType());
932 Map<String, String> att1Headers = responseAttachment.getHeaders();
933 assertEquals(6, att1Headers.size());
934
935 responseAttachment = attachmentCallbackHandler.getResponseAttachments().get(1);
936
937 byte[] attachment2Bytes = readInputStream(responseAttachment.getSourceStream());
938 assertTrue(Arrays.equals(attachment2Bytes, SOAPUtil.SAMPLE_SOAP_MSG.getBytes(StandardCharsets.UTF_8)));
939 assertEquals("text/plain", responseAttachment.getMimeType());
940 Map<String, String> att2Headers = responseAttachment.getHeaders();
941 assertEquals(6, att2Headers.size());
942 }
943
944 @Test
945 public void testXMLAttachmentCmplSignCmplEnc() throws Exception {
946
947 final String attachmentId = UUID.randomUUID().toString();
948 final Attachment[] attachment = new Attachment[1];
949 attachment[0] = new Attachment();
950 attachment[0].setMimeType("text/xml");
951 attachment[0].addHeaders(getHeaders(attachmentId));
952 attachment[0].setId(attachmentId);
953 attachment[0].setSourceStream(new ByteArrayInputStream(SOAPUtil.SAMPLE_SOAP_MSG.getBytes(StandardCharsets.UTF_8)));
954
955 ByteArrayOutputStream baos = new ByteArrayOutputStream();
956 {
957 WSSSecurityProperties securityProperties = new WSSSecurityProperties();
958 List<WSSConstants.Action> actions = new ArrayList<>();
959 actions.add(WSSConstants.SIGNATURE);
960 actions.add(WSSConstants.ENCRYPTION);
961 securityProperties.setActions(actions);
962 securityProperties.loadSignatureKeyStore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
963 securityProperties.setSignatureUser("transmitter");
964 securityProperties.addSignaturePart(new SecurePart(new QName("http://schemas.xmlsoap.org/soap/envelope/", "Body"), SecurePart.Modifier.Element));
965 securityProperties.addSignaturePart(new SecurePart("cid:Attachments", SecurePart.Modifier.Element));
966 securityProperties.setCallbackHandler(new CallbackHandlerImpl());
967
968 securityProperties.loadEncryptionKeystore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
969 securityProperties.setEncryptionUser("receiver");
970 securityProperties.addEncryptionPart(new SecurePart(new QName("http://schemas.xmlsoap.org/soap/envelope/", "Body"), SecurePart.Modifier.Content));
971 securityProperties.addEncryptionPart(new SecurePart("cid:Attachments", SecurePart.Modifier.Element));
972
973 securityProperties.setAttachmentCallbackHandler(new CallbackHandler() {
974 @Override
975 public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
976 if (callbacks[0] instanceof AttachmentRequestCallback) {
977 AttachmentRequestCallback attachmentRequestCallback = (AttachmentRequestCallback) callbacks[0];
978 List<Attachment> attachments = new ArrayList<>();
979 attachments.add(attachment[0]);
980 attachmentRequestCallback.setAttachments(attachments);
981 } else {
982 AttachmentResultCallback attachmentResultCallback = (AttachmentResultCallback) callbacks[0];
983 attachment[0] = attachmentResultCallback.getAttachment();
984 }
985 }
986 });
987
988 OutboundWSSec wsSecOut = WSSec.getOutboundWSSec(securityProperties);
989 XMLStreamWriter xmlStreamWriter = wsSecOut.processOutMessage(baos, StandardCharsets.UTF_8.name(), new ArrayList<SecurityEvent>());
990 XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml"));
991 XmlReaderToWriter.writeAll(xmlStreamReader, xmlStreamWriter);
992 xmlStreamWriter.close();
993
994 Document securedDoc = documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray()));
995
996 NodeList securityHeaderElement = securedDoc.getElementsByTagNameNS(WSConstants.WSSE_NS, "Security");
997 assertEquals(1, securityHeaderElement.getLength());
998 NodeList childs = securityHeaderElement.item(0).getChildNodes();
999 assertEquals(3, childs.getLength());
1000 assertEquals(childs.item(0).getLocalName(), "EncryptedKey");
1001 assertEquals(childs.item(1).getLocalName(), "EncryptedData");
1002 assertEquals(childs.item(2).getLocalName(), "Signature");
1003
1004 assertEquals(1, attachment[0].getHeaders().size());
1005 }
1006
1007 {
1008 WSSSecurityProperties securityProperties = new WSSSecurityProperties();
1009 securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
1010 securityProperties.loadDecryptionKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
1011 securityProperties.setCallbackHandler(new CallbackHandlerImpl());
1012 securityProperties.setAttachmentCallbackHandler(new CallbackHandler() {
1013 @Override
1014 public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
1015 if (callbacks[0] instanceof AttachmentRequestCallback) {
1016 AttachmentRequestCallback attachmentRequestCallback = (AttachmentRequestCallback)callbacks[0];
1017
1018 if (!attachment[0].getId().equals(attachmentRequestCallback.getAttachmentId())) {
1019 throw new RuntimeException("wrong attachment requested");
1020 }
1021
1022 List<Attachment> attachments = new ArrayList<>();
1023 attachments.add(attachment[0]);
1024 attachmentRequestCallback.setAttachments(attachments);
1025 } else {
1026 AttachmentResultCallback attachmentResultCallback = (AttachmentResultCallback)callbacks[0];
1027 attachment[0] = attachmentResultCallback.getAttachment();
1028 }
1029 }
1030 });
1031
1032 InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
1033 XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
1034 StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
1035 }
1036
1037 byte[] attachmentBytes = readInputStream(attachment[0].getSourceStream());
1038 assertTrue(Arrays.equals(attachmentBytes, SOAPUtil.SAMPLE_SOAP_MSG.getBytes(StandardCharsets.UTF_8)));
1039 assertEquals("text/xml", attachment[0].getMimeType());
1040
1041 Map<String, String> attHeaders = attachment[0].getHeaders();
1042 assertEquals(6, attHeaders.size());
1043 }
1044
1045 @Test
1046 public void testInvalidXMLAttachmentCmplSignCmplEnc() throws Exception {
1047
1048 final String attachmentId = UUID.randomUUID().toString();
1049 final Attachment[] attachment = new Attachment[1];
1050 attachment[0] = new Attachment();
1051 attachment[0].setMimeType("text/xml");
1052 attachment[0].addHeaders(getHeaders(attachmentId));
1053 attachment[0].setId(attachmentId);
1054 attachment[0].setSourceStream(new ByteArrayInputStream(SOAPUtil.SAMPLE_SOAP_MSG.getBytes(StandardCharsets.UTF_8)));
1055
1056 ByteArrayOutputStream baos = new ByteArrayOutputStream();
1057 {
1058 WSSSecurityProperties securityProperties = new WSSSecurityProperties();
1059 List<WSSConstants.Action> actions = new ArrayList<>();
1060 actions.add(WSSConstants.SIGNATURE);
1061 actions.add(WSSConstants.ENCRYPTION);
1062 securityProperties.setActions(actions);
1063 securityProperties.loadSignatureKeyStore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
1064 securityProperties.setSignatureUser("transmitter");
1065 securityProperties.addSignaturePart(new SecurePart(new QName("http://schemas.xmlsoap.org/soap/envelope/", "Body"), SecurePart.Modifier.Element));
1066 securityProperties.addSignaturePart(new SecurePart("cid:Attachments", SecurePart.Modifier.Element));
1067 securityProperties.setCallbackHandler(new CallbackHandlerImpl());
1068
1069 securityProperties.loadEncryptionKeystore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
1070 securityProperties.setEncryptionUser("receiver");
1071 securityProperties.addEncryptionPart(new SecurePart(new QName("http://schemas.xmlsoap.org/soap/envelope/", "Body"), SecurePart.Modifier.Content));
1072 securityProperties.addEncryptionPart(new SecurePart("cid:Attachments", SecurePart.Modifier.Element));
1073
1074 securityProperties.setAttachmentCallbackHandler(new CallbackHandler() {
1075 @Override
1076 public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
1077 if (callbacks[0] instanceof AttachmentRequestCallback) {
1078 AttachmentRequestCallback attachmentRequestCallback = (AttachmentRequestCallback) callbacks[0];
1079 List<Attachment> attachments = new ArrayList<>();
1080 attachments.add(attachment[0]);
1081 attachmentRequestCallback.setAttachments(attachments);
1082 } else {
1083 AttachmentResultCallback attachmentResultCallback = (AttachmentResultCallback) callbacks[0];
1084 attachment[0] = attachmentResultCallback.getAttachment();
1085 }
1086 }
1087 });
1088
1089 OutboundWSSec wsSecOut = WSSec.getOutboundWSSec(securityProperties);
1090 XMLStreamWriter xmlStreamWriter = wsSecOut.processOutMessage(baos, StandardCharsets.UTF_8.name(), new ArrayList<SecurityEvent>());
1091 XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml"));
1092 XmlReaderToWriter.writeAll(xmlStreamReader, xmlStreamWriter);
1093 xmlStreamWriter.close();
1094 }
1095
1096 {
1097 WSSSecurityProperties securityProperties = new WSSSecurityProperties();
1098 securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
1099 securityProperties.loadDecryptionKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
1100 securityProperties.setCallbackHandler(new CallbackHandlerImpl());
1101 securityProperties.setAttachmentCallbackHandler(new CallbackHandler() {
1102 @Override
1103 public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
1104 if (callbacks[0] instanceof AttachmentRequestCallback) {
1105 AttachmentRequestCallback attachmentRequestCallback = (AttachmentRequestCallback) callbacks[0];
1106
1107 if (!attachment[0].getId().equals(attachmentRequestCallback.getAttachmentId())) {
1108 throw new RuntimeException("wrong attachment requested");
1109 }
1110
1111 List<Attachment> attachments = new ArrayList<>();
1112 attachments.add(attachment[0]);
1113
1114 if (attachment[0].getHeaders().size() == 6) {
1115
1116 attachment[0].addHeader(AttachmentUtils.MIME_HEADER_CONTENT_DESCRIPTION, "Kaputt");
1117 }
1118
1119 attachmentRequestCallback.setAttachments(attachments);
1120 } else {
1121 AttachmentResultCallback attachmentResultCallback = (AttachmentResultCallback) callbacks[0];
1122 attachment[0] = attachmentResultCallback.getAttachment();
1123 }
1124 }
1125 });
1126 InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
1127 XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
1128 try {
1129 StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
1130 fail("Exception expected");
1131 } catch (XMLStreamException e) {
1132 assertTrue(e.getCause() instanceof XMLSecurityException);
1133 assertTrue(e.getCause().getMessage().startsWith("Invalid digest of reference cid:"));
1134 }
1135 }
1136 }
1137
1138 @Test
1139 public void testXMLAttachmentCmplEncCmplSign() throws Exception {
1140
1141 final String attachmentId = UUID.randomUUID().toString();
1142 final Attachment[] attachment = new Attachment[1];
1143 attachment[0] = new Attachment();
1144 attachment[0].setMimeType("text/xml");
1145 attachment[0].addHeaders(getHeaders(attachmentId));
1146 attachment[0].setId(attachmentId);
1147 attachment[0].setSourceStream(new ByteArrayInputStream(SOAPUtil.SAMPLE_SOAP_MSG.getBytes(StandardCharsets.UTF_8)));
1148
1149 ByteArrayOutputStream baos = new ByteArrayOutputStream();
1150 {
1151 WSSSecurityProperties securityProperties = new WSSSecurityProperties();
1152 List<WSSConstants.Action> actions = new ArrayList<>();
1153 actions.add(WSSConstants.ENCRYPTION);
1154 actions.add(WSSConstants.SIGNATURE);
1155 securityProperties.setActions(actions);
1156 securityProperties.loadSignatureKeyStore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
1157 securityProperties.setSignatureUser("transmitter");
1158 securityProperties.addSignaturePart(new SecurePart(new QName("http://schemas.xmlsoap.org/soap/envelope/", "Body"), SecurePart.Modifier.Element));
1159 securityProperties.addSignaturePart(new SecurePart("cid:Attachments", SecurePart.Modifier.Element));
1160 securityProperties.setCallbackHandler(new CallbackHandlerImpl());
1161
1162 securityProperties.loadEncryptionKeystore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
1163 securityProperties.setEncryptionUser("receiver");
1164 securityProperties.addEncryptionPart(new SecurePart(new QName("http://schemas.xmlsoap.org/soap/envelope/", "Body"), SecurePart.Modifier.Content));
1165 securityProperties.addEncryptionPart(new SecurePart("cid:Attachments", SecurePart.Modifier.Element));
1166
1167 securityProperties.setAttachmentCallbackHandler(new CallbackHandler() {
1168 @Override
1169 public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
1170 if (callbacks[0] instanceof AttachmentRequestCallback) {
1171 AttachmentRequestCallback attachmentRequestCallback = (AttachmentRequestCallback) callbacks[0];
1172 List<Attachment> attachments = new ArrayList<>();
1173 attachments.add(attachment[0]);
1174 attachmentRequestCallback.setAttachments(attachments);
1175 } else {
1176 AttachmentResultCallback attachmentResultCallback = (AttachmentResultCallback) callbacks[0];
1177 attachment[0] = attachmentResultCallback.getAttachment();
1178 }
1179 }
1180 });
1181
1182 OutboundWSSec wsSecOut = WSSec.getOutboundWSSec(securityProperties);
1183 XMLStreamWriter xmlStreamWriter = wsSecOut.processOutMessage(baos, StandardCharsets.UTF_8.name(), new ArrayList<SecurityEvent>());
1184 XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml"));
1185 XmlReaderToWriter.writeAll(xmlStreamReader, xmlStreamWriter);
1186 xmlStreamWriter.close();
1187
1188 Document securedDoc = documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray()));
1189
1190 NodeList securityHeaderElement = securedDoc.getElementsByTagNameNS(WSConstants.WSSE_NS, "Security");
1191 assertEquals(1, securityHeaderElement.getLength());
1192 NodeList childs = securityHeaderElement.item(0).getChildNodes();
1193 assertEquals(3, childs.getLength());
1194 assertEquals(childs.item(0).getLocalName(), "Signature");
1195 assertEquals(childs.item(1).getLocalName(), "EncryptedKey");
1196 assertEquals(childs.item(2).getLocalName(), "EncryptedData");
1197
1198 assertEquals(1, attachment[0].getHeaders().size());
1199 }
1200
1201 {
1202 WSSSecurityProperties securityProperties = new WSSSecurityProperties();
1203 securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
1204 securityProperties.loadDecryptionKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
1205 securityProperties.setCallbackHandler(new CallbackHandlerImpl());
1206 securityProperties.setAttachmentCallbackHandler(new CallbackHandler() {
1207 @Override
1208 public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
1209 if (callbacks[0] instanceof AttachmentRequestCallback) {
1210 AttachmentRequestCallback attachmentRequestCallback = (AttachmentRequestCallback) callbacks[0];
1211
1212 if (!attachment[0].getId().equals(attachmentRequestCallback.getAttachmentId())) {
1213 throw new RuntimeException("wrong attachment requested");
1214 }
1215
1216 List<Attachment> attachments = new ArrayList<>();
1217 attachments.add(attachment[0]);
1218 attachmentRequestCallback.setAttachments(attachments);
1219 } else {
1220 AttachmentResultCallback attachmentResultCallback = (AttachmentResultCallback) callbacks[0];
1221 attachment[0] = attachmentResultCallback.getAttachment();
1222 }
1223 }
1224 });
1225
1226 InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
1227 XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
1228 StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
1229 }
1230
1231 byte[] attachmentBytes = readInputStream(attachment[0].getSourceStream());
1232 assertTrue(Arrays.equals(attachmentBytes, SOAPUtil.SAMPLE_SOAP_MSG.getBytes(StandardCharsets.UTF_8)));
1233 assertEquals("text/xml", attachment[0].getMimeType());
1234
1235 Map<String, String> attHeaders = attachment[0].getHeaders();
1236 assertEquals(6, attHeaders.size());
1237 }
1238
1239 @Test
1240 public void testInvalidXMLAttachmentCmplEncCmplSign() throws Exception {
1241
1242 final String attachmentId = UUID.randomUUID().toString();
1243 final Attachment[] attachment = new Attachment[1];
1244 attachment[0] = new Attachment();
1245 attachment[0].setMimeType("text/xml");
1246 attachment[0].addHeaders(getHeaders(attachmentId));
1247 attachment[0].setId(attachmentId);
1248 attachment[0].setSourceStream(new ByteArrayInputStream(SOAPUtil.SAMPLE_SOAP_MSG.getBytes(StandardCharsets.UTF_8)));
1249
1250 ByteArrayOutputStream baos = new ByteArrayOutputStream();
1251 {
1252 WSSSecurityProperties securityProperties = new WSSSecurityProperties();
1253 List<WSSConstants.Action> actions = new ArrayList<>();
1254 actions.add(WSSConstants.ENCRYPTION);
1255 actions.add(WSSConstants.SIGNATURE);
1256 securityProperties.setActions(actions);
1257 securityProperties.loadSignatureKeyStore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
1258 securityProperties.setSignatureUser("transmitter");
1259 securityProperties.addSignaturePart(new SecurePart(new QName("http://schemas.xmlsoap.org/soap/envelope/", "Body"), SecurePart.Modifier.Element));
1260 securityProperties.addSignaturePart(new SecurePart("cid:Attachments", SecurePart.Modifier.Element));
1261 securityProperties.setCallbackHandler(new CallbackHandlerImpl());
1262
1263 securityProperties.loadEncryptionKeystore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
1264 securityProperties.setEncryptionUser("receiver");
1265 securityProperties.addEncryptionPart(new SecurePart(new QName("http://schemas.xmlsoap.org/soap/envelope/", "Body"), SecurePart.Modifier.Content));
1266 securityProperties.addEncryptionPart(new SecurePart("cid:Attachments", SecurePart.Modifier.Element));
1267
1268 securityProperties.setAttachmentCallbackHandler(new CallbackHandler() {
1269 @Override
1270 public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
1271 if (callbacks[0] instanceof AttachmentRequestCallback) {
1272 AttachmentRequestCallback attachmentRequestCallback = (AttachmentRequestCallback) callbacks[0];
1273 List<Attachment> attachments = new ArrayList<>();
1274 attachments.add(attachment[0]);
1275 attachmentRequestCallback.setAttachments(attachments);
1276 } else {
1277 AttachmentResultCallback attachmentResultCallback = (AttachmentResultCallback) callbacks[0];
1278 attachment[0] = attachmentResultCallback.getAttachment();
1279 }
1280 }
1281 });
1282
1283 OutboundWSSec wsSecOut = WSSec.getOutboundWSSec(securityProperties);
1284 XMLStreamWriter xmlStreamWriter = wsSecOut.processOutMessage(baos, StandardCharsets.UTF_8.name(), new ArrayList<SecurityEvent>());
1285 XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml"));
1286 XmlReaderToWriter.writeAll(xmlStreamReader, xmlStreamWriter);
1287 xmlStreamWriter.close();
1288
1289 Document securedDoc = documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray()));
1290
1291 NodeList securityHeaderElement = securedDoc.getElementsByTagNameNS(WSConstants.WSSE_NS, "Security");
1292 assertEquals(1, securityHeaderElement.getLength());
1293 NodeList childs = securityHeaderElement.item(0).getChildNodes();
1294 assertEquals(3, childs.getLength());
1295 assertEquals(childs.item(0).getLocalName(), "Signature");
1296 assertEquals(childs.item(1).getLocalName(), "EncryptedKey");
1297 assertEquals(childs.item(2).getLocalName(), "EncryptedData");
1298 }
1299
1300 {
1301 final PushbackInputStream pis = new PushbackInputStream(attachment[0].getSourceStream(), 1);
1302 pis.unread('K');
1303 attachment[0].setSourceStream(pis);
1304
1305 WSSSecurityProperties securityProperties = new WSSSecurityProperties();
1306 securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
1307 securityProperties.loadDecryptionKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
1308 securityProperties.setCallbackHandler(new CallbackHandlerImpl());
1309 securityProperties.setAttachmentCallbackHandler(new CallbackHandler() {
1310 @Override
1311 public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
1312 if (callbacks[0] instanceof AttachmentRequestCallback) {
1313 AttachmentRequestCallback attachmentRequestCallback = (AttachmentRequestCallback) callbacks[0];
1314
1315 if (!attachment[0].getId().equals(attachmentRequestCallback.getAttachmentId())) {
1316 throw new RuntimeException("wrong attachment requested");
1317 }
1318
1319 List<Attachment> attachments = new ArrayList<>();
1320 attachments.add(attachment[0]);
1321 attachmentRequestCallback.setAttachments(attachments);
1322 } else {
1323 AttachmentResultCallback attachmentResultCallback = (AttachmentResultCallback) callbacks[0];
1324 attachment[0] = attachmentResultCallback.getAttachment();
1325 }
1326 }
1327 });
1328
1329 InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
1330 XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
1331 try {
1332 StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
1333 fail("Exception expected");
1334 } catch (XMLStreamException e) {
1335 assertNotNull(e.getMessage());
1336 }
1337 }
1338 }
1339
1340 }