Author: giger
Date: Sun Nov 24 11:36:22 2013
New Revision: 1544959
URL: http://svn.apache.org/r1544959
Log:
WSS-484 - Streaming code can't process a Key reference pointing to an
EncryptedData element
Modified:
webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/input/EncryptedDataInputHandler.java
webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/input/SecurityHeaderInputProcessor.java
webservices/wss4j/trunk/ws-security-stax/src/test/java/org/apache/wss4j/stax/test/SignatureEncryptionTest.java
Modified:
webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/input/EncryptedDataInputHandler.java
URL:
http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/input/EncryptedDataInputHandler.java?rev=1544959&r1=1544958&r2=1544959&view=diff
==============================================================================
---
webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/input/EncryptedDataInputHandler.java
(original)
+++
webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/input/EncryptedDataInputHandler.java
Sun Nov 24 11:36:22 2013
@@ -25,19 +25,18 @@ import org.apache.wss4j.stax.ext.WSSSecu
import org.apache.xml.security.binding.xmlenc.ReferenceList;
import org.apache.xml.security.binding.xmlenc.ReferenceType;
import org.apache.xml.security.exceptions.XMLSecurityException;
-import org.apache.xml.security.stax.ext.AbstractInputSecurityHeaderHandler;
-import org.apache.xml.security.stax.ext.InputProcessorChain;
-import org.apache.xml.security.stax.ext.XMLSecurityConstants;
-import org.apache.xml.security.stax.ext.XMLSecurityProperties;
+import org.apache.xml.security.stax.ext.*;
import org.apache.xml.security.stax.ext.stax.XMLSecEvent;
import org.apache.xml.security.stax.ext.stax.XMLSecStartElement;
+import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.Attribute;
import java.util.Deque;
-import java.util.Iterator;
/**
- * Processor for the EncryptedData XML Structure in the security header
+ * Processor for the EncryptedData XML Structure in the security header.
+ * Note, this handler is special in respect to when it is called: it is
triggered by the
+ * EncryptedData StartElement and not when the EndElement occurs. @see
comments in SecurityHeaderInputProcessort
*/
public class EncryptedDataInputHandler extends
AbstractInputSecurityHeaderHandler {
@@ -45,12 +44,7 @@ public class EncryptedDataInputHandler e
public void handle(final InputProcessorChain inputProcessorChain, final
XMLSecurityProperties securityProperties,
final Deque<XMLSecEvent> eventQueue, final Integer
index) throws XMLSecurityException {
- XMLSecEvent xmlSecEvent = null;
- final Iterator<XMLSecEvent> xmlSecEventIterator =
eventQueue.descendingIterator();
- int curIdx = 0;
- while (curIdx++ <= index) {
- xmlSecEvent = xmlSecEventIterator.next();
- }
+ XMLSecEvent xmlSecEvent = eventQueue.pollFirst();
if (!(xmlSecEvent instanceof XMLSecStartElement)) {
throw new
WSSecurityException(WSSecurityException.ErrorCode.FAILURE);
}
@@ -70,12 +64,28 @@ public class EncryptedDataInputHandler e
referenceType.setURI("#" + uri);
inputProcessorChain.getSecurityContext().putAsList(WSSConstants.PROP_ENCRYPTED_DATA_REFS,
uri);
}
- inputProcessorChain.removeProcessor(this);
return referenceType;
}
return null;
}
};
inputProcessorChain.addProcessor(decryptInputProcessor);
+
+ //replay the EncryptedData event for the DecryptInputProcessor:
+ InputProcessor tmpProcessor = new
AbstractInputProcessor(securityProperties) {
+ @Override
+ public XMLSecEvent processNextHeaderEvent(InputProcessorChain
inputProcessorChain) throws XMLStreamException, XMLSecurityException {
+ inputProcessorChain.removeProcessor(this);
+ return encryptedDataElement;
+ }
+
+ @Override
+ public XMLSecEvent processNextEvent(InputProcessorChain
inputProcessorChain) throws XMLStreamException, XMLSecurityException {
+ inputProcessorChain.removeProcessor(this);
+ return encryptedDataElement;
+ }
+ };
+ tmpProcessor.addBeforeProcessor(decryptInputProcessor);
+ inputProcessorChain.addProcessor(tmpProcessor);
}
}
Modified:
webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/input/SecurityHeaderInputProcessor.java
URL:
http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/input/SecurityHeaderInputProcessor.java?rev=1544959&r1=1544958&r2=1544959&view=diff
==============================================================================
---
webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/input/SecurityHeaderInputProcessor.java
(original)
+++
webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/input/SecurityHeaderInputProcessor.java
Sun Nov 24 11:36:22 2013
@@ -54,7 +54,6 @@ public class SecurityHeaderInputProcesso
org.slf4j.LoggerFactory.getLogger(SecurityHeaderInputProcessor.class);
private final ArrayDeque<XMLSecEvent> xmlSecEventList = new
ArrayDeque<XMLSecEvent>();
- private int eventCount = 0;
private int startIndexForProcessor = 0;
public SecurityHeaderInputProcessor(WSSSecurityProperties
securityProperties) {
@@ -85,7 +84,6 @@ public class SecurityHeaderInputProcesso
do {
subInputProcessorChain.reset();
xmlSecEvent = subInputProcessorChain.processHeaderEvent();
- eventCount++;
switch (xmlSecEvent.getEventType()) {
case XMLStreamConstants.START_ELEMENT:
@@ -109,7 +107,15 @@ public class SecurityHeaderInputProcesso
} else if (documentLevel == 4 &&
responsibleSecurityHeaderFound
&& WSSUtils.isInSecurityHeader(xmlSecStartElement,
((WSSSecurityProperties)
getSecurityProperties()).getActor())) {
- startIndexForProcessor = eventCount - 1;
+ startIndexForProcessor = xmlSecEventList.size() - 1;
+
+ //special handling for EncryptedData in the
SecurityHeader. This way, if for example
+ // a token was encrypted we have the possibility to
decrypt it before so that we
+ // are able to engage the appropriate processor for
the token.
+ if
(WSSConstants.TAG_xenc_EncryptedData.equals(xmlSecStartElement.getName())) {
+
engageSecurityHeaderHandler(subInputProcessorChain, getSecurityProperties(),
+ xmlSecEventList, startIndexForProcessor,
xmlSecStartElement.getName());
+ }
}
break;
case XMLStreamConstants.END_ELEMENT:
@@ -126,9 +132,12 @@ public class SecurityHeaderInputProcesso
&& WSSUtils.isInSecurityHeader(xmlSecEndElement,
((WSSSecurityProperties)
getSecurityProperties()).getActor())) {
//we are in the security header and the depth is +1,
so every child
- //element should have a responsible handler:
- engageSecurityHeaderHandler(subInputProcessorChain,
getSecurityProperties(),
- xmlSecEventList, startIndexForProcessor,
xmlSecEndElement.getName());
+ //element should have a responsible handler with the
exception of an EncryptedData SecurityHeader
+ //which is already handled in the above StartElement
logic (@see comment above).
+ if
(!WSSConstants.TAG_xenc_EncryptedData.equals(xmlSecEndElement.getName())) {
+
engageSecurityHeaderHandler(subInputProcessorChain, getSecurityProperties(),
+ xmlSecEventList, startIndexForProcessor,
xmlSecEndElement.getName());
+ }
// Check for multiple timestamps
if
(xmlSecEndElement.getName().equals(WSSConstants.TAG_wsu_Timestamp)) {
Modified:
webservices/wss4j/trunk/ws-security-stax/src/test/java/org/apache/wss4j/stax/test/SignatureEncryptionTest.java
URL:
http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-stax/src/test/java/org/apache/wss4j/stax/test/SignatureEncryptionTest.java?rev=1544959&r1=1544958&r2=1544959&view=diff
==============================================================================
---
webservices/wss4j/trunk/ws-security-stax/src/test/java/org/apache/wss4j/stax/test/SignatureEncryptionTest.java
(original)
+++
webservices/wss4j/trunk/ws-security-stax/src/test/java/org/apache/wss4j/stax/test/SignatureEncryptionTest.java
Sun Nov 24 11:36:22 2013
@@ -24,14 +24,24 @@ import java.io.InputStream;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
+import java.util.List;
import javax.crypto.KeyGenerator;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamWriter;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import org.apache.wss4j.common.WSEncryptionPart;
+import org.apache.wss4j.common.crypto.Crypto;
+import org.apache.wss4j.common.crypto.CryptoFactory;
import org.apache.wss4j.common.ext.WSSecurityException;
+import org.apache.wss4j.dom.WSConstants;
import org.apache.wss4j.dom.handler.WSHandlerConstants;
+import org.apache.wss4j.dom.message.WSSecEncrypt;
+import org.apache.wss4j.dom.message.WSSecHeader;
+import org.apache.wss4j.dom.message.WSSecSignature;
import org.apache.wss4j.stax.WSSec;
import org.apache.wss4j.stax.ext.OutboundWSSec;
import org.apache.wss4j.stax.ext.WSSConstants;
@@ -47,7 +57,11 @@ import org.apache.xml.security.stax.impl
import org.apache.xml.security.stax.securityEvent.SecurityEvent;
import org.apache.xml.security.stax.securityToken.OutboundSecurityToken;
import org.apache.xml.security.stax.securityToken.SecurityTokenProvider;
+import org.testng.Assert;
import org.testng.annotations.Test;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
public class SignatureEncryptionTest extends AbstractTestBase {
@@ -249,4 +263,54 @@ public class SignatureEncryptionTest ext
}
}
+ @Test
+ public void testEncryptedDataTokenSecurityHeaderWithoutReferenceInbound()
throws Exception {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ {
+ InputStream sourceDocument =
this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
+
+ Document doc =
documentBuilderFactory.newDocumentBuilder().parse(sourceDocument);
+
+ WSSecHeader secHeader = new WSSecHeader();
+ secHeader.insertSecurityHeader(doc);
+
+ WSSecSignature sign = new WSSecSignature();
+ sign.setUserInfo("transmitter", "default");
+ sign.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
+
+ Crypto crypto =
CryptoFactory.getInstance("transmitter-crypto.properties");
+
+ sign.build(doc, crypto, secHeader);
+
+ WSSecEncrypt builder = new WSSecEncrypt();
+ builder.setKeyIdentifierType(WSConstants.THUMBPRINT_IDENTIFIER);
+ builder.setUserInfo("receiver");
+ builder.prepare(doc, crypto);
+
+ WSEncryptionPart bst = new WSEncryptionPart("BinarySecurityToken",
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd",
"Element");
+ WSEncryptionPart def = new WSEncryptionPart("definitions",
"http://schemas.xmlsoap.org/wsdl/", "Element");
+ List<WSEncryptionPart> encryptionParts = new
ArrayList<WSEncryptionPart>();
+ encryptionParts.add(bst);
+ encryptionParts.add(def);
+ Element ref = builder.encryptForRef(null, encryptionParts);
+
ref.removeChild(ref.getElementsByTagNameNS("http://www.w3.org/2001/04/xmlenc#",
"DataReference").item(0));
+ builder.addExternalRefElement(ref, secHeader);
+ builder.prependToHeader(secHeader);
+
+ javax.xml.transform.Transformer transformer =
TRANSFORMER_FACTORY.newTransformer();
+ transformer.transform(new DOMSource(doc), new StreamResult(baos));
+ }
+
+ //done encryption; now test decryption:
+ {
+ WSSSecurityProperties securityProperties = new
WSSSecurityProperties();
+
securityProperties.loadDecryptionKeystore(this.getClass().getClassLoader().getResource("receiver.jks"),
"default".toCharArray());
+ securityProperties.setCallbackHandler(new CallbackHandlerImpl());
+ Document document = doInboundSecurity(securityProperties,
xmlInputFactory.createXMLStreamReader(new
ByteArrayInputStream(baos.toByteArray())));
+
+ //no encrypted content
+ NodeList nodeList =
document.getElementsByTagNameNS(WSSConstants.TAG_xenc_EncryptedData.getNamespaceURI(),
WSSConstants.TAG_xenc_EncryptedData.getLocalPart());
+ Assert.assertEquals(nodeList.getLength(), 0);
+ }
+ }
}