Author: coheigea
Date: Mon Jan 28 12:26:53 2013
New Revision: 1439362
URL: http://svn.apache.org/viewvc?rev=1439362&view=rev
Log:
[CXF-4786] - Support KerberosToken SupportingToken policies without a security
binding
- Also refactored all of the standalone interceptors to put common
functionality in an abstract class
Added:
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractTokenInterceptor.java
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/KerberosTokenInterceptor.java
Modified:
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/policy/interceptors/KerberosTokenInterceptorProvider.java
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/SamlTokenInterceptor.java
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/UsernameTokenInterceptor.java
cxf/trunk/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/kerberos/KerberosTokenTest.java
cxf/trunk/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/kerberos/DoubleItKerberos.wsdl
cxf/trunk/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/kerberos/client/client.xml
cxf/trunk/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/kerberos/server/server.xml
Modified:
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/policy/interceptors/KerberosTokenInterceptorProvider.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/policy/interceptors/KerberosTokenInterceptorProvider.java?rev=1439362&r1=1439361&r2=1439362&view=diff
==============================================================================
---
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/policy/interceptors/KerberosTokenInterceptorProvider.java
(original)
+++
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/policy/interceptors/KerberosTokenInterceptorProvider.java
Mon Jan 28 12:26:53 2013
@@ -42,8 +42,8 @@ import org.apache.cxf.ws.security.policy
import org.apache.cxf.ws.security.tokenstore.SecurityToken;
import org.apache.cxf.ws.security.tokenstore.TokenStore;
import org.apache.cxf.ws.security.tokenstore.TokenStoreFactory;
+import org.apache.cxf.ws.security.wss4j.KerberosTokenInterceptor;
import org.apache.cxf.ws.security.wss4j.PolicyBasedWSS4JInInterceptor;
-import org.apache.cxf.ws.security.wss4j.PolicyBasedWSS4JOutInterceptor;
import org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor;
import
org.apache.cxf.ws.security.wss4j.policyvalidators.KerberosTokenPolicyValidator;
import org.apache.ws.security.WSConstants;
@@ -62,16 +62,14 @@ public class KerberosTokenInterceptorPro
public KerberosTokenInterceptorProvider() {
super(Arrays.asList(SP11Constants.KERBEROS_TOKEN,
SP12Constants.KERBEROS_TOKEN));
-
- this.getOutInterceptors().add(PolicyBasedWSS4JOutInterceptor.INSTANCE);
-
this.getOutFaultInterceptors().add(PolicyBasedWSS4JOutInterceptor.INSTANCE);
- this.getInInterceptors().add(PolicyBasedWSS4JInInterceptor.INSTANCE);
-
this.getInFaultInterceptors().add(PolicyBasedWSS4JInInterceptor.INSTANCE);
-
+
this.getOutInterceptors().add(new KerberosTokenOutInterceptor());
this.getOutFaultInterceptors().add(new KerberosTokenOutInterceptor());
this.getInInterceptors().add(new KerberosTokenInInterceptor());
this.getInFaultInterceptors().add(new KerberosTokenInInterceptor());
+
+ this.getOutInterceptors().add(new KerberosTokenInterceptor());
+ this.getInInterceptors().add(new KerberosTokenInterceptor());
}
Added:
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractTokenInterceptor.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractTokenInterceptor.java?rev=1439362&view=auto
==============================================================================
---
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractTokenInterceptor.java
(added)
+++
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractTokenInterceptor.java
Mon Jan 28 12:26:53 2013
@@ -0,0 +1,221 @@
+/**
+ * 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.ws.security.wss4j;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.logging.Logger;
+
+import javax.security.auth.callback.CallbackHandler;
+import javax.xml.namespace.QName;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import org.apache.cxf.binding.soap.SoapHeader;
+import org.apache.cxf.binding.soap.SoapMessage;
+import org.apache.cxf.binding.soap.interceptor.AbstractSoapInterceptor;
+import org.apache.cxf.common.classloader.ClassLoaderUtils;
+import org.apache.cxf.common.i18n.Message;
+import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.endpoint.Endpoint;
+import org.apache.cxf.headers.Header;
+import org.apache.cxf.helpers.DOMUtils;
+import org.apache.cxf.interceptor.Fault;
+import org.apache.cxf.message.MessageUtils;
+import org.apache.cxf.phase.Phase;
+import org.apache.cxf.service.model.EndpointInfo;
+import org.apache.cxf.ws.policy.AssertionInfo;
+import org.apache.cxf.ws.policy.AssertionInfoMap;
+import org.apache.cxf.ws.policy.PolicyException;
+import org.apache.cxf.ws.security.SecurityConstants;
+import org.apache.cxf.ws.security.policy.model.Token;
+import org.apache.cxf.ws.security.tokenstore.TokenStore;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSPasswordCallback;
+
+/**
+ * An abstract interceptor that can be used to form the basis of an
interceptor to add and process
+ * a specific type of security token.
+ */
+public abstract class AbstractTokenInterceptor extends AbstractSoapInterceptor
{
+ private static final Logger LOG =
LogUtils.getL7dLogger(AbstractSoapInterceptor.class);
+ private static final Set<QName> HEADERS = new HashSet<QName>();
+ static {
+ HEADERS.add(new QName(WSConstants.WSSE_NS, "Security"));
+ HEADERS.add(new QName(WSConstants.WSSE11_NS, "Security"));
+ }
+
+ /**
+ * @param p
+ */
+ public AbstractTokenInterceptor() {
+ super(Phase.PRE_PROTOCOL);
+ addAfter(PolicyBasedWSS4JOutInterceptor.class.getName());
+ addAfter(PolicyBasedWSS4JInInterceptor.class.getName());
+ }
+
+ public Set<QName> getUnderstoodHeaders() {
+ return HEADERS;
+ }
+
+ public void handleMessage(SoapMessage message) throws Fault {
+
+ boolean isReq = MessageUtils.isRequestor(message);
+ boolean isOut = MessageUtils.isOutbound(message);
+
+ if (isReq != isOut) {
+ //outbound on server side and inbound on client side doesn't need
+ //any specific token stuff, assert policies and return
+ assertTokens(message);
+ return;
+ }
+ if (isReq) {
+ if
(message.containsKey(PolicyBasedWSS4JOutInterceptor.SECURITY_PROCESSED)) {
+ //The full policy interceptors handled this
+ return;
+ }
+ addToken(message);
+ } else {
+ if (message.containsKey(WSS4JInInterceptor.SECURITY_PROCESSED)) {
+ //The full policy interceptors handled this
+ return;
+ }
+ processToken(message);
+ }
+ }
+
+ protected abstract void processToken(SoapMessage message);
+
+ protected abstract void addToken(SoapMessage message);
+
+ protected abstract Token assertTokens(SoapMessage message);
+
+ protected CallbackHandler getCallback(SoapMessage message) {
+ //Then try to get the password from the given callback handler
+ Object o =
message.getContextualProperty(SecurityConstants.CALLBACK_HANDLER);
+
+ CallbackHandler handler = null;
+ if (o instanceof CallbackHandler) {
+ handler = (CallbackHandler)o;
+ } else if (o instanceof String) {
+ try {
+ handler = (CallbackHandler)ClassLoaderUtils
+ .loadClass((String)o, this.getClass()).newInstance();
+ } catch (Exception e) {
+ handler = null;
+ }
+ }
+ return handler;
+ }
+
+ protected TokenStore getTokenStore(SoapMessage message) {
+ EndpointInfo info =
message.getExchange().get(Endpoint.class).getEndpointInfo();
+ synchronized (info) {
+ TokenStore tokenStore =
+
(TokenStore)message.getContextualProperty(SecurityConstants.TOKEN_STORE_CACHE_INSTANCE);
+ if (tokenStore == null) {
+ tokenStore =
(TokenStore)info.getProperty(SecurityConstants.TOKEN_STORE_CACHE_INSTANCE);
+ }
+ return tokenStore;
+ }
+ }
+
+ protected Header findSecurityHeader(SoapMessage message, boolean create) {
+ for (Header h : message.getHeaders()) {
+ QName n = h.getName();
+ if (n.getLocalPart().equals("Security")
+ && (n.getNamespaceURI().equals(WSConstants.WSSE_NS)
+ || n.getNamespaceURI().equals(WSConstants.WSSE11_NS))) {
+ return h;
+ }
+ }
+ if (!create) {
+ return null;
+ }
+ Document doc = DOMUtils.createDocument();
+ Element el = doc.createElementNS(WSConstants.WSSE_NS, "wsse:Security");
+ el.setAttributeNS(WSConstants.XMLNS_NS, "xmlns:wsse",
WSConstants.WSSE_NS);
+ SoapHeader sh = new SoapHeader(new QName(WSConstants.WSSE_NS,
"Security"), el);
+ sh.setMustUnderstand(true);
+ message.getHeaders().add(sh);
+ return sh;
+ }
+
+ protected String getPassword(String userName, Token info, int type,
SoapMessage message) {
+ //Then try to get the password from the given callback handler
+
+ CallbackHandler handler = getCallback(message);
+ if (handler == null) {
+ policyNotAsserted(info, "No callback handler and no password
available", message);
+ return null;
+ }
+
+ WSPasswordCallback[] cb = {new WSPasswordCallback(userName, type)};
+ try {
+ handler.handle(cb);
+ } catch (Exception e) {
+ policyNotAsserted(info, e, message);
+ }
+
+ //get the password
+ return cb[0].getPassword();
+ }
+
+ protected void policyNotAsserted(Token assertion, String reason,
SoapMessage message) {
+ if (assertion == null) {
+ return;
+ }
+ AssertionInfoMap aim = message.get(AssertionInfoMap.class);
+
+ Collection<AssertionInfo> ais;
+ ais = aim.get(assertion.getName());
+ if (ais != null) {
+ for (AssertionInfo ai : ais) {
+ if (ai.getAssertion() == assertion) {
+ ai.setNotAsserted(reason);
+ }
+ }
+ }
+ if (!assertion.isOptional()) {
+ throw new PolicyException(new Message(reason, LOG));
+ }
+ }
+
+ protected void policyNotAsserted(Token assertion, Exception reason,
SoapMessage message) {
+ if (assertion == null) {
+ return;
+ }
+ AssertionInfoMap aim = message.get(AssertionInfoMap.class);
+ Collection<AssertionInfo> ais;
+ ais = aim.get(assertion.getName());
+ if (ais != null) {
+ for (AssertionInfo ai : ais) {
+ if (ai.getAssertion() == assertion) {
+ ai.setNotAsserted(reason.getMessage());
+ }
+ }
+ }
+ throw new PolicyException(reason);
+ }
+
+
+}
Added:
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/KerberosTokenInterceptor.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/KerberosTokenInterceptor.java?rev=1439362&view=auto
==============================================================================
---
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/KerberosTokenInterceptor.java
(added)
+++
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/KerberosTokenInterceptor.java
Mon Jan 28 12:26:53 2013
@@ -0,0 +1,194 @@
+/**
+ * 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.ws.security.wss4j;
+
+import java.security.Principal;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import javax.security.auth.callback.CallbackHandler;
+import javax.xml.namespace.QName;
+
+import org.w3c.dom.Element;
+
+import org.apache.cxf.binding.soap.SoapMessage;
+import org.apache.cxf.common.classloader.ClassLoaderUtils;
+import org.apache.cxf.headers.Header;
+import org.apache.cxf.helpers.CastUtils;
+import org.apache.cxf.helpers.DOMUtils;
+import org.apache.cxf.interceptor.Fault;
+import org.apache.cxf.interceptor.security.DefaultSecurityContext;
+import org.apache.cxf.security.SecurityContext;
+import org.apache.cxf.ws.policy.AssertionInfo;
+import org.apache.cxf.ws.policy.AssertionInfoMap;
+import org.apache.cxf.ws.security.SecurityConstants;
+import org.apache.cxf.ws.security.policy.SP12Constants;
+import org.apache.cxf.ws.security.policy.model.KerberosToken;
+import org.apache.cxf.ws.security.policy.model.Token;
+import org.apache.cxf.ws.security.tokenstore.SecurityToken;
+import org.apache.cxf.ws.security.tokenstore.TokenStore;
+import org.apache.ws.security.WSDocInfo;
+import org.apache.ws.security.WSSConfig;
+import org.apache.ws.security.WSSecurityEngineResult;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.handler.RequestData;
+import org.apache.ws.security.handler.WSHandlerConstants;
+import org.apache.ws.security.handler.WSHandlerResult;
+import org.apache.ws.security.processor.BinarySecurityTokenProcessor;
+import org.apache.ws.security.validate.Validator;
+
+/**
+ * An interceptor to add a Kerberos token to the security header of an
outbound request, and to
+ * process a Kerberos Token on an inbound request. It takes the Kerberos Token
from the message
+ * context on the outbound side, where it was previously placed by the
+ * KerberosTokenInterceptorProvider.
+ */
+public class KerberosTokenInterceptor extends AbstractTokenInterceptor {
+
+ public KerberosTokenInterceptor() {
+ super();
+ }
+
+ protected void processToken(SoapMessage message) {
+ Header h = findSecurityHeader(message, false);
+ if (h == null) {
+ return;
+ }
+ Element el = (Element)h.getObject();
+ Element child = DOMUtils.getFirstElement(el);
+ while (child != null) {
+ if ("BinarySecurityToken".equals(child.getLocalName())) {
+ try {
+ List<WSSecurityEngineResult> bstResults =
processToken(child, message);
+ if (bstResults != null) {
+ List<WSHandlerResult> results =
CastUtils.cast((List<?>)message
+ .get(WSHandlerConstants.RECV_RESULTS));
+ if (results == null) {
+ results = new ArrayList<WSHandlerResult>();
+ message.put(WSHandlerConstants.RECV_RESULTS,
results);
+ }
+ WSHandlerResult rResult = new WSHandlerResult(null,
bstResults);
+ results.add(0, rResult);
+
+ assertTokens(message);
+
+ Principal principal =
+
(Principal)bstResults.get(0).get(WSSecurityEngineResult.TAG_PRINCIPAL);
+ message.put(WSS4JInInterceptor.PRINCIPAL_RESULT,
principal);
+
+ SecurityContext sc =
message.get(SecurityContext.class);
+ if (sc == null || sc.getUserPrincipal() == null) {
+ message.put(SecurityContext.class, new
DefaultSecurityContext(principal, null));
+ }
+
+ }
+ } catch (WSSecurityException ex) {
+ throw new Fault(ex);
+ }
+ }
+ child = DOMUtils.getNextElement(child);
+ }
+ }
+
+ private List<WSSecurityEngineResult> processToken(Element tokenElement,
final SoapMessage message)
+ throws WSSecurityException {
+ WSDocInfo wsDocInfo = new WSDocInfo(tokenElement.getOwnerDocument());
+ RequestData data = new RequestData() {
+ public CallbackHandler getCallbackHandler() {
+ return getCallback(message);
+ }
+ public Validator getValidator(QName qName) throws
WSSecurityException {
+ String key = SecurityConstants.BST_TOKEN_VALIDATOR;
+ Object o = message.getContextualProperty(key);
+ try {
+ if (o instanceof Validator) {
+ return (Validator)o;
+ } else if (o instanceof Class) {
+ return (Validator)((Class<?>)o).newInstance();
+ } else if (o instanceof String) {
+ return
(Validator)ClassLoaderUtils.loadClass(o.toString(),
+
KerberosTokenInterceptor.class)
+
.newInstance();
+ }
+ } catch (RuntimeException t) {
+ throw t;
+ } catch (Throwable t) {
+ throw new WSSecurityException(t.getMessage(), t);
+ }
+ return super.getValidator(qName);
+ }
+ };
+ data.setWssConfig(WSSConfig.getNewInstance());
+
+ BinarySecurityTokenProcessor p = new BinarySecurityTokenProcessor();
+ List<WSSecurityEngineResult> results =
+ p.handleToken(tokenElement, data, wsDocInfo);
+ return results;
+ }
+
+ protected Token assertTokens(SoapMessage message) {
+ AssertionInfoMap aim = message.get(AssertionInfoMap.class);
+ Collection<AssertionInfo> ais =
aim.getAssertionInfo(SP12Constants.KERBEROS_TOKEN);
+ KerberosToken tok = null;
+ for (AssertionInfo ai : ais) {
+ tok = (KerberosToken)ai.getAssertion();
+ ai.setAsserted(true);
+ }
+ ais = aim.getAssertionInfo(SP12Constants.SUPPORTING_TOKENS);
+ for (AssertionInfo ai : ais) {
+ ai.setAsserted(true);
+ }
+ ais = aim.getAssertionInfo(SP12Constants.SIGNED_SUPPORTING_TOKENS);
+ for (AssertionInfo ai : ais) {
+ ai.setAsserted(true);
+ }
+ return tok;
+ }
+
+
+ protected void addToken(SoapMessage message) {
+ SecurityToken securityToken = getSecurityToken(message);
+ if (securityToken == null || securityToken.getToken() == null) {
+ // No SecurityToken so just return
+ return;
+ }
+
+ assertTokens(message);
+ Header h = findSecurityHeader(message, true);
+ Element el = (Element)h.getObject();
+
el.appendChild(el.getOwnerDocument().importNode(securityToken.getToken(),
true));
+ }
+
+ private SecurityToken getSecurityToken(SoapMessage message) {
+ // Get the TokenStore
+ TokenStore tokenStore = getTokenStore(message);
+ if (tokenStore == null) {
+ return null;
+ }
+
+ String id =
(String)message.getContextualProperty(SecurityConstants.TOKEN_ID);
+ if (id != null) {
+ return tokenStore.getToken(id);
+ }
+ return null;
+ }
+
+}
Modified:
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/SamlTokenInterceptor.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/SamlTokenInterceptor.java?rev=1439362&r1=1439361&r2=1439362&view=diff
==============================================================================
---
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/SamlTokenInterceptor.java
(original)
+++
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/SamlTokenInterceptor.java
Mon Jan 28 12:26:53 2013
@@ -25,25 +25,17 @@ import java.net.URL;
import java.security.Principal;
import java.util.ArrayList;
import java.util.Collection;
-import java.util.HashSet;
import java.util.List;
import java.util.Properties;
-import java.util.Set;
-import java.util.logging.Logger;
import javax.security.auth.callback.CallbackHandler;
import javax.xml.namespace.QName;
-import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.apache.cxf.Bus;
-import org.apache.cxf.binding.soap.SoapHeader;
import org.apache.cxf.binding.soap.SoapMessage;
-import org.apache.cxf.binding.soap.interceptor.AbstractSoapInterceptor;
import org.apache.cxf.common.classloader.ClassLoaderUtils;
-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.headers.Header;
import org.apache.cxf.helpers.CastUtils;
@@ -51,16 +43,14 @@ import org.apache.cxf.helpers.DOMUtils;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.interceptor.security.DefaultSecurityContext;
import org.apache.cxf.message.MessageUtils;
-import org.apache.cxf.phase.Phase;
import org.apache.cxf.resource.ResourceManager;
import org.apache.cxf.security.SecurityContext;
import org.apache.cxf.ws.policy.AssertionInfo;
import org.apache.cxf.ws.policy.AssertionInfoMap;
-import org.apache.cxf.ws.policy.PolicyException;
import org.apache.cxf.ws.security.SecurityConstants;
import org.apache.cxf.ws.security.policy.SP12Constants;
import org.apache.cxf.ws.security.policy.model.SamlToken;
-import org.apache.ws.security.WSConstants;
+import org.apache.cxf.ws.security.policy.model.Token;
import org.apache.ws.security.WSDocInfo;
import org.apache.ws.security.WSPasswordCallback;
import org.apache.ws.security.WSSConfig;
@@ -76,61 +66,19 @@ import org.apache.ws.security.processor.
import org.apache.ws.security.saml.ext.AssertionWrapper;
import org.apache.ws.security.saml.ext.SAMLParms;
import org.apache.ws.security.validate.Validator;
-
import org.opensaml.common.SAMLVersion;
/**
* An interceptor to create and add a SAML token to the security header of an
outbound
* request, and to process a SAML Token on an inbound request.
*/
-public class SamlTokenInterceptor extends AbstractSoapInterceptor {
- private static final Logger LOG =
LogUtils.getL7dLogger(SamlTokenInterceptor.class);
- private static final Set<QName> HEADERS = new HashSet<QName>();
- static {
- HEADERS.add(new QName(WSConstants.WSSE_NS, "Security"));
- HEADERS.add(new QName(WSConstants.WSSE11_NS, "Security"));
- }
+public class SamlTokenInterceptor extends AbstractTokenInterceptor {
- /**
- * @param p
- */
public SamlTokenInterceptor() {
- super(Phase.PRE_PROTOCOL);
- addAfter(PolicyBasedWSS4JOutInterceptor.class.getName());
- addAfter(PolicyBasedWSS4JInInterceptor.class.getName());
- }
-
- public Set<QName> getUnderstoodHeaders() {
- return HEADERS;
- }
-
- public void handleMessage(SoapMessage message) throws Fault {
-
- boolean isReq = MessageUtils.isRequestor(message);
- boolean isOut = MessageUtils.isOutbound(message);
-
- if (isReq != isOut) {
- //outbound on server side and inbound on client side doesn't need
- //any saml token stuff, assert policies and return
- assertSamlTokens(message);
- return;
- }
- if (isReq) {
- if
(message.containsKey(PolicyBasedWSS4JOutInterceptor.SECURITY_PROCESSED)) {
- //The full policy interceptors handled this
- return;
- }
- addSamlToken(message);
- } else {
- if (message.containsKey(WSS4JInInterceptor.SECURITY_PROCESSED)) {
- //The full policy interceptors handled this
- return;
- }
- processSamlToken(message);
- }
+ super();
}
- private void processSamlToken(SoapMessage message) {
+ protected void processToken(SoapMessage message) {
Header h = findSecurityHeader(message, false);
if (h == null) {
return;
@@ -151,7 +99,7 @@ public class SamlTokenInterceptor extend
WSHandlerResult rResult = new WSHandlerResult(null,
samlResults);
results.add(0, rResult);
- assertSamlTokens(message);
+ assertTokens(message);
Principal principal =
(Principal)samlResults.get(0).get(WSSecurityEngineResult.TAG_PRINCIPAL);
@@ -214,7 +162,7 @@ public class SamlTokenInterceptor extend
return results;
}
- private SamlToken assertSamlTokens(SoapMessage message) {
+ protected Token assertTokens(SoapMessage message) {
AssertionInfoMap aim = message.get(AssertionInfoMap.class);
Collection<AssertionInfo> ais =
aim.getAssertionInfo(SP12Constants.SAML_TOKEN);
SamlToken tok = null;
@@ -234,9 +182,9 @@ public class SamlTokenInterceptor extend
}
- private void addSamlToken(SoapMessage message) {
+ protected void addToken(SoapMessage message) {
WSSConfig.init();
- SamlToken tok = assertSamlTokens(message);
+ SamlToken tok = (SamlToken)assertTokens(message);
Header h = findSecurityHeader(message, true);
try {
@@ -395,101 +343,4 @@ public class SamlTokenInterceptor extend
return crypto;
}
- private Header findSecurityHeader(SoapMessage message, boolean create) {
- for (Header h : message.getHeaders()) {
- QName n = h.getName();
- if (n.getLocalPart().equals("Security")
- && (n.getNamespaceURI().equals(WSConstants.WSSE_NS)
- || n.getNamespaceURI().equals(WSConstants.WSSE11_NS))) {
- return h;
- }
- }
- if (!create) {
- return null;
- }
- Document doc = DOMUtils.createDocument();
- Element el = doc.createElementNS(WSConstants.WSSE_NS, "wsse:Security");
- el.setAttributeNS(WSConstants.XMLNS_NS, "xmlns:wsse",
WSConstants.WSSE_NS);
- SoapHeader sh = new SoapHeader(new QName(WSConstants.WSSE_NS,
"Security"), el);
- sh.setMustUnderstand(true);
- message.getHeaders().add(sh);
- return sh;
- }
-
- private CallbackHandler getCallback(SoapMessage message) {
- //Then try to get the password from the given callback handler
- Object o =
message.getContextualProperty(SecurityConstants.CALLBACK_HANDLER);
-
- CallbackHandler handler = null;
- if (o instanceof CallbackHandler) {
- handler = (CallbackHandler)o;
- } else if (o instanceof String) {
- try {
- handler = (CallbackHandler)ClassLoaderUtils
- .loadClass((String)o, this.getClass()).newInstance();
- } catch (Exception e) {
- handler = null;
- }
- }
- return handler;
- }
-
- public String getPassword(String userName, SamlToken info, int type,
SoapMessage message) {
- //Then try to get the password from the given callback handler
-
- CallbackHandler handler = getCallback(message);
- if (handler == null) {
- policyNotAsserted(info, "No callback handler and no password
available", message);
- return null;
- }
-
- WSPasswordCallback[] cb = {new WSPasswordCallback(userName, type)};
- try {
- handler.handle(cb);
- } catch (Exception e) {
- policyNotAsserted(info, e, message);
- }
-
- //get the password
- return cb[0].getPassword();
- }
-
- protected void policyNotAsserted(SamlToken assertion, String reason,
SoapMessage message) {
- if (assertion == null) {
- return;
- }
- AssertionInfoMap aim = message.get(AssertionInfoMap.class);
-
- Collection<AssertionInfo> ais;
- ais = aim.get(assertion.getName());
- if (ais != null) {
- for (AssertionInfo ai : ais) {
- if (ai.getAssertion() == assertion) {
- ai.setNotAsserted(reason);
- }
- }
- }
- if (!assertion.isOptional()) {
- throw new PolicyException(new Message(reason, LOG));
- }
- }
-
- protected void policyNotAsserted(SamlToken assertion, Exception reason,
SoapMessage message) {
- if (assertion == null) {
- return;
- }
- AssertionInfoMap aim = message.get(AssertionInfoMap.class);
- Collection<AssertionInfo> ais;
- ais = aim.get(assertion.getName());
- if (ais != null) {
- for (AssertionInfo ai : ais) {
- if (ai.getAssertion() == assertion) {
- ai.setNotAsserted(reason.getMessage());
- }
- }
- }
- throw new PolicyException(reason);
- }
-
-
}
Modified:
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/UsernameTokenInterceptor.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/UsernameTokenInterceptor.java?rev=1439362&r1=1439361&r2=1439362&view=diff
==============================================================================
---
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/UsernameTokenInterceptor.java
(original)
+++
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/UsernameTokenInterceptor.java
Mon Jan 28 12:26:53 2013
@@ -22,24 +22,15 @@ package org.apache.cxf.ws.security.wss4j
import java.security.Principal;
import java.util.ArrayList;
import java.util.Collection;
-import java.util.HashSet;
import java.util.List;
-import java.util.Set;
-import java.util.logging.Logger;
import javax.security.auth.Subject;
import javax.security.auth.callback.CallbackHandler;
import javax.xml.namespace.QName;
-import org.w3c.dom.Document;
import org.w3c.dom.Element;
-import org.apache.cxf.binding.soap.SoapHeader;
import org.apache.cxf.binding.soap.SoapMessage;
-import org.apache.cxf.binding.soap.interceptor.AbstractSoapInterceptor;
-import org.apache.cxf.common.classloader.ClassLoaderUtils;
-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.headers.Header;
import org.apache.cxf.helpers.CastUtils;
@@ -47,11 +38,9 @@ import org.apache.cxf.helpers.DOMUtils;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.interceptor.security.DefaultSecurityContext;
import org.apache.cxf.message.MessageUtils;
-import org.apache.cxf.phase.Phase;
import org.apache.cxf.security.SecurityContext;
import org.apache.cxf.ws.policy.AssertionInfo;
import org.apache.cxf.ws.policy.AssertionInfoMap;
-import org.apache.cxf.ws.policy.PolicyException;
import org.apache.cxf.ws.security.SecurityConstants;
import org.apache.cxf.ws.security.policy.SP12Constants;
import org.apache.cxf.ws.security.policy.SPConstants;
@@ -75,54 +64,13 @@ import org.apache.ws.security.validate.V
/**
*
*/
-public class UsernameTokenInterceptor extends AbstractSoapInterceptor {
- private static final Logger LOG =
LogUtils.getL7dLogger(UsernameTokenInterceptor.class);
- private static final Set<QName> HEADERS = new HashSet<QName>();
- static {
- HEADERS.add(new QName(WSConstants.WSSE_NS, "Security"));
- HEADERS.add(new QName(WSConstants.WSSE11_NS, "Security"));
- }
+public class UsernameTokenInterceptor extends AbstractTokenInterceptor {
- /**
- * @param p
- */
public UsernameTokenInterceptor() {
- super(Phase.PRE_PROTOCOL);
- addAfter(PolicyBasedWSS4JInInterceptor.class.getName());
- addAfter(PolicyBasedWSS4JOutInterceptor.class.getName());
- }
- public Set<QName> getUnderstoodHeaders() {
- return HEADERS;
+ super();
}
-
- public void handleMessage(SoapMessage message) throws Fault {
-
- boolean isReq = MessageUtils.isRequestor(message);
- boolean isOut = MessageUtils.isOutbound(message);
- if (isReq != isOut) {
- //outbound on server side and inbound on client side doesn't need
- //any username token stuff, assert policies and return
- assertUsernameTokens(message, null);
- return;
- }
- if (isReq) {
- if
(message.containsKey(PolicyBasedWSS4JOutInterceptor.SECURITY_PROCESSED)) {
- //The full policy interceptors handled this
- return;
- }
- addUsernameToken(message);
- } else {
- if (message.containsKey(WSS4JInInterceptor.SECURITY_PROCESSED)) {
- //The full policy interceptors handled this
- return;
- }
- processUsernameToken(message);
- }
- }
-
-
- private void processUsernameToken(SoapMessage message) {
+ protected void processToken(SoapMessage message) {
Header h = findSecurityHeader(message, false);
if (h == null) {
return;
@@ -149,7 +97,7 @@ public class UsernameTokenInterceptor ex
WSHandlerResult rResult = new WSHandlerResult(null, v);
results.add(0, rResult);
- assertUsernameTokens(message, princ);
+ assertTokens(message, princ);
message.put(WSS4JInInterceptor.PRINCIPAL_RESULT,
princ);
SecurityContext sc =
message.get(SecurityContext.class);
@@ -256,7 +204,11 @@ public class UsernameTokenInterceptor ex
return null;
}
- private UsernameToken assertUsernameTokens(SoapMessage message,
WSUsernameTokenPrincipal princ) {
+ protected UsernameToken assertTokens(SoapMessage message) {
+ return (UsernameToken)assertTokens(message, null);
+ }
+
+ private UsernameToken assertTokens(SoapMessage message,
WSUsernameTokenPrincipal princ) {
AssertionInfoMap aim = message.get(AssertionInfoMap.class);
Collection<AssertionInfo> ais =
aim.getAssertionInfo(SP12Constants.USERNAME_TOKEN);
UsernameToken tok = null;
@@ -302,8 +254,8 @@ public class UsernameTokenInterceptor ex
return false;
}
- private void addUsernameToken(SoapMessage message) {
- UsernameToken tok = assertUsernameTokens(message, null);
+ protected void addToken(SoapMessage message) {
+ UsernameToken tok = assertTokens(message, null);
Header h = findSecurityHeader(message, true);
WSSecUsernameToken utBuilder =
@@ -324,26 +276,6 @@ public class UsernameTokenInterceptor ex
}
- private Header findSecurityHeader(SoapMessage message, boolean create) {
- for (Header h : message.getHeaders()) {
- QName n = h.getName();
- if (n.getLocalPart().equals("Security")
- && (n.getNamespaceURI().equals(WSConstants.WSSE_NS)
- || n.getNamespaceURI().equals(WSConstants.WSSE11_NS))) {
- return h;
- }
- }
- if (!create) {
- return null;
- }
- Document doc = DOMUtils.createDocument();
- Element el = doc.createElementNS(WSConstants.WSSE_NS, "wsse:Security");
- el.setAttributeNS(WSConstants.XMLNS_NS, "xmlns:wsse",
WSConstants.WSSE_NS);
- SoapHeader sh = new SoapHeader(new QName(WSConstants.WSSE_NS,
"Security"), el);
- sh.setMustUnderstand(true);
- message.getHeaders().add(sh);
- return sh;
- }
protected WSSecUsernameToken addUsernameToken(SoapMessage message,
UsernameToken token) {
String userName =
(String)message.getContextualProperty(SecurityConstants.USERNAME);
WSSConfig wssConfig =
(WSSConfig)message.getContextualProperty(WSSConfig.class.getName());
@@ -384,78 +316,6 @@ public class UsernameTokenInterceptor ex
}
return null;
}
- private CallbackHandler getCallback(SoapMessage message) {
- //Then try to get the password from the given callback handler
- Object o =
message.getContextualProperty(SecurityConstants.CALLBACK_HANDLER);
-
- CallbackHandler handler = null;
- if (o instanceof CallbackHandler) {
- handler = (CallbackHandler)o;
- } else if (o instanceof String) {
- try {
- handler = (CallbackHandler)ClassLoaderUtils
- .loadClass((String)o, this.getClass()).newInstance();
- } catch (Exception e) {
- handler = null;
- }
- }
- return handler;
- }
- public String getPassword(String userName, UsernameToken info, int type,
SoapMessage message) {
- //Then try to get the password from the given callback handler
-
- CallbackHandler handler = getCallback(message);
- if (handler == null) {
- policyNotAsserted(info, "No callback handler and no password
available", message);
- return null;
- }
-
- WSPasswordCallback[] cb = {new WSPasswordCallback(userName,
- type)};
- try {
- handler.handle(cb);
- } catch (Exception e) {
- policyNotAsserted(info, e, message);
- }
-
- //get the password
- return cb[0].getPassword();
- }
- protected void policyNotAsserted(UsernameToken assertion, String reason,
SoapMessage message) {
- if (assertion == null) {
- return;
- }
- AssertionInfoMap aim = message.get(AssertionInfoMap.class);
- Collection<AssertionInfo> ais;
- ais = aim.get(assertion.getName());
- if (ais != null) {
- for (AssertionInfo ai : ais) {
- if (ai.getAssertion() == assertion) {
- ai.setNotAsserted(reason);
- }
- }
- }
- if (!assertion.isOptional()) {
- throw new PolicyException(new Message(reason, LOG));
- }
- }
- protected void policyNotAsserted(UsernameToken assertion, Exception
reason, SoapMessage message) {
- if (assertion == null) {
- return;
- }
- AssertionInfoMap aim = message.get(AssertionInfoMap.class);
- Collection<AssertionInfo> ais;
- ais = aim.get(assertion.getName());
- if (ais != null) {
- for (AssertionInfo ai : ais) {
- if (ai.getAssertion() == assertion) {
- ai.setNotAsserted(reason.getMessage());
- }
- }
- }
- throw new PolicyException(reason);
- }
-
}
Modified:
cxf/trunk/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/kerberos/KerberosTokenTest.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/kerberos/KerberosTokenTest.java?rev=1439362&r1=1439361&r2=1439362&view=diff
==============================================================================
---
cxf/trunk/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/kerberos/KerberosTokenTest.java
(original)
+++
cxf/trunk/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/kerberos/KerberosTokenTest.java
Mon Jan 28 12:26:53 2013
@@ -155,6 +155,35 @@ public class KerberosTokenTest extends A
}
@org.junit.Test
+ public void testKerberosSupporting() throws Exception {
+
+ if (!unrestrictedPoliciesInstalled) {
+ return;
+ }
+
+ SpringBusFactory bf = new SpringBusFactory();
+ URL busFile = KerberosTokenTest.class.getResource("client/client.xml");
+
+ Bus bus = bf.createBus(busFile.toString());
+ SpringBusFactory.setDefaultBus(bus);
+ SpringBusFactory.setThreadDefaultBus(bus);
+
+ URL wsdl =
KerberosTokenTest.class.getResource("DoubleItKerberos.wsdl");
+ Service service = Service.create(wsdl, SERVICE_QNAME);
+ QName portQName = new QName(NAMESPACE,
"DoubleItKerberosSupportingPort");
+ DoubleItPortType kerberosPort =
+ service.getPort(portQName, DoubleItPortType.class);
+
+ updateAddressPort(kerberosPort, PORT);
+
+ int result = kerberosPort.doubleIt(25);
+ assertTrue(result == 50);
+
+ ((java.io.Closeable)kerberosPort).close();
+ bus.shutdown(true);
+ }
+
+ @org.junit.Test
public void testKerberosOverAsymmetric() throws Exception {
if (!unrestrictedPoliciesInstalled) {
@@ -396,5 +425,4 @@ public class KerberosTokenTest extends A
bus.shutdown(true);
}
-
}
Modified:
cxf/trunk/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/kerberos/DoubleItKerberos.wsdl
URL:
http://svn.apache.org/viewvc/cxf/trunk/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/kerberos/DoubleItKerberos.wsdl?rev=1439362&r1=1439361&r2=1439362&view=diff
==============================================================================
---
cxf/trunk/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/kerberos/DoubleItKerberos.wsdl
(original)
+++
cxf/trunk/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/kerberos/DoubleItKerberos.wsdl
Mon Jan 28 12:26:53 2013
@@ -90,6 +90,24 @@
</wsdl:operation>
</wsdl:binding>
+ <wsdl:binding name="DoubleItKerberosSupportingBinding"
type="tns:DoubleItPortType">
+ <wsp:PolicyReference URI="#DoubleItKerberosSupportingPolicy" />
+ <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:binding name="DoubleItKerberosAsymmetricBinding"
type="tns:DoubleItPortType">
<wsp:PolicyReference URI="#DoubleItKerberosAsymmetricPolicy" />
<soap:binding style="document"
@@ -282,6 +300,10 @@
binding="tns:DoubleItKerberosSymmetricSupportingBinding">
<soap:address
location="http://localhost:9001/DoubleItKerberosSymmetricSupporting" />
</wsdl:port>
+ <wsdl:port name="DoubleItKerberosSupportingPort"
+ binding="tns:DoubleItKerberosSupportingBinding">
+ <soap:address
location="http://localhost:9001/DoubleItKerberosSupporting" />
+ </wsdl:port>
<wsdl:port name="DoubleItKerberosAsymmetricPort"
binding="tns:DoubleItKerberosAsymmetricBinding">
<soap:address
location="http://localhost:9001/DoubleItKerberosAsymmetric" />
@@ -461,6 +483,23 @@
</wsp:ExactlyOne>
</wsp:Policy>
+ <wsp:Policy wsu:Id="DoubleItKerberosSupportingPolicy">
+ <wsp:ExactlyOne>
+ <wsp:All>
+ <sp:SupportingTokens>
+ <wsp:Policy>
+ <sp:KerberosToken
+
sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/Once">
+ <wsp:Policy>
+ <sp:WssGssKerberosV5ApReqToken11/>
+ </wsp:Policy>
+ </sp:KerberosToken>
+ </wsp:Policy>
+ </sp:SupportingTokens>
+ </wsp:All>
+ </wsp:ExactlyOne>
+ </wsp:Policy>
+
<wsp:Policy wsu:Id="DoubleItKerberosAsymmetricPolicy">
<wsp:ExactlyOne>
<wsp:All>
Modified:
cxf/trunk/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/kerberos/client/client.xml
URL:
http://svn.apache.org/viewvc/cxf/trunk/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/kerberos/client/client.xml?rev=1439362&r1=1439361&r2=1439362&view=diff
==============================================================================
---
cxf/trunk/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/kerberos/client/client.xml
(original)
+++
cxf/trunk/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/kerberos/client/client.xml
Mon Jan 28 12:26:53 2013
@@ -97,6 +97,22 @@
</jaxws:properties>
</jaxws:client>
+ <jaxws:client
name="{http://www.example.org/contract/DoubleIt}DoubleItKerberosSupportingPort"
+ createdFromAPI="true">
+ <jaxws:properties>
+ <entry key="ws-security.encryption.properties"
+
value="org/apache/cxf/systest/ws/wssec10/client/bob.properties"/>
+ <entry key="ws-security.encryption.username" value="bob"/>
+ <entry key="ws-security.kerberos.client">
+ <bean
class="org.apache.cxf.ws.security.kerberos.KerberosClient">
+ <constructor-arg ref="cxf"/>
+ <property name="contextName" value="alice"/>
+ <property name="serviceName"
value="[email protected]"/>
+ </bean>
+ </entry>
+ </jaxws:properties>
+ </jaxws:client>
+
<jaxws:client
name="{http://www.example.org/contract/DoubleIt}DoubleItKerberosAsymmetricPort"
createdFromAPI="true">
<jaxws:properties>
Modified:
cxf/trunk/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/kerberos/server/server.xml
URL:
http://svn.apache.org/viewvc/cxf/trunk/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/kerberos/server/server.xml?rev=1439362&r1=1439361&r2=1439362&view=diff
==============================================================================
---
cxf/trunk/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/kerberos/server/server.xml
(original)
+++
cxf/trunk/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/kerberos/server/server.xml
Mon Jan 28 12:26:53 2013
@@ -137,6 +137,25 @@
</jaxws:endpoint>
<jaxws:endpoint
+ id="Kerberosupporting"
+
address="http://localhost:${testutil.ports.Server}/DoubleItKerberosSupporting"
+ serviceName="s:DoubleItService"
+ endpointName="s:DoubleItKerberosSupportingPort"
+ xmlns:s="http://www.example.org/contract/DoubleIt"
+ implementor="org.apache.cxf.systest.ws.common.DoubleItPortTypeImpl"
+ wsdlLocation="org/apache/cxf/systest/ws/kerberos/DoubleItKerberos.wsdl">
+
+ <jaxws:properties>
+ <entry key="ws-security.callback-handler"
+
value="org.apache.cxf.systest.ws.wssec10.client.KeystorePasswordCallback"/>
+ <entry key="ws-security.signature.properties"
+
value="org/apache/cxf/systest/ws/wssec10/client/bob.properties"/>
+ <entry key="ws-security.bst.validator"
value-ref="kerberosValidator"/>
+ </jaxws:properties>
+
+ </jaxws:endpoint>
+
+ <jaxws:endpoint
id="KerberosOverAsymmetric"
address="http://localhost:${testutil.ports.Server}/DoubleItKerberosAsymmetric"
serviceName="s:DoubleItService"