Author: coheigea Date: Mon Jan 28 12:52:54 2013 New Revision: 1439375 URL: http://svn.apache.org/viewvc?rev=1439375&view=rev Log: Merged revisions 1439364 via git cherry-pick from https://svn.apache.org/repos/asf/cxf/branches/2.7.x-fixes
........ r1439364 | coheigea | 2013-01-28 12:28:54 +0000 (Mon, 28 Jan 2013) | 11 lines Merged revisions 1439362 via git cherry-pick from https://svn.apache.org/repos/asf/cxf/trunk ........ r1439362 | coheigea | 2013-01-28 12:26:53 +0000 (Mon, 28 Jan 2013) | 3 lines [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 ........ ........ Conflicts: rt/ws/security/src/main/java/org/apache/cxf/ws/security/policy/interceptors/KerberosTokenInterceptorProvider.java Added: cxf/branches/2.5.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractTokenInterceptor.java cxf/branches/2.5.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/KerberosTokenInterceptor.java Modified: cxf/branches/2.5.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/policy/interceptors/KerberosTokenInterceptorProvider.java cxf/branches/2.5.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/SamlTokenInterceptor.java cxf/branches/2.5.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/UsernameTokenInterceptor.java cxf/branches/2.5.x-fixes/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/kerberos/KerberosTokenTest.java cxf/branches/2.5.x-fixes/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/kerberos/DoubleItKerberos.wsdl cxf/branches/2.5.x-fixes/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/kerberos/client/client.xml cxf/branches/2.5.x-fixes/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/kerberos/server/server.xml Modified: cxf/branches/2.5.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/policy/interceptors/KerberosTokenInterceptorProvider.java URL: http://svn.apache.org/viewvc/cxf/branches/2.5.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/policy/interceptors/KerberosTokenInterceptorProvider.java?rev=1439375&r1=1439374&r2=1439375&view=diff ============================================================================== --- cxf/branches/2.5.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/policy/interceptors/KerberosTokenInterceptorProvider.java (original) +++ cxf/branches/2.5.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/policy/interceptors/KerberosTokenInterceptorProvider.java Mon Jan 28 12:52:54 2013 @@ -42,8 +42,8 @@ import org.apache.cxf.ws.security.policy import org.apache.cxf.ws.security.tokenstore.MemoryTokenStore; import org.apache.cxf.ws.security.tokenstore.SecurityToken; import org.apache.cxf.ws.security.tokenstore.TokenStore; +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; @@ -60,16 +60,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/branches/2.5.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractTokenInterceptor.java URL: http://svn.apache.org/viewvc/cxf/branches/2.5.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractTokenInterceptor.java?rev=1439375&view=auto ============================================================================== --- cxf/branches/2.5.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractTokenInterceptor.java (added) +++ cxf/branches/2.5.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractTokenInterceptor.java Mon Jan 28 12:52:54 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(TokenStore.class.getName()); + if (tokenStore == null) { + tokenStore = (TokenStore)info.getProperty(TokenStore.class.getName()); + } + 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/branches/2.5.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/KerberosTokenInterceptor.java URL: http://svn.apache.org/viewvc/cxf/branches/2.5.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/KerberosTokenInterceptor.java?rev=1439375&view=auto ============================================================================== --- cxf/branches/2.5.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/KerberosTokenInterceptor.java (added) +++ cxf/branches/2.5.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/KerberosTokenInterceptor.java Mon Jan 28 12:52:54 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/branches/2.5.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/SamlTokenInterceptor.java URL: http://svn.apache.org/viewvc/cxf/branches/2.5.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/SamlTokenInterceptor.java?rev=1439375&r1=1439374&r2=1439375&view=diff ============================================================================== --- cxf/branches/2.5.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/SamlTokenInterceptor.java (original) +++ cxf/branches/2.5.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/SamlTokenInterceptor.java Mon Jan 28 12:52:54 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/branches/2.5.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/UsernameTokenInterceptor.java URL: http://svn.apache.org/viewvc/cxf/branches/2.5.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/UsernameTokenInterceptor.java?rev=1439375&r1=1439374&r2=1439375&view=diff ============================================================================== --- cxf/branches/2.5.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/UsernameTokenInterceptor.java (original) +++ cxf/branches/2.5.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/UsernameTokenInterceptor.java Mon Jan 28 12:52:54 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/branches/2.5.x-fixes/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/kerberos/KerberosTokenTest.java URL: http://svn.apache.org/viewvc/cxf/branches/2.5.x-fixes/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/kerberos/KerberosTokenTest.java?rev=1439375&r1=1439374&r2=1439375&view=diff ============================================================================== --- cxf/branches/2.5.x-fixes/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/kerberos/KerberosTokenTest.java (original) +++ cxf/branches/2.5.x-fixes/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/kerberos/KerberosTokenTest.java Mon Jan 28 12:52:54 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/branches/2.5.x-fixes/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/kerberos/DoubleItKerberos.wsdl URL: http://svn.apache.org/viewvc/cxf/branches/2.5.x-fixes/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/kerberos/DoubleItKerberos.wsdl?rev=1439375&r1=1439374&r2=1439375&view=diff ============================================================================== --- cxf/branches/2.5.x-fixes/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/kerberos/DoubleItKerberos.wsdl (original) +++ cxf/branches/2.5.x-fixes/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/kerberos/DoubleItKerberos.wsdl Mon Jan 28 12:52:54 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/branches/2.5.x-fixes/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/kerberos/client/client.xml URL: http://svn.apache.org/viewvc/cxf/branches/2.5.x-fixes/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/kerberos/client/client.xml?rev=1439375&r1=1439374&r2=1439375&view=diff ============================================================================== --- cxf/branches/2.5.x-fixes/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/kerberos/client/client.xml (original) +++ cxf/branches/2.5.x-fixes/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/kerberos/client/client.xml Mon Jan 28 12:52:54 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/branches/2.5.x-fixes/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/kerberos/server/server.xml URL: http://svn.apache.org/viewvc/cxf/branches/2.5.x-fixes/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/kerberos/server/server.xml?rev=1439375&r1=1439374&r2=1439375&view=diff ============================================================================== --- cxf/branches/2.5.x-fixes/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/kerberos/server/server.xml (original) +++ cxf/branches/2.5.x-fixes/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/kerberos/server/server.xml Mon Jan 28 12:52:54 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"
