Author: coheigea
Date: Tue Dec 10 15:48:25 2013
New Revision: 1549869
URL: http://svn.apache.org/r1549869
Log:
[WSS-481] - Problem with EncryptSignature + EndorsingSupportingTokens
Modified:
webservices/wss4j/trunk/ws-security-policy-stax/src/main/java/org/apache/wss4j/policy/stax/PolicyInputProcessor.java
webservices/wss4j/trunk/ws-security-policy-stax/src/main/java/org/apache/wss4j/policy/stax/assertionStates/SignatureProtectionAssertionState.java
webservices/wss4j/trunk/ws-security-policy-stax/src/test/java/org/apache/wss4j/policy/stax/test/AbstractPolicyTestBase.java
webservices/wss4j/trunk/ws-security-policy-stax/src/test/java/org/apache/wss4j/policy/stax/test/AsymmetricBindingIntegrationTest.java
webservices/wss4j/trunk/ws-security-policy-stax/src/test/java/org/apache/wss4j/policy/stax/test/AsymmetricBindingTest.java
webservices/wss4j/trunk/ws-security-policy-stax/src/test/java/org/apache/wss4j/policy/stax/test/SymmetricBindingTest.java
Modified:
webservices/wss4j/trunk/ws-security-policy-stax/src/main/java/org/apache/wss4j/policy/stax/PolicyInputProcessor.java
URL:
http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-policy-stax/src/main/java/org/apache/wss4j/policy/stax/PolicyInputProcessor.java?rev=1549869&r1=1549868&r2=1549869&view=diff
==============================================================================
---
webservices/wss4j/trunk/ws-security-policy-stax/src/main/java/org/apache/wss4j/policy/stax/PolicyInputProcessor.java
(original)
+++
webservices/wss4j/trunk/ws-security-policy-stax/src/main/java/org/apache/wss4j/policy/stax/PolicyInputProcessor.java
Tue Dec 10 15:48:25 2013
@@ -39,6 +39,8 @@ import org.apache.xml.security.stax.secu
import javax.xml.namespace.QName;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.events.Attribute;
+
import java.util.List;
/**
@@ -198,6 +200,7 @@ public class PolicyInputProcessor extend
EncryptedElementSecurityEvent encryptedElementSecurityEvent
= new EncryptedElementSecurityEvent(null, false,
null);
+
encryptedElementSecurityEvent.setCorrelationID(getId(xmlSecEvent));
encryptedElementSecurityEvent.setElementPath(elementPath);
policyEnforcer.registerSecurityEvent(encryptedElementSecurityEvent);
@@ -219,6 +222,29 @@ public class PolicyInputProcessor extend
break;
}
}
+
+ protected String getId(XMLSecEvent xmlSecEvent) {
+ XMLSecStartElement xmlSecStartElement = xmlSecEvent.asStartElement();
+ if (xmlSecStartElement.getOnElementDeclaredAttributes().size() >= 0) {
+ Attribute attribute =
xmlSecStartElement.getAttributeByName(WSSConstants.ATT_wsu_Id);
+ if (attribute != null) {
+ return attribute.getValue();
+ }
+ attribute =
xmlSecStartElement.getAttributeByName(WSSConstants.ATT_NULL_Id);
+ if (attribute != null) {
+ return attribute.getValue();
+ }
+ attribute =
xmlSecStartElement.getAttributeByName(WSSConstants.ATT_NULL_ID);
+ if (attribute != null) {
+ return attribute.getValue();
+ }
+ attribute =
xmlSecStartElement.getAttributeByName(WSSConstants.ATT_NULL_AssertionID);
+ if (attribute != null) {
+ return attribute.getValue();
+ }
+ }
+ return null;
+ }
protected void init(InputProcessorChain inputProcessorChain) {
if (!this.initDone) {
Modified:
webservices/wss4j/trunk/ws-security-policy-stax/src/main/java/org/apache/wss4j/policy/stax/assertionStates/SignatureProtectionAssertionState.java
URL:
http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-policy-stax/src/main/java/org/apache/wss4j/policy/stax/assertionStates/SignatureProtectionAssertionState.java?rev=1549869&r1=1549868&r2=1549869&view=diff
==============================================================================
---
webservices/wss4j/trunk/ws-security-policy-stax/src/main/java/org/apache/wss4j/policy/stax/assertionStates/SignatureProtectionAssertionState.java
(original)
+++
webservices/wss4j/trunk/ws-security-policy-stax/src/main/java/org/apache/wss4j/policy/stax/assertionStates/SignatureProtectionAssertionState.java
Tue Dec 10 15:48:25 2013
@@ -22,15 +22,20 @@ import org.apache.wss4j.policy.Assertion
import org.apache.wss4j.policy.WSSPolicyException;
import org.apache.wss4j.policy.model.AbstractSecurityAssertion;
import org.apache.wss4j.policy.model.AbstractSymmetricAsymmetricBinding;
+import org.apache.xml.security.exceptions.XMLSecurityException;
import
org.apache.xml.security.stax.securityEvent.EncryptedElementSecurityEvent;
import org.apache.xml.security.stax.securityEvent.SecurityEvent;
import org.apache.xml.security.stax.securityEvent.SecurityEventConstants;
+import org.apache.xml.security.stax.securityEvent.TokenSecurityEvent;
+import org.apache.xml.security.stax.securityToken.SecurityToken;
import org.apache.wss4j.policy.stax.Assertable;
import org.apache.wss4j.stax.ext.WSSConstants;
import org.apache.wss4j.stax.ext.WSSUtils;
import org.apache.wss4j.stax.securityEvent.WSSecurityEventConstants;
+import org.apache.wss4j.stax.securityToken.WSSecurityTokenConstants;
import javax.xml.namespace.QName;
+
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
@@ -41,6 +46,10 @@ import java.util.List;
*/
public class SignatureProtectionAssertionState extends AssertionState
implements Assertable {
+ private final ArrayList<EncryptedElementSecurityEvent>
encryptedElementEvents =
+ new ArrayList<EncryptedElementSecurityEvent>();
+ private final ArrayList<TokenSecurityEvent<? extends SecurityToken>>
tokenSecurityEvents =
+ new ArrayList<TokenSecurityEvent<? extends SecurityToken>>();
private final List<List<QName>> elementPaths = new
ArrayList<List<QName>>();
public SignatureProtectionAssertionState(AbstractSecurityAssertion
assertion, boolean asserted) {
@@ -61,42 +70,144 @@ public class SignatureProtectionAssertio
@Override
public SecurityEventConstants.Event[] getSecurityEventType() {
return new SecurityEventConstants.Event[]{
- WSSecurityEventConstants.EncryptedElement
+ WSSecurityEventConstants.EncryptedElement,
+ WSSecurityEventConstants.EncryptedKeyToken,
+ WSSecurityEventConstants.IssuedToken,
+ WSSecurityEventConstants.KerberosToken,
+ SecurityEventConstants.KeyValueToken,
+ WSSecurityEventConstants.RelToken,
+ WSSecurityEventConstants.SamlToken,
+ WSSecurityEventConstants.SecurityContextToken,
+ WSSecurityEventConstants.UsernameToken,
+ SecurityEventConstants.X509Token,
+ WSSecurityEventConstants.Operation,
};
}
-
+
@Override
public boolean assertEvent(SecurityEvent securityEvent) throws
WSSPolicyException {
- EncryptedElementSecurityEvent encryptedElementSecurityEvent =
(EncryptedElementSecurityEvent) securityEvent;
- AbstractSymmetricAsymmetricBinding abstractSymmetricAsymmetricBinding
= (AbstractSymmetricAsymmetricBinding) getAssertion();
- //todo better matching until we have a streaming xpath evaluation
engine (work in progress)
-
- Iterator<List<QName>> pathElementsIterator = elementPaths.iterator();
- while (pathElementsIterator.hasNext()) {
- List<QName> qNameList = pathElementsIterator.next();
- if (WSSUtils.pathMatches(qNameList,
encryptedElementSecurityEvent.getElementPath(), true, false)) {
- if (encryptedElementSecurityEvent.isEncrypted()) {
- if
(abstractSymmetricAsymmetricBinding.isEncryptSignature()) {
- setAsserted(true);
- return true;
- } else {
- setAsserted(false);
- setErrorMessage("Element " +
WSSUtils.pathAsString(encryptedElementSecurityEvent.getElementPath()) + " must
not be encrypted");
- return false;
- }
- } else {
- if
(abstractSymmetricAsymmetricBinding.isEncryptSignature()) {
- setAsserted(false);
- setErrorMessage("Element " +
WSSUtils.pathAsString(encryptedElementSecurityEvent.getElementPath()) + " must
be encrypted");
- return false;
- } else {
- setAsserted(true);
- return true;
- }
+ if (securityEvent instanceof EncryptedElementSecurityEvent) {
+ EncryptedElementSecurityEvent encryptedElementSecurityEvent =
+ (EncryptedElementSecurityEvent) securityEvent;
+ // Store all matching Signature/SignatureConfirmation Elements
+ Iterator<List<QName>> pathElementsIterator =
elementPaths.iterator();
+ while (pathElementsIterator.hasNext()) {
+ List<QName> qNameList = pathElementsIterator.next();
+ if (WSSUtils.pathMatches(qNameList,
encryptedElementSecurityEvent.getElementPath(), true, false)) {
+ encryptedElementEvents.add(encryptedElementSecurityEvent);
+ }
+ }
+ } else if (securityEvent instanceof TokenSecurityEvent) {
+ @SuppressWarnings("unchecked")
+ TokenSecurityEvent<? extends SecurityToken> tokenSecurityEvent
+ = (TokenSecurityEvent<? extends SecurityToken>) securityEvent;
+ tokenSecurityEvents.add(tokenSecurityEvent);
+ }
+
+ return true;
+ }
+
+ @Override
+ public boolean isAsserted() {
+ clearErrorMessage();
+
+ // If we only have one (main) Signature, then check that it matches
the policy
+ if (encryptedElementEvents.size() == 1) {
+ return testEncryptedSignature(encryptedElementEvents.get(0));
+ } else if (encryptedElementEvents.size() > 1) {
+ // Otherwise we only check the policy for the main Signature
+ String endorsingSignatureId = findEndorsingSignatureId();
+ for (EncryptedElementSecurityEvent encryptedElementSecurityEvent :
encryptedElementEvents) {
+ String elementId =
encryptedElementSecurityEvent.getCorrelationID();
+ if (endorsingSignatureId != null &&
endorsingSignatureId.equals(elementId)) {
+ // Skip this Endorsing Signature
+ continue;
+ }
+ if (!testEncryptedSignature(encryptedElementSecurityEvent)) {
+ return false;
}
}
}
- //if we return false here other encrypted elements will trigger a
PolicyViolationException
+
return true;
}
+
+ private String findEndorsingSignatureId() {
+ for (int i = 0; i < tokenSecurityEvents.size(); i++) {
+ TokenSecurityEvent<? extends SecurityToken> tokenSecurityEvent =
tokenSecurityEvents.get(i);
+ try {
+ SecurityToken securityToken =
+
getEffectiveSignatureToken(tokenSecurityEvent.getSecurityToken());
+ if (isSignatureToken(securityToken) &&
!isMainSignatureToken(securityToken)) {
+ return tokenSecurityEvent.getCorrelationID();
+ }
+ } catch (XMLSecurityException e) {
+ // Just return null here
+ return null;
+ }
+ }
+ return null;
+ }
+
+ private boolean isSignatureToken(SecurityToken securityToken) {
+ List<WSSecurityTokenConstants.TokenUsage> tokenUsages =
securityToken.getTokenUsages();
+ for (int i = 0; i < tokenUsages.size(); i++) {
+ WSSecurityTokenConstants.TokenUsage tokenUsage =
tokenUsages.get(i);
+ if
(WSSecurityTokenConstants.TokenUsage_Signature.equals(tokenUsage)
+ ||
WSSecurityTokenConstants.TokenUsage_MainSignature.equals(tokenUsage)
+ || tokenUsage.getName().contains("Endorsing")) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean isMainSignatureToken(SecurityToken securityToken) throws
XMLSecurityException {
+ SecurityToken rootToken = WSSUtils.getRootToken(securityToken);
+ List<WSSecurityTokenConstants.TokenUsage> tokenUsages =
rootToken.getTokenUsages();
+ return
tokenUsages.contains(WSSecurityTokenConstants.TokenUsage_MainSignature);
+ }
+
+ private SecurityToken getEffectiveSignatureToken(SecurityToken
securityToken) throws XMLSecurityException {
+ SecurityToken tmp = WSSUtils.getRootToken(securityToken);
+ List<? extends SecurityToken> wrappedTokens = tmp.getWrappedTokens();
+ for (int i = 0; i < wrappedTokens.size(); i++) {
+ SecurityToken token = wrappedTokens.get(i);
+ if (isSignatureToken(token)) {
+ //WSP 1.3, 6.5 [Token Protection] Property: Note that in cases
where derived keys are used
+ //the 'main' token, and NOT the derived key token, is covered
by the signature.
+ if
(WSSecurityTokenConstants.DerivedKeyToken.equals(token.getTokenType())) {
+ return tmp;
+ }
+ tmp = token;
+ }
+ }
+ return tmp;
+ }
+
+ private boolean testEncryptedSignature(EncryptedElementSecurityEvent
encryptedElementSecurityEvent) {
+ AbstractSymmetricAsymmetricBinding abstractSymmetricAsymmetricBinding
=
+ (AbstractSymmetricAsymmetricBinding) getAssertion();
+
+ if (encryptedElementSecurityEvent.isEncrypted()) {
+ if (abstractSymmetricAsymmetricBinding.isEncryptSignature()) {
+ setAsserted(true);
+ return true;
+ } else {
+ setAsserted(false);
+ setErrorMessage("Element " +
WSSUtils.pathAsString(encryptedElementSecurityEvent.getElementPath()) + " must
not be encrypted");
+ return false;
+ }
+ } else {
+ if (abstractSymmetricAsymmetricBinding.isEncryptSignature()) {
+ setAsserted(false);
+ setErrorMessage("Element " +
WSSUtils.pathAsString(encryptedElementSecurityEvent.getElementPath()) + " must
be encrypted");
+ return false;
+ } else {
+ setAsserted(true);
+ return true;
+ }
+ }
+ }
+
}
Modified:
webservices/wss4j/trunk/ws-security-policy-stax/src/test/java/org/apache/wss4j/policy/stax/test/AbstractPolicyTestBase.java
URL:
http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-policy-stax/src/test/java/org/apache/wss4j/policy/stax/test/AbstractPolicyTestBase.java?rev=1549869&r1=1549868&r2=1549869&view=diff
==============================================================================
---
webservices/wss4j/trunk/ws-security-policy-stax/src/test/java/org/apache/wss4j/policy/stax/test/AbstractPolicyTestBase.java
(original)
+++
webservices/wss4j/trunk/ws-security-policy-stax/src/test/java/org/apache/wss4j/policy/stax/test/AbstractPolicyTestBase.java
Tue Dec 10 15:48:25 2013
@@ -44,6 +44,7 @@ import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
+import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
@@ -54,6 +55,7 @@ import java.io.InputStreamReader;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
+import java.util.Collections;
import java.util.List;
public class AbstractPolicyTestBase extends AbstractTestBase {
@@ -121,6 +123,15 @@ public class AbstractPolicyTestBase exte
protected String getAlias() throws XMLSecurityException {
return keyAlias;
}
+
+ @Override
+ public List<QName> getElementPath() {
+ List<QName> elementPath = super.getElementPath();
+ if (elementPath != null) {
+ return elementPath;
+ }
+ return Collections.emptyList();
+ }
};
x509SecurityToken.setSecretKey("", keyStore.getKey(keyAlias,
"default".toCharArray()));
x509SecurityToken.setPublicKey(keyStore.getCertificate(keyAlias).getPublicKey());
Modified:
webservices/wss4j/trunk/ws-security-policy-stax/src/test/java/org/apache/wss4j/policy/stax/test/AsymmetricBindingIntegrationTest.java
URL:
http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-policy-stax/src/test/java/org/apache/wss4j/policy/stax/test/AsymmetricBindingIntegrationTest.java?rev=1549869&r1=1549868&r2=1549869&view=diff
==============================================================================
---
webservices/wss4j/trunk/ws-security-policy-stax/src/test/java/org/apache/wss4j/policy/stax/test/AsymmetricBindingIntegrationTest.java
(original)
+++
webservices/wss4j/trunk/ws-security-policy-stax/src/test/java/org/apache/wss4j/policy/stax/test/AsymmetricBindingIntegrationTest.java
Tue Dec 10 15:48:25 2013
@@ -1716,8 +1716,6 @@ public class AsymmetricBindingIntegratio
Assert.fail("Exception expected");
} catch (XMLStreamException e) {
Assert.assertTrue(e.getCause() instanceof WSSecurityException);
- Assert.assertEquals(e.getCause().getMessage(),
- "Element
/{http://schemas.xmlsoap.org/soap/envelope/}Envelope/{http://schemas.xmlsoap.org/soap/envelope/}Header/{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd}Security/{http://www.w3.org/2000/09/xmldsig#}Signature
must be encrypted");
Assert.assertEquals(((WSSecurityException)
e.getCause()).getFaultCode(), WSSecurityException.INVALID_SECURITY);
}
}
Modified:
webservices/wss4j/trunk/ws-security-policy-stax/src/test/java/org/apache/wss4j/policy/stax/test/AsymmetricBindingTest.java
URL:
http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-policy-stax/src/test/java/org/apache/wss4j/policy/stax/test/AsymmetricBindingTest.java?rev=1549869&r1=1549868&r2=1549869&view=diff
==============================================================================
---
webservices/wss4j/trunk/ws-security-policy-stax/src/test/java/org/apache/wss4j/policy/stax/test/AsymmetricBindingTest.java
(original)
+++
webservices/wss4j/trunk/ws-security-policy-stax/src/test/java/org/apache/wss4j/policy/stax/test/AsymmetricBindingTest.java
Tue Dec 10 15:48:25 2013
@@ -241,8 +241,6 @@ public class AsymmetricBindingTest exten
Assert.fail("Exception expected");
} catch (WSSecurityException e) {
Assert.assertTrue(e.getCause() instanceof
PolicyViolationException);
- Assert.assertEquals(e.getCause().getMessage(),
- "Element
/{http://schemas.xmlsoap.org/soap/envelope/}Envelope/{http://schemas.xmlsoap.org/soap/envelope/}Header/{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd}Security/{http://www.w3.org/2000/09/xmldsig#}Signature
must be encrypted");
Assert.assertEquals(e.getFaultCode(),
WSSecurityException.INVALID_SECURITY);
}
}
Modified:
webservices/wss4j/trunk/ws-security-policy-stax/src/test/java/org/apache/wss4j/policy/stax/test/SymmetricBindingTest.java
URL:
http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-policy-stax/src/test/java/org/apache/wss4j/policy/stax/test/SymmetricBindingTest.java?rev=1549869&r1=1549868&r2=1549869&view=diff
==============================================================================
---
webservices/wss4j/trunk/ws-security-policy-stax/src/test/java/org/apache/wss4j/policy/stax/test/SymmetricBindingTest.java
(original)
+++
webservices/wss4j/trunk/ws-security-policy-stax/src/test/java/org/apache/wss4j/policy/stax/test/SymmetricBindingTest.java
Tue Dec 10 15:48:25 2013
@@ -253,7 +253,6 @@ public class SymmetricBindingTest extend
policyEnforcer.registerSecurityEvent(operationSecurityEvent);
Assert.fail("Exception expected");
} catch (WSSecurityException e) {
- Assert.assertTrue(e.getCause() instanceof
PolicyViolationException);
Assert.assertEquals(e.getCause().getMessage(),
"Element
/{http://schemas.xmlsoap.org/soap/envelope/}Envelope/{http://schemas.xmlsoap.org/soap/envelope/}Header/{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd}Security/{http://www.w3.org/2000/09/xmldsig#}Signature
must be encrypted");
Assert.assertEquals(e.getFaultCode(),
WSSecurityException.INVALID_SECURITY);