This is an automated email from the ASF dual-hosted git repository. coheigea pushed a commit to branch coheigea/wss4j-saml-refactor in repository https://gitbox.apache.org/repos/asf/cxf.git
commit 851e5c6b5cdacc69df0b4c428500b0850d34c03f Author: Colm O hEigeartaigh <[email protected]> AuthorDate: Tue Jul 1 10:24:10 2025 +0100 Fixing most WS-Security tests --- .../security/wss4j/AbstractWSS4JInterceptor.java | 25 ++++++-- .../cxf/ws/security/wss4j/WSS4JInInterceptor.java | 10 +++- .../cxf/ws/security/wss4j/WSS4JOutInterceptor.java | 70 +++++++++++++++++++++- .../cxf/ws/security/wss4j/WSS4JInOutTest.java | 2 +- .../ws/security/wss4j/WSS4JOutInterceptorTest.java | 1 - .../apache/cxf/systest/ws/action/ActionTest.java | 2 +- .../ws/fault/AbstractModifyRequestInterceptor.java | 2 +- .../cxf/systest/ws/saml/CustomSaml2Validator.java | 8 +-- .../ws/saml/client/SamlCallbackHandler.java | 2 +- .../cxf/systest/ws/tokens/DoubleItBSTImpl.java | 2 +- .../cxf/systest/ws/ut/CustomUTValidator.java | 6 +- .../ws/ut/SecurityHeaderCacheInterceptor.java | 2 +- 12 files changed, 107 insertions(+), 25 deletions(-) diff --git a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractWSS4JInterceptor.java b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractWSS4JInterceptor.java index a77b1c554f..b667288810 100644 --- a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractWSS4JInterceptor.java +++ b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractWSS4JInterceptor.java @@ -25,6 +25,7 @@ import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; +import javax.security.auth.callback.CallbackHandler; import javax.xml.namespace.QName; import org.apache.cxf.binding.soap.SoapMessage; @@ -94,10 +95,6 @@ public abstract class AbstractWSS4JInterceptor extends WSHandler implements Soap properties.put(key, value); } - public String getPassword(Object msgContext) { - return (String)((Message)msgContext).getContextualProperty("password"); - } - public Object getProperty(Object msgContext, String key) { if (msgContext == null) { return null; @@ -110,8 +107,24 @@ public abstract class AbstractWSS4JInterceptor extends WSHandler implements Soap return obj; } - public void setPassword(Object msgContext, String password) { - ((Message)msgContext).put("password", password); + @Override + public CallbackHandler getCallbackHandler( + String callbackHandlerClass, + String callbackHandlerRef, + RequestData requestData + ) throws WSSecurityException { + if (callbackHandlerRef != null && properties.containsKey(callbackHandlerRef)) { + return (CallbackHandler)properties.get(callbackHandlerRef); + } + return super.getCallbackHandler(callbackHandlerClass, callbackHandlerRef, requestData); + } + + @Override + protected String getString(String key, Map<String, Object> mc) { + if (properties.containsKey(key)) { + return (String)properties.get(key); + } + return super.getString(key, mc); } public void setProperty(Object msgContext, String key, Object value) { diff --git a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/WSS4JInInterceptor.java b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/WSS4JInInterceptor.java index e797817922..8c738be7f5 100644 --- a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/WSS4JInInterceptor.java +++ b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/WSS4JInInterceptor.java @@ -185,6 +185,11 @@ public class WSS4JInInterceptor extends AbstractWSS4JInterceptor { public Object getProperty(Object msgContext, String key) { // use the superclass first Object result = super.getProperty(msgContext, key); + if (result == null) { + result = msgContext instanceof SoapMessage + ? ((SoapMessage)msgContext).getContextualProperty(key) + : null; + } // handle the special case of the SEND_SIGV if (result == null @@ -223,6 +228,7 @@ public class WSS4JInInterceptor extends AbstractWSS4JInterceptor { boolean utWithCallbacks = MessageUtils.getContextualBoolean(msg, SecurityConstants.VALIDATE_TOKEN, true); translateProperties(msg); + RequestData reqData = new CXFRequestData(); @@ -297,8 +303,8 @@ public class WSS4JInInterceptor extends AbstractWSS4JInterceptor { // Only search for and expand (Signed) XOP Elements if MTOM is enabled (and not // explicitly specified by the user) - if (getString(ConfigurationConstants.EXPAND_XOP_INCLUDE_FOR_SIGNATURE, msg) == null - && getString(ConfigurationConstants.EXPAND_XOP_INCLUDE, msg) == null) { + if (getProperty(msg, ConfigurationConstants.EXPAND_XOP_INCLUDE_FOR_SIGNATURE) == null + && getProperty(msg, ConfigurationConstants.EXPAND_XOP_INCLUDE) == null) { reqData.setExpandXopInclude(AttachmentUtil.isMtomEnabled(msg)); } diff --git a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/WSS4JOutInterceptor.java b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/WSS4JOutInterceptor.java index 1290a4eb28..a4e0ade215 100644 --- a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/WSS4JOutInterceptor.java +++ b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/WSS4JOutInterceptor.java @@ -18,6 +18,7 @@ */ package org.apache.cxf.ws.security.wss4j; +import java.io.IOException; import java.security.Provider; import java.util.Collection; import java.util.Collections; @@ -28,6 +29,10 @@ import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; +import javax.security.auth.callback.Callback; +import javax.security.auth.callback.CallbackHandler; +import javax.security.auth.callback.UnsupportedCallbackException; + import org.w3c.dom.Document; import jakarta.xml.soap.SOAPMessage; @@ -38,12 +43,16 @@ import org.apache.cxf.binding.soap.SoapVersion; import org.apache.cxf.binding.soap.saaj.SAAJOutInterceptor; import org.apache.cxf.common.i18n.Message; import org.apache.cxf.common.logging.LogUtils; +import org.apache.cxf.common.util.StringUtils; import org.apache.cxf.helpers.CastUtils; import org.apache.cxf.interceptor.Fault; import org.apache.cxf.phase.Phase; import org.apache.cxf.phase.PhaseInterceptor; +import org.apache.cxf.rt.security.utils.SecurityUtils; +import org.apache.cxf.ws.security.SecurityConstants; import org.apache.wss4j.common.ConfigurationConstants; import org.apache.wss4j.common.crypto.ThreadLocalSecurityProvider; +import org.apache.wss4j.common.ext.WSPasswordCallback; import org.apache.wss4j.common.ext.WSSecurityException; import org.apache.wss4j.common.dom.WSConstants; import org.apache.wss4j.common.dom.action.Action; @@ -86,6 +95,11 @@ public class WSS4JOutInterceptor extends AbstractWSS4JInterceptor { public Object getProperty(Object msgContext, String key) { // use the superclass first Object result = super.getProperty(msgContext, key); + if (result == null) { + result = msgContext instanceof SoapMessage + ? ((SoapMessage)msgContext).getContextualProperty(key) + : null; + } // handle the special case of the RECV_RESULTS if (result == null @@ -181,7 +195,7 @@ public class WSS4JOutInterceptor extends AbstractWSS4JInterceptor { CastUtils.cast((List<?>)getProperty(mc, WSHandlerConstants.HANDLER_ACTIONS)); if (actions == null) { // If null then just fall back to the "action" String - String action = getString(ConfigurationConstants.ACTION, mc); + String action = (String)getProperty(mc, ConfigurationConstants.ACTION); if (action == null) { throw new SoapFault(new Message("NO_ACTION", LOG), version .getReceiver()); @@ -195,13 +209,14 @@ public class WSS4JOutInterceptor extends AbstractWSS4JInterceptor { translateProperties(mc); reqData.setMsgContext(mc); + reqData.setCallbackHandler(getCallback(reqData)); reqData.setAttachmentCallbackHandler(new AttachmentCallbackHandler(mc)); // Enable XOP Include unless the user has explicitly configured it - if (getString(ConfigurationConstants.EXPAND_XOP_INCLUDE, mc) == null) { + if (getProperty(mc, ConfigurationConstants.EXPAND_XOP_INCLUDE) == null) { reqData.setExpandXopInclude(AttachmentUtil.isMtomEnabled(mc)); } - if (getString(ConfigurationConstants.STORE_BYTES_IN_ATTACHMENT, mc) == null) { + if (getProperty(mc, ConfigurationConstants.STORE_BYTES_IN_ATTACHMENT) == null) { reqData.setStoreBytesInAttachment(AttachmentUtil.isMtomEnabled(mc)); } @@ -346,4 +361,53 @@ public class WSS4JOutInterceptor extends AbstractWSS4JInterceptor { return null; } } + + private CallbackHandler getCallback(RequestData reqData) throws WSSecurityException { + Object o = + SecurityUtils.getSecurityPropertyValue(SecurityConstants.CALLBACK_HANDLER, + (SoapMessage)reqData.getMsgContext()); + CallbackHandler cbHandler; + try { + cbHandler = SecurityUtils.getCallbackHandler(o); + } catch (Exception ex) { + throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, ex); + } + + if (cbHandler == null) { + try { + cbHandler = getPasswordCallbackHandler(reqData); + } catch (WSSecurityException sec) { + // Ignore + } + } + + // Defer to SecurityConstants.PASSWORD or "password" if no callback handler is defined + if (cbHandler == null) { + String password = + (String)SecurityUtils.getSecurityPropertyValue(SecurityConstants.PASSWORD, + (SoapMessage)reqData.getMsgContext()); + if (StringUtils.isEmpty(password)) { + password = (String)SecurityUtils.getSecurityPropertyValue("password", + (SoapMessage)reqData.getMsgContext()); + } + + if (!StringUtils.isEmpty(password)) { + final String contextualPassword = password; + cbHandler = new CallbackHandler() { + + @Override + public void handle(Callback[] callbacks) + throws IOException, UnsupportedCallbackException { + for (Callback c : callbacks) { + WSPasswordCallback pwCallback = (WSPasswordCallback)c; + pwCallback.setPassword(contextualPassword); + } + } + }; + } + + } + + return cbHandler; + } } diff --git a/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/WSS4JInOutTest.java b/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/WSS4JInOutTest.java index 87ffa14b2e..35232ae529 100644 --- a/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/WSS4JInOutTest.java +++ b/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/WSS4JInOutTest.java @@ -53,7 +53,7 @@ import org.apache.wss4j.common.principal.UsernameTokenPrincipal; import org.apache.wss4j.common.dom.WSConstants; import org.apache.wss4j.common.WSDataRef; import org.apache.wss4j.common.dom.engine.WSSecurityEngineResult; -import org.apache.wss4j.dom.handler.WSHandlerConstants; +import org.apache.wss4j.dom.handler.WSHandlerConstants; import org.apache.wss4j.dom.handler.WSHandlerResult; import org.apache.xml.security.utils.Constants; import org.apache.xml.security.utils.EncryptionConstants; diff --git a/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/WSS4JOutInterceptorTest.java b/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/WSS4JOutInterceptorTest.java index 55f1e85ba8..f02cf3e734 100644 --- a/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/WSS4JOutInterceptorTest.java +++ b/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/WSS4JOutInterceptorTest.java @@ -34,7 +34,6 @@ import org.apache.wss4j.common.ext.WSSecurityException; import org.apache.wss4j.common.dom.WSConstants; import org.apache.wss4j.dom.action.UsernameTokenAction; import org.apache.wss4j.common.dom.RequestData; -import org.apache.wss4j.dom.handler.WSHandler; import org.junit.Test; diff --git a/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/action/ActionTest.java b/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/action/ActionTest.java index 655bda7da5..993a154179 100644 --- a/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/action/ActionTest.java +++ b/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/action/ActionTest.java @@ -54,7 +54,7 @@ import org.apache.wss4j.common.SignatureActionToken; 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.common.dom.WSConstants; import org.apache.wss4j.dom.handler.HandlerAction; import org.apache.wss4j.dom.handler.WSHandlerConstants; import org.apache.wss4j.stax.ext.WSSConstants; diff --git a/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/fault/AbstractModifyRequestInterceptor.java b/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/fault/AbstractModifyRequestInterceptor.java index 12a44099ef..3e62490506 100644 --- a/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/fault/AbstractModifyRequestInterceptor.java +++ b/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/fault/AbstractModifyRequestInterceptor.java @@ -39,7 +39,7 @@ import org.apache.cxf.message.Message; import org.apache.cxf.phase.Phase; import org.apache.cxf.phase.PhaseInterceptor; import org.apache.cxf.ws.security.wss4j.PolicyBasedWSS4JOutInterceptor; -import org.apache.wss4j.dom.WSConstants; +import org.apache.wss4j.common.dom.WSConstants; public abstract class AbstractModifyRequestInterceptor implements PhaseInterceptor<SoapMessage> { diff --git a/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/saml/CustomSaml2Validator.java b/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/saml/CustomSaml2Validator.java index 6d6535608f..38f0fa976e 100644 --- a/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/saml/CustomSaml2Validator.java +++ b/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/saml/CustomSaml2Validator.java @@ -22,9 +22,9 @@ import java.util.List; import org.apache.wss4j.common.ext.WSSecurityException; import org.apache.wss4j.common.saml.SamlAssertionWrapper; -import org.apache.wss4j.dom.handler.RequestData; -import org.apache.wss4j.dom.validate.Credential; -import org.apache.wss4j.dom.validate.SamlAssertionValidator; +import org.apache.wss4j.common.dom.RequestData; +import org.apache.wss4j.common.dom.validate.Credential; +import org.apache.wss4j.common.saml.validate.SamlAssertionValidator; import org.opensaml.saml.saml2.core.Assertion; import org.opensaml.saml.saml2.core.AttributeStatement; @@ -37,7 +37,7 @@ public class CustomSaml2Validator extends SamlAssertionValidator { @Override public Credential validate(Credential credential, RequestData data) throws WSSecurityException { Credential validatedCredential = super.validate(credential, data); - SamlAssertionWrapper assertion = validatedCredential.getSamlAssertion(); + SamlAssertionWrapper assertion = (SamlAssertionWrapper)validatedCredential.getSamlAssertion(); if (!"sts".equals(assertion.getIssuerString())) { throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity"); diff --git a/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/saml/client/SamlCallbackHandler.java b/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/saml/client/SamlCallbackHandler.java index e532da163b..b3296f5bff 100644 --- a/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/saml/client/SamlCallbackHandler.java +++ b/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/saml/client/SamlCallbackHandler.java @@ -41,7 +41,7 @@ import org.apache.wss4j.common.saml.bean.SubjectBean; import org.apache.wss4j.common.saml.bean.Version; import org.apache.wss4j.common.saml.builder.SAML1Constants; import org.apache.wss4j.common.saml.builder.SAML2Constants; -import org.apache.wss4j.dom.WSConstants; +import org.apache.wss4j.common.dom.WSConstants; /** * A CallbackHandler instance that is used by the STS to mock up a SAML Attribute Assertion. diff --git a/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/tokens/DoubleItBSTImpl.java b/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/tokens/DoubleItBSTImpl.java index 1fed98f3d3..86ba2ad003 100644 --- a/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/tokens/DoubleItBSTImpl.java +++ b/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/tokens/DoubleItBSTImpl.java @@ -26,7 +26,7 @@ import jakarta.xml.ws.WebServiceContext; import org.apache.cxf.feature.Features; import org.apache.cxf.helpers.CastUtils; import org.apache.wss4j.common.token.BinarySecurity; -import org.apache.wss4j.dom.engine.WSSecurityEngineResult; +import org.apache.wss4j.common.dom.engine.WSSecurityEngineResult; import org.apache.wss4j.dom.handler.WSHandlerConstants; import org.apache.wss4j.dom.handler.WSHandlerResult; import org.example.contract.doubleit.DoubleItFault; diff --git a/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/ut/CustomUTValidator.java b/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/ut/CustomUTValidator.java index 4ff5fedc1d..a71b3aeebd 100644 --- a/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/ut/CustomUTValidator.java +++ b/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/ut/CustomUTValidator.java @@ -24,9 +24,9 @@ import javax.security.auth.Subject; import org.apache.cxf.common.security.SimpleGroup; import org.apache.wss4j.common.ext.WSSecurityException; import org.apache.wss4j.common.principal.WSUsernameTokenPrincipalImpl; -import org.apache.wss4j.dom.handler.RequestData; -import org.apache.wss4j.dom.message.token.UsernameToken; -import org.apache.wss4j.dom.validate.Credential; +import org.apache.wss4j.common.dom.RequestData; +import org.apache.wss4j.common.dom.message.token.UsernameToken; +import org.apache.wss4j.common.dom.validate.Credential; import org.apache.wss4j.dom.validate.UsernameTokenValidator; /** diff --git a/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/ut/SecurityHeaderCacheInterceptor.java b/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/ut/SecurityHeaderCacheInterceptor.java index d0c5c688cc..80edf8333a 100644 --- a/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/ut/SecurityHeaderCacheInterceptor.java +++ b/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/ut/SecurityHeaderCacheInterceptor.java @@ -38,7 +38,7 @@ import org.apache.cxf.message.Message; import org.apache.cxf.phase.Phase; import org.apache.cxf.phase.PhaseInterceptor; import org.apache.cxf.ws.security.wss4j.PolicyBasedWSS4JOutInterceptor; -import org.apache.wss4j.dom.WSConstants; +import org.apache.wss4j.common.dom.WSConstants; /** * Cache the first security header and then use it instead of all subsequent security headers, until
