You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by co...@apache.org on 2019/01/09 11:55:19 UTC
[cxf] branch master updated: CXF-7938 / CXF-7939 - Support the
WSS4J "validatorMap" configuration constant + Support omitting the "action"
string when "ignoreActions" is true in WSS4JInInterceptor
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/cxf.git
The following commit(s) were added to refs/heads/master by this push:
new 976ecb5 CXF-7938 / CXF-7939 - Support the WSS4J "validatorMap" configuration constant + Support omitting the "action" string when "ignoreActions" is true in WSS4JInInterceptor
976ecb5 is described below
commit 976ecb5f43bd873d01e07078194636a99e812906
Author: Colm O hEigeartaigh <co...@apache.org>
AuthorDate: Wed Jan 9 11:54:14 2019 +0000
CXF-7938 / CXF-7939 - Support the WSS4J "validatorMap" configuration constant + Support omitting the "action" string when "ignoreActions" is true in WSS4JInInterceptor
---
...ractUsernameTokenAuthenticatingInterceptor.java | 13 ++--
.../cxf/ws/security/wss4j/WSS4JInInterceptor.java | 86 +++++++++++-----------
.../common/KerberosClientPasswordCallback.java | 25 +++++++
.../kerberos/wssec/kerberos/KerberosTokenTest.java | 22 ++++++
.../kerberos/wssec/kerberos/DoubleItKerberos.wsdl | 18 +++++
.../cxf/systest/kerberos/wssec/kerberos/client.xml | 13 ++++
.../cxf/systest/kerberos/wssec/kerberos/server.xml | 24 +++++-
7 files changed, 152 insertions(+), 49 deletions(-)
diff --git a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractUsernameTokenAuthenticatingInterceptor.java b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractUsernameTokenAuthenticatingInterceptor.java
index 0508dc2..e0bed7b 100644
--- a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractUsernameTokenAuthenticatingInterceptor.java
+++ b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractUsernameTokenAuthenticatingInterceptor.java
@@ -26,7 +26,6 @@ import java.util.Map;
import java.util.logging.Logger;
import javax.security.auth.Subject;
-import javax.xml.namespace.QName;
import javax.xml.soap.SOAPException;
import javax.xml.stream.XMLStreamException;
@@ -44,12 +43,12 @@ import org.apache.cxf.phase.PhaseInterceptorChain;
import org.apache.cxf.security.SecurityContext;
import org.apache.wss4j.common.ext.WSSecurityException;
import org.apache.wss4j.dom.WSConstants;
+import org.apache.wss4j.dom.engine.WSSConfig;
import org.apache.wss4j.dom.engine.WSSecurityEngine;
import org.apache.wss4j.dom.handler.RequestData;
import org.apache.wss4j.dom.handler.WSHandlerConstants;
import org.apache.wss4j.dom.handler.WSHandlerResult;
import org.apache.wss4j.dom.validate.UsernameTokenValidator;
-import org.apache.wss4j.dom.validate.Validator;
/**
@@ -197,11 +196,11 @@ public abstract class AbstractUsernameTokenAuthenticatingInterceptor extends WSS
@Override
protected WSSecurityEngine getSecurityEngine(boolean utNoCallbacks) {
- Map<QName, Object> profiles = new HashMap<>(1);
-
- Validator validator = new CustomValidator();
- profiles.put(WSConstants.USERNAME_TOKEN, validator);
- return createSecurityEngine(profiles);
+ WSSConfig config = WSSConfig.getNewInstance();
+ config.setValidator(WSConstants.USERNAME_TOKEN, new CustomValidator());
+ WSSecurityEngine ret = new WSSecurityEngine();
+ ret.setWssConfig(config);
+ return ret;
}
protected class CustomValidator extends UsernameTokenValidator {
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 8c70f03..bfb7b9c 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
@@ -22,7 +22,6 @@ import java.lang.reflect.Method;
import java.security.Provider;
import java.security.cert.Certificate;
import java.util.ArrayList;
-import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@@ -121,24 +120,55 @@ public class WSS4JInInterceptor extends AbstractWSS4JInterceptor {
public WSS4JInInterceptor(Map<String, Object> properties) {
this();
setProperties(properties);
+ WSSConfig config = WSSConfig.getNewInstance();
+
+ // Set any custom WSS4J Processor instances that are configured
final Map<QName, Object> processorMap = CastUtils.cast(
(Map<?, ?>)properties.get(PROCESSOR_MAP));
- final Map<QName, Object> validatorMap = CastUtils.cast(
- (Map<?, ?>)properties.get(VALIDATOR_MAP));
-
if (processorMap != null) {
- if (validatorMap != null) {
- processorMap.putAll(validatorMap);
+ for (Map.Entry<QName, Object> 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);
+ }
}
- secEngineOverride = createSecurityEngine(processorMap);
- } else if (validatorMap != null) {
- secEngineOverride = createSecurityEngine(validatorMap);
}
+
+ // Set any custom WSS4J Validator instances that are configured
+ Map<QName, Object> validatorMap = CastUtils.cast(
+ (Map<?, ?>)properties.get(VALIDATOR_MAP));
+ if (validatorMap == null) {
+ validatorMap = CastUtils.cast((Map<?, ?>)properties.get(ConfigurationConstants.VALIDATOR_MAP));
+ }
+ if (validatorMap != null) {
+ for (Map.Entry<QName, Object> entry : validatorMap.entrySet()) {
+ Object val = entry.getValue();
+ if (val instanceof Class<?>) {
+ config.setValidator(entry.getKey(), (Class<?>)val);
+ } else if (val instanceof Validator) {
+ config.setValidator(entry.getKey(), (Validator)val);
+ }
+ }
+ }
+
+ secEngineOverride = new WSSecurityEngine();
+ secEngineOverride.setWssConfig(config);
}
+ /**
+ * Setting this value to true means that WSS4J does not compare the "actions" that were processed against
+ * the list of actions that were configured. It also means that CXF/WSS4J does not throw an error if no actions
+ * were specified. Setting this to true could be a potential security risk, as there is then no guarantee that
+ * the message contains the desired security token.
+ */
public void setIgnoreActions(boolean i) {
ignoreActions = i;
}
+
private SOAPMessage getSOAPMessage(SoapMessage msg) {
SAAJInInterceptor.INSTANCE.handleMessage(msg);
return msg.getContent(SOAPMessage.class);
@@ -230,7 +260,6 @@ public class WSS4JInInterceptor extends AbstractWSS4JInterceptor {
computeAction(msg, reqData);
String action = getAction(msg, version);
-
List<Integer> actions = WSSecurityUtil.decodeAction(action);
String actor = (String)getOption(ConfigurationConstants.ACTOR);
@@ -578,7 +607,7 @@ public class WSS4JInInterceptor extends AbstractWSS4JInterceptor {
if (action == null) {
action = (String)msg.get(ConfigurationConstants.ACTION);
}
- if (action == null) {
+ if (action == null && !ignoreActions) {
LOG.warning("No security action was defined!");
throw new SoapFault("No security action was defined!", version.getReceiver());
}
@@ -648,42 +677,17 @@ public class WSS4JInInterceptor extends AbstractWSS4JInterceptor {
}
if (!utWithCallbacks) {
- Map<QName, Object> profiles = new HashMap<>(1);
- Validator validator = new NoOpValidator();
- profiles.put(WSConstants.USERNAME_TOKEN, validator);
- return createSecurityEngine(profiles);
+ WSSConfig config = WSSConfig.getNewInstance();
+ config.setValidator(WSConstants.USERNAME_TOKEN, new NoOpValidator());
+ WSSecurityEngine ret = new WSSecurityEngine();
+ ret.setWssConfig(config);
+ return ret;
}
return null;
}
/**
- * @return a freshly minted WSSecurityEngine instance, using the
- * (non-null) processor map, to be used to initialize the
- * WSSecurityEngine instance.
- */
- protected static WSSecurityEngine createSecurityEngine(final Map<QName, Object> map) {
- assert map != null;
- final WSSConfig config = WSSConfig.getNewInstance();
- for (Map.Entry<QName, Object> entry : map.entrySet()) {
- final QName key = entry.getKey();
- Object val = entry.getValue();
- if (val instanceof Class<?>) {
- config.setProcessor(key, (Class<?>)val);
- } else if (val instanceof Processor) {
- config.setProcessor(key, (Processor)val);
- } else if (val instanceof Validator) {
- config.setValidator(key, (Validator)val);
- } else if (val == null) {
- config.setProcessor(key, (Class<?>)null);
- }
- }
- final WSSecurityEngine ret = new WSSecurityEngine();
- ret.setWssConfig(config);
- return ret;
- }
-
- /**
* Get a ReplayCache instance. It first checks to see whether caching has been explicitly
* enabled or disabled via the booleanKey argument. If it has been set to false then no
* replay caching is done (for this booleanKey). If it has not been specified, then caching
diff --git a/systests/kerberos/src/test/java/org/apache/cxf/systest/kerberos/common/KerberosClientPasswordCallback.java b/systests/kerberos/src/test/java/org/apache/cxf/systest/kerberos/common/KerberosClientPasswordCallback.java
index a4a9c84..1626676 100644
--- a/systests/kerberos/src/test/java/org/apache/cxf/systest/kerberos/common/KerberosClientPasswordCallback.java
+++ b/systests/kerberos/src/test/java/org/apache/cxf/systest/kerberos/common/KerberosClientPasswordCallback.java
@@ -27,6 +27,12 @@ import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
+import org.apache.cxf.helpers.DOMUtils;
+import org.apache.wss4j.common.ext.WSPasswordCallback;
+import org.apache.wss4j.common.ext.WSSecurityException;
+import org.apache.wss4j.dom.engine.WSSConfig;
+import org.apache.wss4j.dom.message.token.KerberosSecurity;
+
/**
* A CallbackHandler implementation for the kerberos client.
*/
@@ -40,6 +46,25 @@ public class KerberosClientPasswordCallback implements CallbackHandler {
} else if (callbacks[i] instanceof PasswordCallback) {
PasswordCallback passwordCallback = (PasswordCallback)callbacks[i];
passwordCallback.setPassword("alice".toCharArray());
+ } else if (callbacks[i] instanceof WSPasswordCallback) {
+ WSPasswordCallback wsPasswordCallback = (WSPasswordCallback)callbacks[i];
+ // Get a custom (Kerberos) token directly using the WSS4J APIs
+ if (wsPasswordCallback.getUsage() == WSPasswordCallback.CUSTOM_TOKEN) {
+ KerberosSecurity kerberosSecurity = new KerberosSecurity(DOMUtils.getEmptyDocument());
+
+ try {
+ kerberosSecurity.retrieveServiceTicket("alice", this, "bob@service.ws.apache.org",
+ false, false, null);
+ kerberosSecurity.addWSUNamespace();
+ WSSConfig wssConfig = WSSConfig.getNewInstance();
+ kerberosSecurity.setID(wssConfig.getIdAllocator().createSecureId("BST-", kerberosSecurity));
+
+ wsPasswordCallback.setCustomToken(kerberosSecurity.getElement());
+ } catch (WSSecurityException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
}
}
}
diff --git a/systests/kerberos/src/test/java/org/apache/cxf/systest/kerberos/wssec/kerberos/KerberosTokenTest.java b/systests/kerberos/src/test/java/org/apache/cxf/systest/kerberos/wssec/kerberos/KerberosTokenTest.java
index 1cf1e62..ad02cf4 100644
--- a/systests/kerberos/src/test/java/org/apache/cxf/systest/kerberos/wssec/kerberos/KerberosTokenTest.java
+++ b/systests/kerberos/src/test/java/org/apache/cxf/systest/kerberos/wssec/kerberos/KerberosTokenTest.java
@@ -434,4 +434,26 @@ public class KerberosTokenTest extends AbstractBusClientServerTestBase {
bus.shutdown(true);
}
+ @org.junit.Test
+ public void testKerberosViaCustomTokenAction() throws Exception {
+ SpringBusFactory bf = new SpringBusFactory();
+ URL busFile = KerberosTokenTest.class.getResource("client.xml");
+
+ Bus bus = bf.createBus(busFile.toString());
+ BusFactory.setDefaultBus(bus);
+ BusFactory.setThreadDefaultBus(bus);
+
+ URL wsdl = KerberosTokenTest.class.getResource("DoubleItKerberos.wsdl");
+ Service service = Service.create(wsdl, SERVICE_QNAME);
+ QName portQName = new QName(NAMESPACE, "DoubleItKerberosTransportActionPort");
+ DoubleItPortType kerberosPort =
+ service.getPort(portQName, DoubleItPortType.class);
+
+ TestUtil.updateAddressPort(kerberosPort, PORT2);
+
+ Assert.assertEquals(50, kerberosPort.doubleIt(25));
+
+ ((java.io.Closeable)kerberosPort).close();
+ bus.shutdown(true);
+ }
}
diff --git a/systests/kerberos/src/test/resources/org/apache/cxf/systest/kerberos/wssec/kerberos/DoubleItKerberos.wsdl b/systests/kerberos/src/test/resources/org/apache/cxf/systest/kerberos/wssec/kerberos/DoubleItKerberos.wsdl
index 711c753..f7c1f6b 100644
--- a/systests/kerberos/src/test/resources/org/apache/cxf/systest/kerberos/wssec/kerberos/DoubleItKerberos.wsdl
+++ b/systests/kerberos/src/test/resources/org/apache/cxf/systest/kerberos/wssec/kerberos/DoubleItKerberos.wsdl
@@ -284,6 +284,21 @@
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
+ <wsdl:binding name="DoubleItNoSecurityBinding" type="tns:DoubleItPortType">
+ <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
+ <wsdl:operation name="DoubleIt">
+ <soap:operation soapAction=""/>
+ <wsdl:input>
+ <soap:body use="literal"/>
+ </wsdl:input>
+ <wsdl:output>
+ <soap:body use="literal"/>
+ </wsdl:output>
+ <wsdl:fault name="DoubleItFault">
+ <soap:body use="literal" name="DoubleItFault"/>
+ </wsdl:fault>
+ </wsdl:operation>
+ </wsdl:binding>
<wsdl:service name="DoubleItService">
<wsdl:port name="DoubleItKerberosTransportPort" binding="tns:DoubleItKerberosTransportBinding">
<soap:address location="https://localhost:9009/DoubleItKerberosTransport"/>
@@ -334,6 +349,9 @@
<wsdl:port name="DoubleItTransportSAML2Port" binding="tns:DoubleItTransportSAML2Binding">
<soap:address location="https://localhost:8081/doubleit/services/doubleittransportsaml2"/>
</wsdl:port>
+ <wsdl:port name="DoubleItKerberosTransportActionPort" binding="tns:DoubleItNoSecurityBinding">
+ <soap:address location="https://localhost:9009/DoubleItKerberosTransportAction"/>
+ </wsdl:port>
</wsdl:service>
<wsp:Policy wsu:Id="DoubleItKerberosTransportPolicy">
<wsp:ExactlyOne>
diff --git a/systests/kerberos/src/test/resources/org/apache/cxf/systest/kerberos/wssec/kerberos/client.xml b/systests/kerberos/src/test/resources/org/apache/cxf/systest/kerberos/wssec/kerberos/client.xml
index 649fc85..04d4e69 100644
--- a/systests/kerberos/src/test/resources/org/apache/cxf/systest/kerberos/wssec/kerberos/client.xml
+++ b/systests/kerberos/src/test/resources/org/apache/cxf/systest/kerberos/wssec/kerberos/client.xml
@@ -253,4 +253,17 @@
</entry>
</jaxws:properties>
</jaxws:client>
+ <jaxws:client name="{http://www.example.org/contract/DoubleIt}DoubleItKerberosTransportActionPort" createdFromAPI="true">
+ <jaxws:outInterceptors>
+ <bean class="org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor">
+ <constructor-arg>
+ <map>
+ <entry key="action" value="CustomToken"/>
+ <entry key="passwordCallbackRef" value-ref="kerberosCallbackHandler"/>
+ </map>
+ </constructor-arg>
+ </bean>
+ </jaxws:outInterceptors>
+ </jaxws:client>
+
</beans>
diff --git a/systests/kerberos/src/test/resources/org/apache/cxf/systest/kerberos/wssec/kerberos/server.xml b/systests/kerberos/src/test/resources/org/apache/cxf/systest/kerberos/wssec/kerberos/server.xml
index 6a634a9..b44473b 100644
--- a/systests/kerberos/src/test/resources/org/apache/cxf/systest/kerberos/wssec/kerberos/server.xml
+++ b/systests/kerberos/src/test/resources/org/apache/cxf/systest/kerberos/wssec/kerberos/server.xml
@@ -17,7 +17,7 @@
specific language governing permissions and limitations
under the License.
-->
-<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:http="http://cxf.apache.org/transports/http/configuration" xmlns:httpj="http://cxf.apache.org/transports/http-jetty/configuration" xmlns:sec="http://cxf.apache.org/configuration/security" xmlns:interop="http://WSSec/wssec10" xmlns:cxf="http://cxf.apache.org/core" xmlns:p="http://cxf.apache.org/policy" xsi:schemaLocation=" [...]
+<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util" xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:http="http://cxf.apache.org/transports/http/configuration" xmlns:httpj="http://cxf.apache.org/transports/http-jetty/configuration" xmlns:sec="http://cxf.apache.org/configuration/security" xmlns:interop="http://WSSec/wssec10" xmlns:cxf="http://cxf.apache.org/core" xmlns:p="ht [...]
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
<cxf:bus>
<cxf:features>
@@ -181,6 +181,28 @@
</jaxws:properties>
</jaxws:endpoint>
+ <bean class="javax.xml.namespace.QName" id="bstQName">
+ <constructor-arg value="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"/>
+ <constructor-arg value="BinarySecurityToken"/>
+ </bean>
+
+ <util:map id="kerberosValidatorMap">
+ <entry key-ref="bstQName" value-ref="kerberosValidator" />
+ </util:map>
+
+ <jaxws:endpoint xmlns:s="http://www.example.org/contract/DoubleIt" id="DoubleItKerberosTransportActionPort" address="https://localhost:${testutil.ports.Server.2}/DoubleItKerberosTransportAction" serviceName="s:DoubleItService" endpointName="s:DoubleItKerberosTransportActionPort" implementor="org.apache.cxf.systest.kerberos.common.DoubleItPortTypeImpl" wsdlLocation="org/apache/cxf/systest/kerberos/wssec/kerberos/DoubleItKerberos.wsdl" depends-on="tls-settings">
+ <jaxws:inInterceptors>
+ <bean class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor">
+ <constructor-arg>
+ <map>
+ <entry key="validatorMap" value-ref="kerberosValidatorMap"/>
+ </map>
+ </constructor-arg>
+ <property name="ignoreActions" value="true"/>
+ </bean>
+ </jaxws:inInterceptors>
+ </jaxws:endpoint>
+
<httpj:engine-factory id="STSClientAuthHttpsSettings" bus="cxf">
<httpj:engine port="${testutil.ports.Server.3}">
<httpj:tlsServerParameters>