From d6714384c8c192cb656b9119e84088f435a0bd53 Mon Sep 17 00:00:00 2001 From: Colm O hEigeartaigh Date: Wed, 4 Feb 2026 10:15:48 +0000 Subject: [PATCH] CXF-9167 - Enable Custom Processor Injection in PolicyBasedWSS4JInInterceptor --- .../wss4j/PolicyBasedWSS4JInInterceptor.java | 5 ++ .../ws/security/wss4j/WSS4JInInterceptor.java | 27 ++++---- .../ws/ut/CustomUTPasswordCallback.java | 65 +++++++++++++++++++ .../cxf/systest/ws/ut/CustomUTProcessor.java | 43 ++++++++++++ .../ws/ut/UsernameTokenPolicyTest.java | 30 +++++++++ .../cxf/systest/ws/ut/DoubleItUtPolicy.wsdl | 3 + .../cxf/systest/ws/ut/policy-client.xml | 11 ++++ .../cxf/systest/ws/ut/policy-server.xml | 20 ++++++ 8 files changed, 192 insertions(+), 12 deletions(-) create mode 100644 systests/ws-security/src/test/java/org/apache/cxf/systest/ws/ut/CustomUTPasswordCallback.java create mode 100644 systests/ws-security/src/test/java/org/apache/cxf/systest/ws/ut/CustomUTProcessor.java diff --git a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/PolicyBasedWSS4JInInterceptor.java b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/PolicyBasedWSS4JInInterceptor.java index ca8ada8fae1..17e7e885c34 100644 --- a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/PolicyBasedWSS4JInInterceptor.java +++ b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/PolicyBasedWSS4JInInterceptor.java @@ -556,6 +556,11 @@ protected void computeAction(SoapMessage message, RequestData data) throws WSSec } message.put(ConfigurationConstants.ACTION, action.trim()); + + // Set any custom WSS4J Processor instances that are configured + final Map processorMap = CastUtils.cast( + (Map)SecurityUtils.getSecurityPropertyValue(PROCESSOR_MAP, message)); + configureCustomProcessors(data.getWssConfig(), processorMap); } } 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 e6c26001aa7..13c8bf902a1 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 @@ -133,18 +133,7 @@ public WSS4JInInterceptor(Map properties) { // Set any custom WSS4J Processor instances that are configured final Map processorMap = CastUtils.cast( (Map)properties.get(PROCESSOR_MAP)); - if (processorMap != null) { - for (Map.Entry entry : processorMap.entrySet()) { - Object val = entry.getValue(); - if (val instanceof Class) { - config.setProcessor(entry.getKey(), (Class)val); - } else if (val instanceof Processor) { - config.setProcessor(entry.getKey(), (Processor)val); - } else if (val == null) { - config.setProcessor(entry.getKey(), (Class)null); - } - } - } + configureCustomProcessors(config, processorMap); // Set any custom WSS4J Validator instances that are configured Map validatorMap = CastUtils.cast( @@ -729,4 +718,18 @@ protected ReplayCache getReplayCache( return WSS4JUtils.getReplayCache(message, booleanKey, instanceKey); } + protected void configureCustomProcessors(WSSConfig config, final Map processorMap) { + if (processorMap != null) { + for (Map.Entry entry : processorMap.entrySet()) { + Object val = entry.getValue(); + if (val instanceof Class) { + config.setProcessor(entry.getKey(), (Class)val); + } else if (val instanceof Processor) { + config.setProcessor(entry.getKey(), (Processor)val); + } else if (val == null) { + config.setProcessor(entry.getKey(), (Class)null); + } + } + } + } } diff --git a/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/ut/CustomUTPasswordCallback.java b/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/ut/CustomUTPasswordCallback.java new file mode 100644 index 00000000000..67d6eccbe85 --- /dev/null +++ b/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/ut/CustomUTPasswordCallback.java @@ -0,0 +1,65 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cxf.systest.ws.ut; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import javax.security.auth.callback.Callback; +import javax.security.auth.callback.CallbackHandler; +import javax.security.auth.callback.UnsupportedCallbackException; + +import org.apache.wss4j.common.ext.WSPasswordCallback; + +/** + * A CallbackHandler implementation used to test custom Processors. + */ +public class CustomUTPasswordCallback implements CallbackHandler { + + private Map passwords = + new HashMap<>(); + + public CustomUTPasswordCallback() { + passwords.put("Alice", "ecilAAlice"); + } + + /** + * Here, we attempt to get the password from the private + * alias/passwords map. + */ + public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { + for (int i = 0; i < callbacks.length; i++) { + WSPasswordCallback pc = (WSPasswordCallback)callbacks[i]; + + String pass = passwords.get(pc.getIdentifier()); + if (pass != null) { + pc.setPassword(pass); + return; + } + } + } + + /** + * Add an alias/password pair to the callback mechanism. + */ + public void setAliasPassword(String alias, String password) { + passwords.put(alias, password); + } +} diff --git a/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/ut/CustomUTProcessor.java b/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/ut/CustomUTProcessor.java new file mode 100644 index 00000000000..ef322cb8292 --- /dev/null +++ b/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/ut/CustomUTProcessor.java @@ -0,0 +1,43 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.cxf.systest.ws.ut; + +import java.util.List; + +import org.w3c.dom.Element; + +import org.apache.wss4j.common.ext.WSSecurityException; +import org.apache.wss4j.dom.engine.WSSecurityEngineResult; +import org.apache.wss4j.dom.handler.RequestData; +import org.apache.wss4j.dom.processor.Processor; +import org.apache.wss4j.dom.processor.UsernameTokenProcessor; + +/** + * A custom Processor that overrides the default CallbackHandler to use a CustomUTPasswordCallback + */ +public class CustomUTProcessor implements Processor { + + @Override + public List handleToken(Element elem, RequestData request) throws WSSecurityException { + request.setCallbackHandler(new CustomUTPasswordCallback()); + UsernameTokenProcessor processor = new UsernameTokenProcessor(); + return processor.handleToken(elem, request); + } +} diff --git a/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/ut/UsernameTokenPolicyTest.java b/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/ut/UsernameTokenPolicyTest.java index f990946bcd7..0f16c5c435b 100644 --- a/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/ut/UsernameTokenPolicyTest.java +++ b/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/ut/UsernameTokenPolicyTest.java @@ -406,5 +406,35 @@ public void handleMessage(SoapMessage message) throws Fault { } + // https://issues.apache.org/jira/browse/CXF-9167 + // Here we're sending a UsernameToken with a password unknown by the default CallbackHandler on the server side, + // but we are overriding the UsernameToken processor to use a CallbackHandler that knows the password. + @org.junit.Test + public void testSupportingTokenCustomProcessor() throws Exception { + + if (test.getPort().equals(STAX_PORT)) { + // We don't support custom processors with streaming for now + return; + } + + SpringBusFactory bf = new SpringBusFactory(); + URL busFile = UsernameTokenPolicyTest.class.getResource("policy-client.xml"); + + Bus bus = bf.createBus(busFile.toString()); + BusFactory.setDefaultBus(bus); + BusFactory.setThreadDefaultBus(bus); + + URL wsdl = UsernameTokenPolicyTest.class.getResource("DoubleItUtPolicy.wsdl"); + Service service = Service.create(wsdl, SERVICE_QNAME); + QName portQName = new QName(NAMESPACE, "DoubleItSupportingTokenPort3"); + DoubleItPortType port = + service.getPort(portQName, DoubleItPortType.class); + updateAddressPort(port, test.getPort()); + + assertEquals(50, port.doubleIt(25)); + + ((java.io.Closeable)port).close(); + bus.shutdown(true); + } } diff --git a/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/ut/DoubleItUtPolicy.wsdl b/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/ut/DoubleItUtPolicy.wsdl index 9ae032212df..7811d029393 100644 --- a/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/ut/DoubleItUtPolicy.wsdl +++ b/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/ut/DoubleItUtPolicy.wsdl @@ -41,6 +41,9 @@ + + + diff --git a/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/ut/policy-client.xml b/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/ut/policy-client.xml index f9b2d4337c5..c6d710b093a 100644 --- a/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/ut/policy-client.xml +++ b/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/ut/policy-client.xml @@ -60,6 +60,17 @@ + + + + + + + + + + + diff --git a/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/ut/policy-server.xml b/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/ut/policy-server.xml index 1606e002b60..231480e7d3a 100644 --- a/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/ut/policy-server.xml +++ b/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/ut/policy-server.xml @@ -70,6 +70,26 @@ + + + + + + + + + + + + + + + + + + + +