This is an automated email from the ASF dual-hosted git repository. coheigea pushed a commit to branch coheigea/policy in repository https://gitbox.apache.org/repos/asf/ws-wss4j.git
commit 194f168f1f5d49a3ccd72f68e032f5851c3e2003 Author: Colm O hEigeartaigh <[email protected]> AuthorDate: Fri Sep 4 17:04:50 2026 +0100 Only set the StAX RSA 1.5 + UsernameToken No Password properties if we have a corresponding policy --- .../wss4j/policy/stax/enforcer/PolicyEnforcer.java | 66 ++++++++++++++++++++++ .../policy/stax/enforcer/PolicyInputProcessor.java | 16 +++++- 2 files changed, 80 insertions(+), 2 deletions(-) diff --git a/ws-security-policy-stax/src/main/java/org/apache/wss4j/policy/stax/enforcer/PolicyEnforcer.java b/ws-security-policy-stax/src/main/java/org/apache/wss4j/policy/stax/enforcer/PolicyEnforcer.java index 7782cfcdd..891a68969 100644 --- a/ws-security-policy-stax/src/main/java/org/apache/wss4j/policy/stax/enforcer/PolicyEnforcer.java +++ b/ws-security-policy-stax/src/main/java/org/apache/wss4j/policy/stax/enforcer/PolicyEnforcer.java @@ -25,6 +25,7 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.function.Predicate; import javax.xml.namespace.QName; @@ -793,4 +794,69 @@ public class PolicyEnforcer implements SecurityEventListener { verifyPolicy(); } + /** + * Returns true if any configured operation policy contains a UsernameToken assertion + * that explicitly allows password-less tokens (sp:NoPassword). Used to decide whether + * the engine's hardened default (rejecting password-less UsernameTokens) may be + * relaxed in policy mode. + */ + public boolean isUsernameTokenNoPasswordAllowedByPolicy() { + for (OperationPolicy operationPolicy : operationPolicies) { + org.apache.neethi.Policy policy = operationPolicy.getPolicy(); + if (policy != null && policyContains(policy, + assertion -> assertion instanceof UsernameToken + && ((UsernameToken)assertion).getPasswordType() + == UsernameToken.PasswordType.NoPassword)) { + return true; + } + } + return false; + } + + /** + * Returns true if any configured operation policy contains an AlgorithmSuite whose + * asymmetric key wrap is RSA v1.5. Used to decide whether the engine's hardened + * default (rejecting rsa-1_5 key transport) may be relaxed in policy mode. + */ + public boolean isRSA15KeyTransportAllowedByPolicy() { + for (OperationPolicy operationPolicy : operationPolicies) { + org.apache.neethi.Policy policy = operationPolicy.getPolicy(); + if (policy != null && policyContains(policy, assertion -> { + if (!(assertion instanceof AlgorithmSuite)) { + return false; + } + AlgorithmSuite.AlgorithmSuiteType algorithmSuiteType = + ((AlgorithmSuite)assertion).getAlgorithmSuiteType(); + return algorithmSuiteType != null + && SPConstants.KW_RSA15.equals(algorithmSuiteType.getAsymmetricKeyWrap()); + })) { + return true; + } + } + return false; + } + + private static boolean policyContains(PolicyComponent policyComponent, Predicate<Assertion> predicate) { + if (policyComponent instanceof PolicyOperator) { + for (PolicyComponent childComponent + : ((PolicyOperator) policyComponent).getPolicyComponents()) { + if (policyContains(childComponent, predicate)) { + return true; + } + } + } else if (policyComponent instanceof Assertion) { + Assertion assertion = (Assertion) policyComponent; + if (predicate.test(assertion)) { + return true; + } + if (assertion instanceof PolicyContainingAssertion) { + Policy nestedPolicy = ((PolicyContainingAssertion) assertion).getPolicy(); + if (nestedPolicy != null && policyContains(nestedPolicy, predicate)) { + return true; + } + } + } + return false; + } + } diff --git a/ws-security-policy-stax/src/main/java/org/apache/wss4j/policy/stax/enforcer/PolicyInputProcessor.java b/ws-security-policy-stax/src/main/java/org/apache/wss4j/policy/stax/enforcer/PolicyInputProcessor.java index 03c466d4c..78a4d3ef2 100644 --- a/ws-security-policy-stax/src/main/java/org/apache/wss4j/policy/stax/enforcer/PolicyInputProcessor.java +++ b/ws-security-policy-stax/src/main/java/org/apache/wss4j/policy/stax/enforcer/PolicyInputProcessor.java @@ -248,8 +248,20 @@ public class PolicyInputProcessor extends AbstractInputProcessor { this.initDone = true; this.transportSecurityActive = Boolean.TRUE.equals(inputProcessorChain.getSecurityContext().get(WSSConstants.TRANSPORT_SECURITY_ACTIVE)); - inputProcessorChain.getSecurityContext().put(WSSConstants.PROP_ALLOW_RSA15_KEYTRANSPORT_ALGORITHM, Boolean.TRUE); - inputProcessorChain.getSecurityContext().put(WSSConstants.PROP_ALLOW_USERNAMETOKEN_NOPASSWORD, Boolean.TRUE.toString()); + // These two properties relax hardened engine defaults (rejection of rsa-1_5 + // key transport and of password-less UsernameTokens) so that the corresponding + // policy assertions can take over enforcement. They used to be set + // unconditionally, which silently reversed both defaults even when the + // configured policy contained no assertion that re-imposes the check. Only + // relax an engine default when the policy actually covers it. + if (policyEnforcer.isRSA15KeyTransportAllowedByPolicy()) { + inputProcessorChain.getSecurityContext().put( + WSSConstants.PROP_ALLOW_RSA15_KEYTRANSPORT_ALGORITHM, Boolean.TRUE); + } + if (policyEnforcer.isUsernameTokenNoPasswordAllowedByPolicy()) { + inputProcessorChain.getSecurityContext().put( + WSSConstants.PROP_ALLOW_USERNAMETOKEN_NOPASSWORD, Boolean.TRUE.toString()); + } } } }
