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