This is an automated email from the ASF dual-hosted git repository.
coheigea pushed a commit to branch 3_0_x-fixes
in repository https://gitbox.apache.org/repos/asf/ws-wss4j.git
The following commit(s) were added to refs/heads/3_0_x-fixes by this push:
new 0be20382b Make sure for Attachment-Complete the mime type is read from
the encrypted header (#688)
0be20382b is described below
commit 0be20382b991a0afd748586251753409cc17e20b
Author: Colm O hEigeartaigh <[email protected]>
AuthorDate: Mon Sep 14 10:13:06 2026 +0100
Make sure for Attachment-Complete the mime type is read from the encrypted
header (#688)
---
.../org/apache/wss4j/dom/util/EncryptionUtils.java | 17 ++-
.../apache/wss4j/dom/message/AttachmentTest.java | 128 +++++++++++++++--
.../processor/input/DecryptInputProcessor.java | 16 ++-
.../org/apache/wss4j/stax/test/AttachmentTest.java | 154 +++++++++++++++++++--
4 files changed, 285 insertions(+), 30 deletions(-)
diff --git
a/ws-security-dom/src/main/java/org/apache/wss4j/dom/util/EncryptionUtils.java
b/ws-security-dom/src/main/java/org/apache/wss4j/dom/util/EncryptionUtils.java
index 9240f725f..fce625ca4 100644
---
a/ws-security-dom/src/main/java/org/apache/wss4j/dom/util/EncryptionUtils.java
+++
b/ws-security-dom/src/main/java/org/apache/wss4j/dom/util/EncryptionUtils.java
@@ -53,7 +53,9 @@ import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.NoSuchAlgorithmException;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
public final class EncryptionUtils {
@@ -346,14 +348,21 @@ public final class EncryptionUtils {
Attachment resultAttachment = new Attachment();
resultAttachment.setId(attachment.getId());
- resultAttachment.setMimeType(encData.getAttributeNS(null,
"MimeType"));
resultAttachment.setSourceStream(attachmentInputStream);
- resultAttachment.addHeaders(attachment.getHeaders());
String typeStr = encData.getAttributeNS(null, "Type");
if
(WSConstants.SWA_ATTACHMENT_ENCRYPTED_DATA_TYPE_COMPLETE.equals(typeStr)) {
- AttachmentUtils.readAndReplaceEncryptedAttachmentHeaders(
- resultAttachment.getHeaders(), attachmentInputStream);
+ Map<String, String> protectedHeaders = new HashMap<>();
+
AttachmentUtils.readAndReplaceEncryptedAttachmentHeaders(protectedHeaders,
attachmentInputStream);
+ String contentType =
protectedHeaders.get(AttachmentUtils.MIME_HEADER_CONTENT_TYPE);
+ if (contentType == null) {
+ throw new
WSSecurityException(WSSecurityException.ErrorCode.FAILED_CHECK);
+ }
+ resultAttachment.setMimeType(contentType);
+ resultAttachment.addHeaders(protectedHeaders);
+ } else {
+ resultAttachment.setMimeType(encData.getAttributeNS(null,
"MimeType"));
+ resultAttachment.addHeaders(attachment.getHeaders());
}
AttachmentResultCallback attachmentResultCallback = new
AttachmentResultCallback();
diff --git
a/ws-security-dom/src/test/java/org/apache/wss4j/dom/message/AttachmentTest.java
b/ws-security-dom/src/test/java/org/apache/wss4j/dom/message/AttachmentTest.java
index 9eab6c6fd..68a0751af 100644
---
a/ws-security-dom/src/test/java/org/apache/wss4j/dom/message/AttachmentTest.java
+++
b/ws-security-dom/src/test/java/org/apache/wss4j/dom/message/AttachmentTest.java
@@ -725,10 +725,10 @@ public class AttachmentTest {
byte[] attachmentBytes =
readInputStream(responseAttachment.getSourceStream());
assertTrue(Arrays.equals(attachmentBytes,
SOAPUtil.SAMPLE_SOAP_MSG.getBytes(StandardCharsets.UTF_8)));
- assertEquals("text/xml", responseAttachment.getMimeType());
+ assertEquals("text/xml; charset=UTF-8",
responseAttachment.getMimeType());
Map<String, String> attHeaders = responseAttachment.getHeaders();
- assertEquals(6, attHeaders.size());
+ assertEquals(5, attHeaders.size());
}
@Test
@@ -785,6 +785,112 @@ public class AttachmentTest {
assertEquals("text/xml", responseAttachment.getMimeType());
}
+ // Regression test for CWE-345: a wire attacker cannot forge the delivered
MIME type of an
+ // Attachment-Complete encrypted attachment by tampering with the
unauthenticated
+ // xenc:EncryptedData/@MimeType attribute - the MIME type must be sourced
from the
+ // encrypted (protected) Content-Type header instead.
+ @Test
+ public void
testXMLAttachmentCompleteEncryptionTamperedMimeTypeAttributeIgnored() throws
Exception {
+ Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
+ WSSecHeader secHeader = new WSSecHeader(doc);
+ secHeader.insertSecurityHeader();
+
+ WSSecEncrypt encrypt = new WSSecEncrypt(secHeader);
+ encrypt.setUserInfo("16c73ab6-b892-458f-abf5-2f875f74882e",
"security");
+ encrypt.setKeyIdentifierType(WSConstants.ISSUER_SERIAL);
+
+ encrypt.getParts().add(new WSEncryptionPart("Body",
"http://schemas.xmlsoap.org/soap/envelope/", "Content"));
+ encrypt.getParts().add(new WSEncryptionPart("cid:Attachments",
"Element"));
+
+ String attachmentId = UUID.randomUUID().toString();
+ final Attachment attachment = new Attachment();
+ attachment.setMimeType("text/xml");
+ attachment.addHeaders(getHeaders(attachmentId));
+ attachment.setId(attachmentId);
+ attachment.setSourceStream(new
ByteArrayInputStream(SOAPUtil.SAMPLE_SOAP_MSG.getBytes(StandardCharsets.UTF_8)));
+
+ AttachmentCallbackHandler attachmentCallbackHandler =
+ new
AttachmentCallbackHandler(Collections.singletonList(attachment));
+ encrypt.setAttachmentCallbackHandler(attachmentCallbackHandler);
+ List<Attachment> encryptedAttachments =
attachmentCallbackHandler.getResponseAttachments();
+
+ KeyGenerator keyGen = KeyUtils.getKeyGenerator(WSConstants.AES_128);
+ SecretKey symmetricKey = keyGen.generateKey();
+ Document encryptedDoc = encrypt.build(crypto, symmetricKey);
+
+ // Simulate a wire attacker rewriting the unauthenticated @MimeType
attribute
+ NodeList encDatas =
encryptedDoc.getElementsByTagNameNS(WSConstants.ENC_NS, "EncryptedData");
+ Element attachmentEncData = null;
+ for (int i = 0; i < encDatas.getLength(); i++) {
+ Element encData = (Element) encDatas.item(i);
+ if
(WSConstants.SWA_ATTACHMENT_ENCRYPTED_DATA_TYPE_COMPLETE.equals(encData.getAttributeNS(null,
"Type"))) {
+ attachmentEncData = encData;
+ break;
+ }
+ }
+ assertFalse(attachmentEncData == null);
+ attachmentEncData.setAttributeNS(null, "MimeType",
"application/malicious");
+ encryptedAttachments.get(0).getHeaders().put("X-Attacker-Controlled",
"forged");
+
+ if (LOG.isDebugEnabled()) {
+ String outputString =
XMLUtils.prettyDocumentToString(encryptedDoc);
+ LOG.debug(outputString);
+ }
+
+ attachmentCallbackHandler = new
AttachmentCallbackHandler(encryptedAttachments);
+ verify(encryptedDoc, attachmentCallbackHandler);
+
+
assertFalse(attachmentCallbackHandler.getResponseAttachments().isEmpty());
+ Attachment responseAttachment =
attachmentCallbackHandler.getResponseAttachments().get(0);
+
+ byte[] attachmentBytes =
readInputStream(responseAttachment.getSourceStream());
+ assertTrue(Arrays.equals(attachmentBytes,
SOAPUtil.SAMPLE_SOAP_MSG.getBytes(StandardCharsets.UTF_8)));
+ assertEquals("text/xml; charset=UTF-8",
responseAttachment.getMimeType());
+ assertFalse(responseAttachment.getHeaders().containsKey("TestHeader"));
+
assertFalse(responseAttachment.getHeaders().containsKey("X-Attacker-Controlled"));
+ }
+
+ // Regression test for CWE-345: if the protected header block (inside the
ciphertext) does
+ // not contain a Content-Type header, decryption of an Attachment-Complete
attachment must
+ // fail closed rather than falling back to the unauthenticated @MimeType
attribute.
+ @Test
+ public void
testXMLAttachmentCompleteEncryptionMissingProtectedContentType() throws
Exception {
+ Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
+ WSSecHeader secHeader = new WSSecHeader(doc);
+ secHeader.insertSecurityHeader();
+
+ WSSecEncrypt encrypt = new WSSecEncrypt(secHeader);
+ encrypt.setUserInfo("16c73ab6-b892-458f-abf5-2f875f74882e",
"security");
+ encrypt.setKeyIdentifierType(WSConstants.ISSUER_SERIAL);
+
+ encrypt.getParts().add(new WSEncryptionPart("Body",
"http://schemas.xmlsoap.org/soap/envelope/", "Content"));
+ encrypt.getParts().add(new WSEncryptionPart("cid:Attachments",
"Element"));
+
+ String attachmentId = UUID.randomUUID().toString();
+ final Attachment attachment = new Attachment();
+ attachment.setMimeType("text/xml");
+ Map<String, String> headers = getHeaders(attachmentId);
+ headers.remove(AttachmentUtils.MIME_HEADER_CONTENT_TYPE);
+ attachment.addHeaders(headers);
+ attachment.setId(attachmentId);
+ attachment.setSourceStream(new
ByteArrayInputStream(SOAPUtil.SAMPLE_SOAP_MSG.getBytes(StandardCharsets.UTF_8)));
+
+ AttachmentCallbackHandler attachmentCallbackHandler =
+ new
AttachmentCallbackHandler(Collections.singletonList(attachment));
+ encrypt.setAttachmentCallbackHandler(attachmentCallbackHandler);
+ List<Attachment> encryptedAttachments =
attachmentCallbackHandler.getResponseAttachments();
+
+ KeyGenerator keyGen = KeyUtils.getKeyGenerator(WSConstants.AES_128);
+ SecretKey symmetricKey = keyGen.generateKey();
+ Document encryptedDoc = encrypt.build(crypto, symmetricKey);
+
+ final AttachmentCallbackHandler finalAttachmentCallbackHandler =
+ new AttachmentCallbackHandler(encryptedAttachments);
+ WSSecurityException exception =
org.junit.jupiter.api.Assertions.assertThrows(
+ WSSecurityException.class, () -> verify(encryptedDoc,
finalAttachmentCallbackHandler));
+ assertEquals(WSSecurityException.ErrorCode.FAILED_CHECK,
exception.getErrorCode());
+ }
+
@Test
public void testMultipleAttachmentCompleteEncryption() throws Exception {
Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
@@ -835,17 +941,17 @@ public class AttachmentTest {
byte[] attachment1Bytes =
readInputStream(responseAttachment.getSourceStream());
assertTrue(Arrays.equals(attachment1Bytes,
SOAPUtil.SAMPLE_SOAP_MSG.getBytes(StandardCharsets.UTF_8)));
- assertEquals("text/xml", responseAttachment.getMimeType());
+ assertEquals("text/xml; charset=UTF-8",
responseAttachment.getMimeType());
Map<String, String> att1Headers = responseAttachment.getHeaders();
- assertEquals(6, att1Headers.size());
+ assertEquals(5, att1Headers.size());
responseAttachment =
attachmentCallbackHandler.getResponseAttachments().get(1);
byte[] attachment2Bytes =
readInputStream(responseAttachment.getSourceStream());
assertTrue(Arrays.equals(attachment2Bytes,
SOAPUtil.SAMPLE_SOAP_MSG.getBytes(StandardCharsets.UTF_8)));
- assertEquals("text/plain", responseAttachment.getMimeType());
+ assertEquals("text/xml; charset=UTF-8",
responseAttachment.getMimeType());
Map<String, String> att2Headers = responseAttachment.getHeaders();
- assertEquals(6, att2Headers.size());
+ assertEquals(5, att2Headers.size());
}
@Test
@@ -909,10 +1015,10 @@ public class AttachmentTest {
byte[] attachmentBytes =
readInputStream(responseAttachment.getSourceStream());
assertTrue(Arrays.equals(attachmentBytes,
SOAPUtil.SAMPLE_SOAP_MSG.getBytes(StandardCharsets.UTF_8)));
- assertEquals("text/xml", responseAttachment.getMimeType());
+ assertEquals("text/xml; charset=UTF-8",
responseAttachment.getMimeType());
Map<String, String> attHeaders = responseAttachment.getHeaders();
- assertEquals(6, attHeaders.size());
+ assertEquals(5, attHeaders.size());
}
@Test
@@ -998,7 +1104,7 @@ public class AttachmentTest {
List<Attachment> attachments = new ArrayList<>();
attachments.add(attachment[0]);
- if (attachment[0].getHeaders().size() == 6) {
+ if (attachment[0].getHeaders().size() == 5) {
//signature callback
attachment[0].addHeader(AttachmentUtils.MIME_HEADER_CONTENT_DESCRIPTION,
"Kaputt");
}
@@ -1077,10 +1183,10 @@ public class AttachmentTest {
byte[] attachmentBytes =
readInputStream(responseAttachment.getSourceStream());
assertTrue(Arrays.equals(attachmentBytes,
SOAPUtil.SAMPLE_SOAP_MSG.getBytes(StandardCharsets.UTF_8)));
- assertEquals("text/xml", responseAttachment.getMimeType());
+ assertEquals("text/xml; charset=UTF-8",
responseAttachment.getMimeType());
Map<String, String> attHeaders = responseAttachment.getHeaders();
- assertEquals(6, attHeaders.size());
+ assertEquals(5, attHeaders.size());
}
@Test
diff --git
a/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/input/DecryptInputProcessor.java
b/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/input/DecryptInputProcessor.java
index 709d8ca5a..c41267a3e 100644
---
a/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/input/DecryptInputProcessor.java
+++
b/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/input/DecryptInputProcessor.java
@@ -24,6 +24,7 @@ import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.security.Key;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -359,17 +360,24 @@ public class DecryptInputProcessor extends
AbstractDecryptInputProcessor {
Attachment resultAttachment = new Attachment();
resultAttachment.setId(attachment.getId());
- resultAttachment.setMimeType(encryptedDataType.getMimeType());
resultAttachment.setSourceStream(attachmentInputStream);
- resultAttachment.addHeaders(attachment.getHeaders());
if
(WSSConstants.SWA_ATTACHMENT_ENCRYPTED_DATA_TYPE_COMPLETE.equals(encryptedDataType.getType()))
{
+ Map<String, String> protectedHeaders = new HashMap<>();
try {
- AttachmentUtils.readAndReplaceEncryptedAttachmentHeaders(
- resultAttachment.getHeaders(), attachmentInputStream);
+
AttachmentUtils.readAndReplaceEncryptedAttachmentHeaders(protectedHeaders,
attachmentInputStream);
} catch (IOException e) {
throw new
WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY, e);
}
+ String contentType =
protectedHeaders.get(AttachmentUtils.MIME_HEADER_CONTENT_TYPE);
+ if (contentType == null) {
+ throw new
WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY);
+ }
+ resultAttachment.setMimeType(contentType);
+ resultAttachment.addHeaders(protectedHeaders);
+ } else {
+ resultAttachment.setMimeType(encryptedDataType.getMimeType());
+ resultAttachment.addHeaders(attachment.getHeaders());
}
AttachmentResultCallback attachmentResultCallback = new
AttachmentResultCallback();
diff --git
a/ws-security-stax/src/test/java/org/apache/wss4j/stax/test/AttachmentTest.java
b/ws-security-stax/src/test/java/org/apache/wss4j/stax/test/AttachmentTest.java
index 62d21dd8c..99eb15f4c 100644
---
a/ws-security-stax/src/test/java/org/apache/wss4j/stax/test/AttachmentTest.java
+++
b/ws-security-stax/src/test/java/org/apache/wss4j/stax/test/AttachmentTest.java
@@ -784,10 +784,10 @@ public class AttachmentTest extends AbstractTestBase {
Attachment responseAttachment =
attachmentCallbackHandler.getResponseAttachments().get(0);
byte[] attachmentBytes =
readInputStream(responseAttachment.getSourceStream());
assertTrue(Arrays.equals(attachmentBytes,
SOAPUtil.SAMPLE_SOAP_MSG.getBytes(StandardCharsets.UTF_8)));
- assertEquals("text/xml", responseAttachment.getMimeType());
+ assertEquals("text/xml; charset=UTF-8",
responseAttachment.getMimeType());
Map<String, String> attHeaders = responseAttachment.getHeaders();
- assertEquals(6, attHeaders.size());
+ assertEquals(5, attHeaders.size());
}
@Test
@@ -870,6 +870,138 @@ public class AttachmentTest extends AbstractTestBase {
}
}
+ // Regression test for CWE-345: a wire attacker cannot forge the delivered
MIME type of an
+ // Attachment-Complete encrypted attachment by tampering with the
unauthenticated
+ // xenc:EncryptedData/@MimeType attribute - the MIME type must be sourced
from the
+ // encrypted (protected) Content-Type header instead.
+ @Test
+ public void
testXMLAttachmentCompleteEncryptionTamperedMimeTypeAttributeIgnored() throws
Exception {
+
+ final String attachmentId = UUID.randomUUID().toString();
+ final Attachment attachment = new Attachment();
+ attachment.setMimeType("text/xml");
+ attachment.addHeaders(getHeaders(attachmentId));
+ attachment.setId(attachmentId);
+ attachment.setSourceStream(new
ByteArrayInputStream(SOAPUtil.SAMPLE_SOAP_MSG.getBytes(StandardCharsets.UTF_8)));
+
+ AttachmentCallbackHandler attachmentCallbackHandler =
+ new
AttachmentCallbackHandler(Collections.singletonList(attachment));
+ List<Attachment> encryptedAttachments =
attachmentCallbackHandler.getResponseAttachments();
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ {
+ WSSSecurityProperties securityProperties = new
WSSSecurityProperties();
+ List<WSSConstants.Action> actions = new ArrayList<>();
+ actions.add(WSSConstants.ENCRYPTION);
+ securityProperties.setActions(actions);
+
securityProperties.loadEncryptionKeystore(this.getClass().getClassLoader().getResource("transmitter.jks"),
"default".toCharArray());
+ securityProperties.setEncryptionUser("receiver");
+ securityProperties.addEncryptionPart(new SecurePart(new
QName("http://schemas.xmlsoap.org/soap/envelope/", "Body"),
SecurePart.Modifier.Content));
+ securityProperties.addEncryptionPart(new
SecurePart("cid:Attachments", SecurePart.Modifier.Element));
+
securityProperties.setAttachmentCallbackHandler(attachmentCallbackHandler);
+
+ OutboundWSSec wsSecOut =
WSSec.getOutboundWSSec(securityProperties);
+ XMLStreamWriter xmlStreamWriter = wsSecOut.processOutMessage(baos,
StandardCharsets.UTF_8.name(), new ArrayList<SecurityEvent>());
+ XMLStreamReader xmlStreamReader =
xmlInputFactory.createXMLStreamReader(this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml"));
+ XmlReaderToWriter.writeAll(xmlStreamReader, xmlStreamWriter);
+ xmlStreamWriter.close();
+ }
+
+ // Simulate a wire attacker rewriting the unauthenticated @MimeType
attribute
+ Document securedDoc =
documentBuilderFactory.newDocumentBuilder().parse(new
ByteArrayInputStream(baos.toByteArray()));
+ NodeList encDatas =
securedDoc.getElementsByTagNameNS(WSConstants.ENC_NS, "EncryptedData");
+ Element attachmentEncData = null;
+ for (int i = 0; i < encDatas.getLength(); i++) {
+ Element encData = (Element) encDatas.item(i);
+ if
(WSConstants.SWA_ATTACHMENT_ENCRYPTED_DATA_TYPE_COMPLETE.equals(encData.getAttributeNS(null,
"Type"))) {
+ attachmentEncData = encData;
+ break;
+ }
+ }
+ assertFalse(attachmentEncData == null);
+ attachmentEncData.setAttributeNS(null, "MimeType",
"application/malicious");
+ encryptedAttachments.get(0).getHeaders().put("X-Attacker-Controlled",
"forged");
+
+ ByteArrayOutputStream tamperedBaos = new ByteArrayOutputStream();
+ javax.xml.transform.TransformerFactory.newInstance().newTransformer()
+ .transform(new DOMSource(securedDoc), new
StreamResult(tamperedBaos));
+
+ attachmentCallbackHandler = new
AttachmentCallbackHandler(encryptedAttachments);
+ {
+ WSSSecurityProperties securityProperties = new
WSSSecurityProperties();
+
securityProperties.loadDecryptionKeystore(this.getClass().getClassLoader().getResource("receiver.jks"),
"default".toCharArray());
+ securityProperties.setCallbackHandler(new CallbackHandlerImpl());
+
securityProperties.setAttachmentCallbackHandler(attachmentCallbackHandler);
+
+ InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
+ XMLStreamReader xmlStreamReader =
wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new
ByteArrayInputStream(tamperedBaos.toByteArray())));
+ StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(),
xmlStreamReader);
+ }
+
+
assertFalse(attachmentCallbackHandler.getResponseAttachments().isEmpty());
+ Attachment responseAttachment =
attachmentCallbackHandler.getResponseAttachments().get(0);
+ byte[] attachmentBytes =
readInputStream(responseAttachment.getSourceStream());
+ assertTrue(Arrays.equals(attachmentBytes,
SOAPUtil.SAMPLE_SOAP_MSG.getBytes(StandardCharsets.UTF_8)));
+ assertEquals("text/xml; charset=UTF-8",
responseAttachment.getMimeType());
+ assertFalse(responseAttachment.getHeaders().containsKey("TestHeader"));
+
assertFalse(responseAttachment.getHeaders().containsKey("X-Attacker-Controlled"));
+ }
+
+ // Regression test for CWE-345: if the protected header block (inside the
ciphertext) does
+ // not contain a Content-Type header, decryption of an Attachment-Complete
attachment must
+ // fail closed rather than falling back to the unauthenticated MimeType
attribute.
+ @Test
+ public void
testXMLAttachmentCompleteEncryptionMissingProtectedContentType() throws
Exception {
+
+ final String attachmentId = UUID.randomUUID().toString();
+ final Attachment attachment = new Attachment();
+ attachment.setMimeType("text/xml");
+ Map<String, String> headers = getHeaders(attachmentId);
+ headers.remove(AttachmentUtils.MIME_HEADER_CONTENT_TYPE);
+ attachment.addHeaders(headers);
+ attachment.setId(attachmentId);
+ attachment.setSourceStream(new
ByteArrayInputStream(SOAPUtil.SAMPLE_SOAP_MSG.getBytes(StandardCharsets.UTF_8)));
+
+ AttachmentCallbackHandler attachmentCallbackHandler =
+ new
AttachmentCallbackHandler(Collections.singletonList(attachment));
+ List<Attachment> encryptedAttachments =
attachmentCallbackHandler.getResponseAttachments();
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ {
+ WSSSecurityProperties securityProperties = new
WSSSecurityProperties();
+ List<WSSConstants.Action> actions = new ArrayList<>();
+ actions.add(WSSConstants.ENCRYPTION);
+ securityProperties.setActions(actions);
+
securityProperties.loadEncryptionKeystore(this.getClass().getClassLoader().getResource("transmitter.jks"),
"default".toCharArray());
+ securityProperties.setEncryptionUser("receiver");
+ securityProperties.addEncryptionPart(new SecurePart(new
QName("http://schemas.xmlsoap.org/soap/envelope/", "Body"),
SecurePart.Modifier.Content));
+ securityProperties.addEncryptionPart(new
SecurePart("cid:Attachments", SecurePart.Modifier.Element));
+
securityProperties.setAttachmentCallbackHandler(attachmentCallbackHandler);
+
+ OutboundWSSec wsSecOut =
WSSec.getOutboundWSSec(securityProperties);
+ XMLStreamWriter xmlStreamWriter = wsSecOut.processOutMessage(baos,
StandardCharsets.UTF_8.name(), new ArrayList<SecurityEvent>());
+ XMLStreamReader xmlStreamReader =
xmlInputFactory.createXMLStreamReader(this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml"));
+ XmlReaderToWriter.writeAll(xmlStreamReader, xmlStreamWriter);
+ xmlStreamWriter.close();
+ }
+
+ attachmentCallbackHandler = new
AttachmentCallbackHandler(encryptedAttachments);
+ WSSSecurityProperties securityProperties = new WSSSecurityProperties();
+
securityProperties.loadDecryptionKeystore(this.getClass().getClassLoader().getResource("receiver.jks"),
"default".toCharArray());
+ securityProperties.setCallbackHandler(new CallbackHandlerImpl());
+
securityProperties.setAttachmentCallbackHandler(attachmentCallbackHandler);
+
+ InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
+ XMLStreamReader xmlStreamReader =
wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new
ByteArrayInputStream(baos.toByteArray())));
+ try {
+ StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(),
xmlStreamReader);
+ fail("Expected a WSSecurityException due to the missing protected
Content-Type header");
+ } catch (XMLStreamException e) {
+ assertTrue(e.getCause() instanceof WSSecurityException);
+ assertEquals(WSSecurityException.ErrorCode.INVALID_SECURITY,
((WSSecurityException) e.getCause()).getErrorCode());
+ }
+ }
+
@Test
public void testMultipleAttachmentCompleteEncryption() throws Exception {
@@ -928,17 +1060,17 @@ public class AttachmentTest extends AbstractTestBase {
byte[] attachment1Bytes =
readInputStream(responseAttachment.getSourceStream());
assertTrue(Arrays.equals(attachment1Bytes,
SOAPUtil.SAMPLE_SOAP_MSG.getBytes(StandardCharsets.UTF_8)));
- assertEquals("text/xml", responseAttachment.getMimeType());
+ assertEquals("text/xml; charset=UTF-8",
responseAttachment.getMimeType());
Map<String, String> att1Headers = responseAttachment.getHeaders();
- assertEquals(6, att1Headers.size());
+ assertEquals(5, att1Headers.size());
responseAttachment =
attachmentCallbackHandler.getResponseAttachments().get(1);
byte[] attachment2Bytes =
readInputStream(responseAttachment.getSourceStream());
assertTrue(Arrays.equals(attachment2Bytes,
SOAPUtil.SAMPLE_SOAP_MSG.getBytes(StandardCharsets.UTF_8)));
- assertEquals("text/plain", responseAttachment.getMimeType());
+ assertEquals("text/xml; charset=UTF-8",
responseAttachment.getMimeType());
Map<String, String> att2Headers = responseAttachment.getHeaders();
- assertEquals(6, att2Headers.size());
+ assertEquals(5, att2Headers.size());
}
@Test
@@ -1036,10 +1168,10 @@ public class AttachmentTest extends AbstractTestBase {
byte[] attachmentBytes =
readInputStream(attachment[0].getSourceStream());
assertTrue(Arrays.equals(attachmentBytes,
SOAPUtil.SAMPLE_SOAP_MSG.getBytes(StandardCharsets.UTF_8)));
- assertEquals("text/xml", attachment[0].getMimeType());
+ assertEquals("text/xml; charset=UTF-8", attachment[0].getMimeType());
Map<String, String> attHeaders = attachment[0].getHeaders();
- assertEquals(6, attHeaders.size());
+ assertEquals(5, attHeaders.size());
}
@Test
@@ -1111,7 +1243,7 @@ public class AttachmentTest extends AbstractTestBase {
List<Attachment> attachments = new ArrayList<>();
attachments.add(attachment[0]);
- if (attachment[0].getHeaders().size() == 6) {
+ if (attachment[0].getHeaders().size() == 5) {
//signature callback
attachment[0].addHeader(AttachmentUtils.MIME_HEADER_CONTENT_DESCRIPTION,
"Kaputt");
}
@@ -1230,10 +1362,10 @@ public class AttachmentTest extends AbstractTestBase {
byte[] attachmentBytes =
readInputStream(attachment[0].getSourceStream());
assertTrue(Arrays.equals(attachmentBytes,
SOAPUtil.SAMPLE_SOAP_MSG.getBytes(StandardCharsets.UTF_8)));
- assertEquals("text/xml", attachment[0].getMimeType());
+ assertEquals("text/xml; charset=UTF-8", attachment[0].getMimeType());
Map<String, String> attHeaders = attachment[0].getHeaders();
- assertEquals(6, attHeaders.size());
+ assertEquals(5, attHeaders.size());
}
@Test