This is an automated email from the ASF dual-hosted git repository.
coheigea pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ws-wss4j.git
The following commit(s) were added to refs/heads/master by this push:
new ef2bb58a7 Fix issues with SignedElements / EncryptedElements (#682)
ef2bb58a7 is described below
commit ef2bb58a7fda08612cd94dc6d5e1464f2995dd0e
Author: Colm O hEigeartaigh <[email protected]>
AuthorDate: Wed Sep 9 14:18:33 2026 +0100
Fix issues with SignedElements / EncryptedElements (#682)
---
.../org/apache/wss4j/policy/stax/PolicyUtils.java | 111 +++++++++++++++++++--
.../ContentEncryptedElementsAssertionState.java | 14 ++-
.../EncryptedElementsAssertionState.java | 14 ++-
.../RequiredElementsAssertionState.java | 22 ++--
.../SignedElementsAssertionState.java | 14 +--
.../test/AsymmetricBindingIntegrationTest.java | 18 ----
.../wss4j/policy/stax/test/SignedElementsTest.java | 49 +++++++++
7 files changed, 183 insertions(+), 59 deletions(-)
diff --git
a/ws-security-policy-stax/src/main/java/org/apache/wss4j/policy/stax/PolicyUtils.java
b/ws-security-policy-stax/src/main/java/org/apache/wss4j/policy/stax/PolicyUtils.java
index 16de0768e..6aa5309b7 100644
---
a/ws-security-policy-stax/src/main/java/org/apache/wss4j/policy/stax/PolicyUtils.java
+++
b/ws-security-policy-stax/src/main/java/org/apache/wss4j/policy/stax/PolicyUtils.java
@@ -18,37 +18,134 @@
*/
package org.apache.wss4j.policy.stax;
+import org.apache.wss4j.common.WSSPolicyException;
import org.apache.wss4j.policy.model.XPath;
+import org.apache.wss4j.stax.utils.WSSUtils;
import javax.xml.namespace.QName;
import java.util.ArrayList;
import java.util.List;
+import java.util.regex.Pattern;
public final class PolicyUtils {
+ // Conservative approximation of an XML NCName; rejects wildcards ("*"),
predicates
+ // (e.g. "Body[1]") and functions, which getElementPath cannot represent
as a QName step.
+ private static final Pattern NCNAME_PATTERN =
Pattern.compile("^[A-Za-z_][\\w.-]*$");
+
private PolicyUtils() {
// complete
}
+ /**
+ * Parses an XPath into raw QName steps.
+ */
public static List<QName> getElementPath(XPath xPath) {
+ try {
+ return getElementPathDescriptor(xPath).getPath();
+ } catch (WSSPolicyException e) {
+ throw new IllegalArgumentException(e.getMessage(), e);
+ }
+ }
+
+ /**
+ * Parses a sp:XPath expression into validated element steps. Only chains
of plain
+ * prefix:localName (or localName) steps are supported, either absolute
(leading "/") or
+ * relative; wildcards, predicates, functions and descendant ("//") steps
are rejected
+ * instead of silently producing a path that could never match a real
element (CWE-347).
+ */
+ public static ElementPath getElementPathDescriptor(XPath xPath) throws
WSSPolicyException {
+ String xPathString = xPath.getXPath();
+ if (xPathString == null || xPathString.isEmpty()) {
+ throw new WSSPolicyException("Empty XPath expression");
+ }
+ boolean absolute = xPathString.charAt(0) == '/';
+
List<QName> elements = new ArrayList<>();
- String[] xPathElements = xPath.getXPath().split("/");
+ String[] xPathElements = xPathString.split("/");
for (int j = 0; j < xPathElements.length; j++) {
String xPathElement = xPathElements[j];
- if (xPathElement == null || xPathElement.length() == 0) {
- continue;
+ if (xPathElement.isEmpty()) {
+ // only the leading '/' of an absolute path may produce an
empty step;
+ // any other empty step means a "//" descendant axis, which
isn't supported
+ if (absolute && j == 0) {
+ continue;
+ }
+ throw new WSSPolicyException(
+ "Unsupported XPath expression, descendant ('//') steps are
not supported: " + xPathString);
}
String[] elementParts = xPathElement.split(":");
- if (elementParts.length == 2) {
+ if (elementParts.length == 2 && isNCName(elementParts[0]) &&
isNCName(elementParts[1])) {
String ns = xPath.getPrefixNamespaceMap().get(elementParts[0]);
if (ns == null) {
- throw new IllegalArgumentException("Namespace not
declared");
+ throw new WSSPolicyException("Namespace not declared for
prefix: " + elementParts[0]);
}
elements.add(new QName(ns, elementParts[1]));
- } else {
+ } else if (elementParts.length == 1 && isNCName(elementParts[0])) {
elements.add(new QName(elementParts[0]));
+ } else {
+ throw new WSSPolicyException(
+ "Unsupported XPath step (wildcards, predicates and
functions are not supported): "
+ + xPathElement);
}
}
- return elements;
+ return new ElementPath(elements, absolute);
+ }
+
+ private static boolean isNCName(String name) {
+ return NCNAME_PATTERN.matcher(name).matches();
+ }
+
+ /**
+ * Wraps an already fully-qualified, absolute element path (e.g. a
well-known SOAP header
+ * path built in code) as an ElementPath that must match the observed path
exactly.
+ */
+ public static ElementPath absoluteElementPath(List<QName> path) {
+ return new ElementPath(path, true);
+ }
+
+ /**
+ * The element steps parsed from a sp:XPath expression. An absolute path
must match the
+ * observed element path exactly; a relative path must match its trailing
steps (tail).
+ */
+ public static final class ElementPath {
+ private final List<QName> path;
+ private final boolean absolute;
+
+ private ElementPath(List<QName> path, boolean absolute) {
+ this.path = path;
+ this.absolute = absolute;
+ }
+
+ public List<QName> getPath() {
+ return path;
+ }
+
+ public boolean matches(List<QName> observedPath) {
+ if (absolute) {
+ return WSSUtils.pathMatches(path, observedPath);
+ }
+ if (observedPath == null || observedPath.size() < path.size()) {
+ return false;
+ }
+ return WSSUtils.pathMatches(path,
observedPath.subList(observedPath.size() - path.size(), observedPath.size()));
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof ElementPath)) {
+ return false;
+ }
+ ElementPath other = (ElementPath) o;
+ return absolute == other.absolute && path.equals(other.path);
+ }
+
+ @Override
+ public int hashCode() {
+ return path.hashCode() * 31 + (absolute ? 1 : 0);
+ }
}
}
diff --git
a/ws-security-policy-stax/src/main/java/org/apache/wss4j/policy/stax/assertionStates/ContentEncryptedElementsAssertionState.java
b/ws-security-policy-stax/src/main/java/org/apache/wss4j/policy/stax/assertionStates/ContentEncryptedElementsAssertionState.java
index 3e00acd31..f8634729d 100644
---
a/ws-security-policy-stax/src/main/java/org/apache/wss4j/policy/stax/assertionStates/ContentEncryptedElementsAssertionState.java
+++
b/ws-security-policy-stax/src/main/java/org/apache/wss4j/policy/stax/assertionStates/ContentEncryptedElementsAssertionState.java
@@ -33,8 +33,6 @@ import org.apache.wss4j.policy.stax.PolicyUtils;
import org.apache.wss4j.stax.securityEvent.WSSecurityEventConstants;
import org.apache.wss4j.stax.utils.WSSUtils;
-import javax.xml.namespace.QName;
-
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
@@ -44,18 +42,18 @@ import java.util.List;
*/
public class ContentEncryptedElementsAssertionState extends AssertionState
implements Assertable {
- private final List<List<QName>> pathElements = new ArrayList<>();
+ private final List<PolicyUtils.ElementPath> pathElements = new
ArrayList<>();
private PolicyAsserter policyAsserter;
public ContentEncryptedElementsAssertionState(AbstractSecurityAssertion
assertion,
PolicyAsserter
policyAsserter,
- boolean asserted) {
+ boolean asserted) throws
WSSPolicyException {
super(assertion, asserted);
ContentEncryptedElements contentEncryptedElements =
(ContentEncryptedElements) assertion;
for (int i = 0; i < contentEncryptedElements.getXPaths().size(); i++) {
XPath xPath = contentEncryptedElements.getXPaths().get(i);
- List<QName> elements = PolicyUtils.getElementPath(xPath);
+ PolicyUtils.ElementPath elements =
PolicyUtils.getElementPathDescriptor(xPath);
pathElements.add(elements);
}
@@ -80,10 +78,10 @@ public class ContentEncryptedElementsAssertionState extends
AssertionState imple
public boolean assertEvent(SecurityEvent securityEvent) throws
WSSPolicyException {
ContentEncryptedElementSecurityEvent
contentEncryptedElementSecurityEvent = (ContentEncryptedElementSecurityEvent)
securityEvent;
- Iterator<List<QName>> pathElementIterator = pathElements.iterator();
+ Iterator<PolicyUtils.ElementPath> pathElementIterator =
pathElements.iterator();
while (pathElementIterator.hasNext()) {
- List<QName> pathElements = pathElementIterator.next();
- if (WSSUtils.pathMatches(pathElements,
contentEncryptedElementSecurityEvent.getElementPath())) {
+ PolicyUtils.ElementPath pathElement = pathElementIterator.next();
+ if
(pathElement.matches(contentEncryptedElementSecurityEvent.getElementPath())) {
if (contentEncryptedElementSecurityEvent.isEncrypted()) {
setAsserted(true);
policyAsserter.assertPolicy(getAssertion());
diff --git
a/ws-security-policy-stax/src/main/java/org/apache/wss4j/policy/stax/assertionStates/EncryptedElementsAssertionState.java
b/ws-security-policy-stax/src/main/java/org/apache/wss4j/policy/stax/assertionStates/EncryptedElementsAssertionState.java
index 535e39123..bcd264cb1 100644
---
a/ws-security-policy-stax/src/main/java/org/apache/wss4j/policy/stax/assertionStates/EncryptedElementsAssertionState.java
+++
b/ws-security-policy-stax/src/main/java/org/apache/wss4j/policy/stax/assertionStates/EncryptedElementsAssertionState.java
@@ -33,8 +33,6 @@ import org.apache.wss4j.policy.stax.PolicyUtils;
import org.apache.wss4j.stax.securityEvent.WSSecurityEventConstants;
import org.apache.wss4j.stax.utils.WSSUtils;
-import javax.xml.namespace.QName;
-
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
@@ -44,18 +42,18 @@ import java.util.List;
*/
public class EncryptedElementsAssertionState extends AssertionState implements
Assertable {
- private final List<List<QName>> pathElements = new ArrayList<>();
+ private final List<PolicyUtils.ElementPath> pathElements = new
ArrayList<>();
private PolicyAsserter policyAsserter;
public EncryptedElementsAssertionState(AbstractSecurityAssertion assertion,
PolicyAsserter policyAsserter,
- boolean asserted) {
+ boolean asserted) throws
WSSPolicyException {
super(assertion, asserted);
EncryptedElements encryptedElements = (EncryptedElements) assertion;
for (int i = 0; i < encryptedElements.getXPaths().size(); i++) {
XPath xPath = encryptedElements.getXPaths().get(i);
- List<QName> elements = PolicyUtils.getElementPath(xPath);
+ PolicyUtils.ElementPath elements =
PolicyUtils.getElementPathDescriptor(xPath);
pathElements.add(elements);
}
@@ -82,10 +80,10 @@ public class EncryptedElementsAssertionState extends
AssertionState implements A
AbstractSecuredElementSecurityEvent encryptedElementSecurityEvent =
(AbstractSecuredElementSecurityEvent) securityEvent;
- Iterator<List<QName>> pathElementIterator = pathElements.iterator();
+ Iterator<PolicyUtils.ElementPath> pathElementIterator =
pathElements.iterator();
while (pathElementIterator.hasNext()) {
- List<QName> pathElements = pathElementIterator.next();
- if (WSSUtils.pathMatches(pathElements,
encryptedElementSecurityEvent.getElementPath())) {
+ PolicyUtils.ElementPath pathElement = pathElementIterator.next();
+ if
(pathElement.matches(encryptedElementSecurityEvent.getElementPath())) {
if (encryptedElementSecurityEvent.isEncrypted()) {
setAsserted(true);
policyAsserter.assertPolicy(getAssertion());
diff --git
a/ws-security-policy-stax/src/main/java/org/apache/wss4j/policy/stax/assertionStates/RequiredElementsAssertionState.java
b/ws-security-policy-stax/src/main/java/org/apache/wss4j/policy/stax/assertionStates/RequiredElementsAssertionState.java
index ce91e1087..d4eae6b73 100644
---
a/ws-security-policy-stax/src/main/java/org/apache/wss4j/policy/stax/assertionStates/RequiredElementsAssertionState.java
+++
b/ws-security-policy-stax/src/main/java/org/apache/wss4j/policy/stax/assertionStates/RequiredElementsAssertionState.java
@@ -45,19 +45,19 @@ import java.util.Map;
*/
public class RequiredElementsAssertionState extends AssertionState implements
Assertable {
- private final Map<List<QName>, Boolean> pathElements = new HashMap<>();
+ private final Map<PolicyUtils.ElementPath, Boolean> pathElements = new
HashMap<>();
private PolicyAsserter policyAsserter;
public RequiredElementsAssertionState(AbstractSecurityAssertion assertion,
PolicyAsserter policyAsserter,
- boolean asserted) {
+ boolean asserted) throws
WSSPolicyException {
super(assertion, asserted);
if (assertion instanceof RequiredElements) {
RequiredElements requiredElements = (RequiredElements) assertion;
for (int i = 0; i < requiredElements.getXPaths().size(); i++) {
XPath xPath = requiredElements.getXPaths().get(i);
- List<QName> elements = PolicyUtils.getElementPath(xPath);
+ PolicyUtils.ElementPath elements =
PolicyUtils.getElementPathDescriptor(xPath);
pathElements.put(elements, Boolean.FALSE);
}
}
@@ -73,7 +73,7 @@ public class RequiredElementsAssertionState extends
AssertionState implements As
}
public void addElement(List<QName> pathElement) {
- this.pathElements.put(pathElement, Boolean.FALSE);
+ this.pathElements.put(PolicyUtils.absoluteElementPath(pathElement),
Boolean.FALSE);
}
@Override
@@ -87,11 +87,11 @@ public class RequiredElementsAssertionState extends
AssertionState implements As
public boolean assertEvent(SecurityEvent securityEvent) throws
WSSPolicyException {
RequiredElementSecurityEvent requiredElementSecurityEvent =
(RequiredElementSecurityEvent) securityEvent;
- Iterator<Map.Entry<List<QName>, Boolean>> elementMapIterator =
pathElements.entrySet().iterator();
+ Iterator<Map.Entry<PolicyUtils.ElementPath, Boolean>>
elementMapIterator = pathElements.entrySet().iterator();
while (elementMapIterator.hasNext()) {
- Map.Entry<List<QName>, Boolean> next = elementMapIterator.next();
- List<QName> qNameList = next.getKey();
- if (WSSUtils.pathMatches(qNameList,
requiredElementSecurityEvent.getElementPath())) {
+ Map.Entry<PolicyUtils.ElementPath, Boolean> next =
elementMapIterator.next();
+ PolicyUtils.ElementPath pathElement = next.getKey();
+ if
(pathElement.matches(requiredElementSecurityEvent.getElementPath())) {
next.setValue(Boolean.TRUE);
break;
}
@@ -104,11 +104,11 @@ public class RequiredElementsAssertionState extends
AssertionState implements As
@Override
public boolean isAsserted() {
clearErrorMessage();
- Iterator<Map.Entry<List<QName>, Boolean>> elementMapIterator =
pathElements.entrySet().iterator();
+ Iterator<Map.Entry<PolicyUtils.ElementPath, Boolean>>
elementMapIterator = pathElements.entrySet().iterator();
while (elementMapIterator.hasNext()) {
- Map.Entry<List<QName>, Boolean> next = elementMapIterator.next();
+ Map.Entry<PolicyUtils.ElementPath, Boolean> next =
elementMapIterator.next();
if (Boolean.FALSE.equals(next.getValue())) {
- setErrorMessage("Element " +
WSSUtils.pathAsString(next.getKey()) + " must be present");
+ setErrorMessage("Element " +
WSSUtils.pathAsString(next.getKey().getPath()) + " must be present");
policyAsserter.unassertPolicy(getAssertion(),
getErrorMessage());
return false;
}
diff --git
a/ws-security-policy-stax/src/main/java/org/apache/wss4j/policy/stax/assertionStates/SignedElementsAssertionState.java
b/ws-security-policy-stax/src/main/java/org/apache/wss4j/policy/stax/assertionStates/SignedElementsAssertionState.java
index 0872f609d..cc1bae646 100644
---
a/ws-security-policy-stax/src/main/java/org/apache/wss4j/policy/stax/assertionStates/SignedElementsAssertionState.java
+++
b/ws-security-policy-stax/src/main/java/org/apache/wss4j/policy/stax/assertionStates/SignedElementsAssertionState.java
@@ -44,19 +44,19 @@ import java.util.List;
*/
public class SignedElementsAssertionState extends AssertionState implements
Assertable {
- private final List<List<QName>> pathElements = new ArrayList<>();
+ private final List<PolicyUtils.ElementPath> pathElements = new
ArrayList<>();
private PolicyAsserter policyAsserter;
public SignedElementsAssertionState(AbstractSecurityAssertion assertion,
PolicyAsserter policyAsserter,
- boolean asserted) {
+ boolean asserted) throws
WSSPolicyException {
super(assertion, asserted);
if (assertion instanceof SignedElements) {
SignedElements signedElements = (SignedElements) assertion;
for (int i = 0; i < signedElements.getXPaths().size(); i++) {
XPath xPath = signedElements.getXPaths().get(i);
- List<QName> elements = PolicyUtils.getElementPath(xPath);
+ PolicyUtils.ElementPath elements =
PolicyUtils.getElementPathDescriptor(xPath);
pathElements.add(elements);
}
}
@@ -80,17 +80,17 @@ public class SignedElementsAssertionState extends
AssertionState implements Asse
}
public void addElement(List<QName> pathElement) {
- this.pathElements.add(pathElement);
+ this.pathElements.add(PolicyUtils.absoluteElementPath(pathElement));
}
@Override
public boolean assertEvent(SecurityEvent securityEvent) throws
WSSPolicyException {
AbstractSecuredElementSecurityEvent signedSecurityEvent =
(AbstractSecuredElementSecurityEvent) securityEvent;
- Iterator<List<QName>> pathElementIterator = pathElements.iterator();
+ Iterator<PolicyUtils.ElementPath> pathElementIterator =
pathElements.iterator();
while (pathElementIterator.hasNext()) {
- List<QName> pathElements = pathElementIterator.next();
- if (WSSUtils.pathMatches(pathElements,
signedSecurityEvent.getElementPath())) {
+ PolicyUtils.ElementPath pathElement = pathElementIterator.next();
+ if (pathElement.matches(signedSecurityEvent.getElementPath())) {
if (signedSecurityEvent.isSigned()) {
setAsserted(true);
policyAsserter.assertPolicy(getAssertion());
diff --git
a/ws-security-policy-stax/src/test/java/org/apache/wss4j/policy/stax/test/AsymmetricBindingIntegrationTest.java
b/ws-security-policy-stax/src/test/java/org/apache/wss4j/policy/stax/test/AsymmetricBindingIntegrationTest.java
index 7a4711a8c..55f751b42 100644
---
a/ws-security-policy-stax/src/test/java/org/apache/wss4j/policy/stax/test/AsymmetricBindingIntegrationTest.java
+++
b/ws-security-policy-stax/src/test/java/org/apache/wss4j/policy/stax/test/AsymmetricBindingIntegrationTest.java
@@ -2716,20 +2716,11 @@ public class AsymmetricBindingIntegrationTest extends
AbstractPolicyTestBase {
" <sp:Header Name=\"Header1\"
Namespace=\"...\"/>\n" +
" <sp:Header
Namespace=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\"/>\n"
+
" </sp:SignedParts>\n" +
- " <sp:SignedElements>\n" +
- " <sp:XPath
xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\">wsu:Created</sp:XPath>\n"
+
- " </sp:SignedElements>\n" +
" <sp:EncryptedParts>\n" +
" <sp:Body/>\n" +
" <sp:Header Name=\"Header2\"
Namespace=\"...\"/>\n" +
" <sp:Header
Namespace=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\"/>\n"
+
" </sp:EncryptedParts>\n" +
- " <sp:EncryptedElements>\n" +
- " <sp:XPath
xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\">wsu:Created</sp:XPath>\n"
+
- " </sp:EncryptedElements>\n" +
- " <sp:ContentEncryptedElements>\n" +
- " <sp:XPath
xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\">wsu:Expires</sp:XPath>\n"
+
- " </sp:ContentEncryptedElements>\n" +
" </wsp:All>\n" +
" </wsp:ExactlyOne>";
@@ -2830,20 +2821,11 @@ public class AsymmetricBindingIntegrationTest extends
AbstractPolicyTestBase {
" <sp:Header Name=\"Header1\"
Namespace=\"...\"/>\n" +
" <sp:Header
Namespace=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\"/>\n"
+
" </sp:SignedParts>\n" +
- " <sp:SignedElements>\n" +
- " <sp:XPath
xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\">wsu:Created</sp:XPath>\n"
+
- " </sp:SignedElements>\n" +
" <sp:EncryptedParts>\n" +
" <sp:Body/>\n" +
" <sp:Header Name=\"Header2\"
Namespace=\"...\"/>\n" +
" <sp:Header
Namespace=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\"/>\n"
+
" </sp:EncryptedParts>\n" +
- " <sp:EncryptedElements>\n" +
- " <sp:XPath
xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\">wsu:Created</sp:XPath>\n"
+
- " </sp:EncryptedElements>\n" +
- " <sp:ContentEncryptedElements>\n" +
- " <sp:XPath
xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\">wsu:Expires</sp:XPath>\n"
+
- " </sp:ContentEncryptedElements>\n" +
" </wsp:All>\n" +
" </wsp:ExactlyOne>";
diff --git
a/ws-security-policy-stax/src/test/java/org/apache/wss4j/policy/stax/test/SignedElementsTest.java
b/ws-security-policy-stax/src/test/java/org/apache/wss4j/policy/stax/test/SignedElementsTest.java
index 12a7f66b0..bcd41cf54 100644
---
a/ws-security-policy-stax/src/test/java/org/apache/wss4j/policy/stax/test/SignedElementsTest.java
+++
b/ws-security-policy-stax/src/test/java/org/apache/wss4j/policy/stax/test/SignedElementsTest.java
@@ -25,15 +25,18 @@ import java.util.List;
import javax.xml.namespace.QName;
import org.apache.wss4j.common.ext.WSSecurityException;
+import org.apache.wss4j.common.WSSPolicyException;
import org.apache.wss4j.policy.stax.PolicyViolationException;
import org.apache.wss4j.policy.stax.enforcer.PolicyEnforcer;
import org.apache.wss4j.stax.ext.WSSConstants;
import org.apache.wss4j.stax.securityEvent.OperationSecurityEvent;
+import org.apache.wss4j.stax.utils.WSSUtils;
import org.apache.xml.security.stax.ext.XMLSecurityConstants;
import org.apache.xml.security.stax.securityEvent.SignedElementSecurityEvent;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
@@ -103,4 +106,50 @@ public class SignedElementsTest extends
AbstractPolicyTestBase {
assertEquals(e.getFaultCode(),
WSSecurityException.INVALID_SECURITY);
}
}
+
+ @Test
+ public void testRelativeXPathMustBeSigned() throws Exception {
+ String policyString =
+ "<sp:SignedElements
xmlns:sp=\"http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702\">\n" +
+ "<sp:XPath
xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\">wsu:Created</sp:XPath>\n"
+
+ "</sp:SignedElements>";
+ PolicyEnforcer policyEnforcer =
buildAndStartPolicyEngine(policyString);
+
+ OperationSecurityEvent operationSecurityEvent = new
OperationSecurityEvent();
+ operationSecurityEvent.setOperation(WSDL_DEFINITIONS);
+ policyEnforcer.registerSecurityEvent(operationSecurityEvent);
+
+ List<QName> createdPath = new ArrayList<>();
+ createdPath.addAll(WSSConstants.SOAP_11_WSSE_SECURITY_HEADER_PATH);
+ createdPath.add(WSSConstants.TAG_WSU_TIMESTAMP);
+ createdPath.add(WSSConstants.TAG_WSU_CREATED);
+ SignedElementSecurityEvent signedElementSecurityEvent = new
SignedElementSecurityEvent(null, false, null);
+ signedElementSecurityEvent.setElementPath(createdPath);
+
+ try {
+ policyEnforcer.registerSecurityEvent(signedElementSecurityEvent);
+ fail("Exception expected");
+ } catch (WSSecurityException e) {
+ assertTrue(e.getCause() instanceof PolicyViolationException);
+ assertEquals(e.getCause().getMessage(),
+ "Element " + WSSUtils.pathAsString(createdPath) + " must
be signed");
+ assertEquals(e.getFaultCode(),
WSSecurityException.INVALID_SECURITY);
+ }
+ }
+
+ @Test
+ public void testUnsupportedXPathIsRejected() throws Exception {
+ String policyString =
+ "<sp:SignedElements
xmlns:sp=\"http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702\">\n" +
+ "<sp:XPath
xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\">//wsu:Created</sp:XPath>\n"
+
+ "</sp:SignedElements>";
+
+ PolicyEnforcer policyEnforcer =
buildAndStartPolicyEngine(policyString);
+ OperationSecurityEvent operationSecurityEvent = new
OperationSecurityEvent();
+ operationSecurityEvent.setOperation(WSDL_DEFINITIONS);
+
+ WSSecurityException exception = assertThrows(WSSecurityException.class,
+ () ->
policyEnforcer.registerSecurityEvent(operationSecurityEvent));
+ assertTrue(exception.getCause() instanceof WSSPolicyException);
+ }
}
\ No newline at end of file