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 ae7c3dc CXF-8010 - Avoid applying the SAAJInInterceptor to unsecured messages when using WS-SecurityPolicy ae7c3dc is described below commit ae7c3dcfc7e70b8921f1c1c49734dc11ce0fde40 Author: Colm O hEigeartaigh <cohei...@apache.org> AuthorDate: Wed Apr 3 14:40:36 2019 +0100 CXF-8010 - Avoid applying the SAAJInInterceptor to unsecured messages when using WS-SecurityPolicy --- .../security/wss4j/AbstractWSS4JInterceptor.java | 4 ++ .../wss4j/PolicyBasedWSS4JInInterceptor.java | 77 +++++++++++++++++++++- .../security/wss4j/AbstractPolicySecurityTest.java | 10 +++ .../ws/security/wss4j/AbstractSecurityTest.java | 8 +++ .../wss4j/PluggablePolicyValidatorTest.java | 11 ++++ .../security/wss4j/saml/PolicyBasedSamlTest.java | 13 ++++ .../ws/policy/operation/PolicyOperationTest.java | 2 +- 7 files changed, 123 insertions(+), 2 deletions(-) diff --git a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractWSS4JInterceptor.java b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractWSS4JInterceptor.java index e222faa..e72745f 100644 --- a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractWSS4JInterceptor.java +++ b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractWSS4JInterceptor.java @@ -99,6 +99,10 @@ public abstract class AbstractWSS4JInterceptor extends WSHandler implements Soap } public Object getProperty(Object msgContext, String key) { + if (msgContext == null) { + return null; + } + Object obj = SecurityUtils.getSecurityPropertyValue(key, (Message)msgContext); if (obj == null) { obj = getOption(key); diff --git a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/PolicyBasedWSS4JInInterceptor.java b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/PolicyBasedWSS4JInInterceptor.java index 2f054e4..767be4c 100644 --- a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/PolicyBasedWSS4JInInterceptor.java +++ b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/PolicyBasedWSS4JInInterceptor.java @@ -21,17 +21,24 @@ package org.apache.cxf.ws.security.wss4j; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.logging.Logger; import javax.xml.namespace.QName; import javax.xml.soap.SOAPException; import javax.xml.stream.XMLStreamException; +import org.w3c.dom.Attr; import org.w3c.dom.Element; +import org.apache.cxf.binding.soap.SoapFault; import org.apache.cxf.binding.soap.SoapMessage; +import org.apache.cxf.common.i18n.Message; +import org.apache.cxf.common.logging.LogUtils; +import org.apache.cxf.headers.Header; import org.apache.cxf.helpers.CastUtils; import org.apache.cxf.interceptor.Fault; import org.apache.cxf.message.MessageUtils; @@ -44,6 +51,7 @@ import org.apache.cxf.ws.security.wss4j.policyvalidators.PolicyValidatorParamete import org.apache.cxf.ws.security.wss4j.policyvalidators.SecurityPolicyValidator; import org.apache.cxf.ws.security.wss4j.policyvalidators.ValidatorUtils; import org.apache.wss4j.common.ConfigurationConstants; +import org.apache.wss4j.common.WSS4JConstants; import org.apache.wss4j.common.crypto.Crypto; import org.apache.wss4j.common.crypto.PasswordEncryptor; import org.apache.wss4j.common.ext.WSSecurityException; @@ -53,6 +61,7 @@ import org.apache.wss4j.dom.engine.WSSecurityEngineResult; import org.apache.wss4j.dom.handler.RequestData; import org.apache.wss4j.dom.handler.WSHandlerResult; import org.apache.wss4j.dom.message.token.Timestamp; +import org.apache.wss4j.dom.util.WSSecurityUtil; import org.apache.wss4j.policy.SP12Constants; import org.apache.wss4j.policy.SP13Constants; import org.apache.wss4j.policy.SPConstants; @@ -65,6 +74,9 @@ import org.apache.wss4j.policy.model.Wss11; * */ public class PolicyBasedWSS4JInInterceptor extends WSS4JInInterceptor { + + private static final Logger LOG = LogUtils.getL7dLogger(PolicyBasedWSS4JInInterceptor.class); + /** * */ @@ -76,11 +88,73 @@ public class PolicyBasedWSS4JInInterceptor extends WSS4JInInterceptor { AssertionInfoMap aim = msg.get(AssertionInfoMap.class); boolean enableStax = MessageUtils.getContextualBoolean(msg, SecurityConstants.ENABLE_STREAMING_SECURITY); - if (aim != null && !enableStax) { + if (aim != null && !enableStax && !msg.containsKey(SECURITY_PROCESSED) + && !isGET(msg) && msg.getExchange() != null) { + try { + // First check to see if we have a security header before we apply the SAAJInInterceptor + // If there is no security header then we can just assert the policies and proceed + String actor = (String)getOption(ConfigurationConstants.ACTOR); + if (actor == null) { + actor = (String)msg.getContextualProperty(SecurityConstants.ACTOR); + } + if (!containsSecurityHeader(msg, actor, msg.getVersion().getVersion() != 1.1)) { + LOG.fine("The request contains no security header, so the SAAJInInterceptor is not applied"); + computeAction(msg, new RequestData()); + + boolean utWithCallbacks = + MessageUtils.getContextualBoolean(msg, SecurityConstants.VALIDATE_TOKEN, true); + doResults(msg, actor, + null, + null, + new WSHandlerResult(actor, Collections.emptyList(), Collections.emptyMap()), + utWithCallbacks); + msg.put(SECURITY_PROCESSED, Boolean.TRUE); + return; + } + } catch (WSSecurityException e) { + throw WSS4JUtils.createSoapFault(msg, msg.getVersion(), e); + } catch (XMLStreamException e) { + throw new SoapFault(new Message("STAX_EX", LOG), e, msg.getVersion().getSender()); + } catch (SOAPException e) { + throw new SoapFault(new Message("SAAJ_EX", LOG), e, msg.getVersion().getSender()); + } + + super.handleMessage(msg); } } + private boolean containsSecurityHeader(SoapMessage message, String actor, boolean soap12) + throws WSSecurityException { + String actorLocal = WSConstants.ATTR_ACTOR; + String soapNamespace = WSConstants.URI_SOAP11_ENV; + if (soap12) { + actorLocal = WSConstants.ATTR_ROLE; + soapNamespace = WSConstants.URI_SOAP12_ENV; + } + + // + // Iterate through the security headers + // + for (Header h : message.getHeaders()) { + QName n = h.getName(); + if (WSConstants.WSSE_LN.equals(n.getLocalPart()) + && (n.getNamespaceURI().equals(WSS4JConstants.WSSE_NS) + || n.getNamespaceURI().equals(WSS4JConstants.OLD_WSSE_NS))) { + + Element elem = (Element)h.getObject(); + Attr attr = elem.getAttributeNodeNS(soapNamespace, actorLocal); + String hActor = (attr != null) ? attr.getValue() : null; + + if (WSSecurityUtil.isActorEqual(actor, hActor)) { + return true; + } + } + } + + return false; + } + private void handleWSS11(AssertionInfoMap aim, SoapMessage message) { if (isRequestor(message)) { message.put(ConfigurationConstants.ENABLE_SIGNATURE_CONFIRMATION, "false"); @@ -383,6 +457,7 @@ public class PolicyBasedWSS4JInInterceptor extends WSS4JInInterceptor { } } + @Override protected void computeAction(SoapMessage message, RequestData data) throws WSSecurityException { String action = getString(ConfigurationConstants.ACTION, message); if (action == null) { diff --git a/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/AbstractPolicySecurityTest.java b/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/AbstractPolicySecurityTest.java index ba15034..9246a1b 100644 --- a/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/AbstractPolicySecurityTest.java +++ b/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/AbstractPolicySecurityTest.java @@ -43,6 +43,7 @@ import org.w3c.dom.NodeList; import org.apache.cxf.Bus; import org.apache.cxf.BusException; import org.apache.cxf.binding.Binding; +import org.apache.cxf.binding.soap.SoapHeader; import org.apache.cxf.binding.soap.SoapMessage; import org.apache.cxf.endpoint.Endpoint; import org.apache.cxf.feature.Feature; @@ -76,6 +77,7 @@ import org.apache.wss4j.dom.WSDataRef; import org.apache.wss4j.dom.engine.WSSecurityEngineResult; import org.apache.wss4j.dom.handler.WSHandlerConstants; import org.apache.wss4j.dom.handler.WSHandlerResult; +import org.apache.wss4j.dom.util.WSSecurityUtil; import org.apache.wss4j.policy.SP12Constants; import static org.junit.Assert.assertEquals; @@ -263,6 +265,14 @@ public abstract class AbstractPolicySecurityTest extends AbstractSecurityTest { SoapMessage inmsg = this.getSoapMessageForDom(document, aim); + Element securityHeaderElem = WSSecurityUtil.getSecurityHeader(document, ""); + if (securityHeaderElem != null) { + SoapHeader securityHeader = new SoapHeader(new QName(securityHeaderElem.getNamespaceURI(), + securityHeaderElem.getLocalName()), + securityHeaderElem); + inmsg.getHeaders().add(securityHeader); + } + inHandler.handleMessage(inmsg); for (CoverageType type : types) { diff --git a/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/AbstractSecurityTest.java b/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/AbstractSecurityTest.java index e622ba7..a39c672 100644 --- a/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/AbstractSecurityTest.java +++ b/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/AbstractSecurityTest.java @@ -25,6 +25,7 @@ import java.io.InputStream; import java.util.List; import java.util.Map; +import javax.xml.namespace.QName; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; @@ -36,8 +37,10 @@ import javax.xml.stream.XMLStreamReader; import javax.xml.stream.XMLStreamWriter; import org.w3c.dom.Document; +import org.w3c.dom.Element; import org.apache.cxf.binding.soap.Soap11; +import org.apache.cxf.binding.soap.SoapHeader; import org.apache.cxf.binding.soap.SoapMessage; import org.apache.cxf.binding.soap.saaj.SAAJStreamWriter; import org.apache.cxf.helpers.DOMUtils.NullResolver; @@ -48,6 +51,7 @@ import org.apache.cxf.phase.PhaseInterceptor; import org.apache.cxf.staxutils.StaxUtils; import org.apache.cxf.test.AbstractCXFTest; import org.apache.wss4j.common.WSS4JConstants; +import org.apache.wss4j.dom.util.WSSecurityUtil; public abstract class AbstractSecurityTest extends AbstractCXFTest { @@ -152,6 +156,10 @@ public abstract class AbstractSecurityTest extends AbstractCXFTest { ex.setInMessage(inmsg); inmsg.setContent(SOAPMessage.class, saajMsg); + Element securityHeaderElem = WSSecurityUtil.getSecurityHeader(doc, ""); + SoapHeader securityHeader = new SoapHeader(new QName(securityHeaderElem.getNamespaceURI(), + securityHeaderElem.getLocalName()), securityHeaderElem); + inmsg.getHeaders().add(securityHeader); inHandler.handleMessage(inmsg); diff --git a/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/PluggablePolicyValidatorTest.java b/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/PluggablePolicyValidatorTest.java index 1f55398..c84ef8c 100644 --- a/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/PluggablePolicyValidatorTest.java +++ b/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/PluggablePolicyValidatorTest.java @@ -27,7 +27,9 @@ import java.util.Map; 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.ws.policy.AssertionInfo; import org.apache.cxf.ws.policy.AssertionInfoMap; @@ -37,6 +39,7 @@ import org.apache.cxf.ws.security.wss4j.CryptoCoverageUtil.CoverageType; import org.apache.cxf.ws.security.wss4j.policyvalidators.PolicyValidatorParameters; import org.apache.cxf.ws.security.wss4j.policyvalidators.SecurityPolicyValidator; import org.apache.neethi.Policy; +import org.apache.wss4j.dom.util.WSSecurityUtil; import org.apache.wss4j.policy.SP12Constants; import org.junit.Test; @@ -133,6 +136,14 @@ public class PluggablePolicyValidatorTest extends AbstractPolicySecurityTest { SoapMessage inmsg = this.getSoapMessageForDom(document, aim); + Element securityHeaderElem = WSSecurityUtil.getSecurityHeader(document, ""); + if (securityHeaderElem != null) { + SoapHeader securityHeader = new SoapHeader(new QName(securityHeaderElem.getNamespaceURI(), + securityHeaderElem.getLocalName()), + securityHeaderElem); + inmsg.getHeaders().add(securityHeader); + } + if (validators != null) { inmsg.put(SecurityConstants.POLICY_VALIDATOR_MAP, validators); } diff --git a/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/saml/PolicyBasedSamlTest.java b/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/saml/PolicyBasedSamlTest.java index c7207bf..506115b 100644 --- a/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/saml/PolicyBasedSamlTest.java +++ b/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/saml/PolicyBasedSamlTest.java @@ -22,14 +22,19 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +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.ws.policy.AssertionInfoMap; import org.apache.cxf.ws.security.SecurityConstants; import org.apache.cxf.ws.security.wss4j.AbstractPolicySecurityTest; import org.apache.cxf.ws.security.wss4j.CryptoCoverageUtil.CoverageType; import org.apache.cxf.ws.security.wss4j.PolicyBasedWSS4JInInterceptor; +import org.apache.wss4j.dom.util.WSSecurityUtil; import org.apache.wss4j.dom.validate.SamlAssertionValidator; import org.apache.wss4j.policy.SP12Constants; @@ -115,6 +120,14 @@ public class PolicyBasedSamlTest extends AbstractPolicySecurityTest { SoapMessage inmsg = this.getSoapMessageForDom(document, aim); + Element securityHeaderElem = WSSecurityUtil.getSecurityHeader(document, ""); + if (securityHeaderElem != null) { + SoapHeader securityHeader = new SoapHeader(new QName(securityHeaderElem.getNamespaceURI(), + securityHeaderElem.getLocalName()), + securityHeaderElem); + inmsg.getHeaders().add(securityHeader); + } + // Necessary because the Bearer Assertion does not have an internal signature SamlAssertionValidator assertionValidator = new SamlAssertionValidator(); assertionValidator.setRequireBearerSignature(false); diff --git a/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/policy/operation/PolicyOperationTest.java b/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/policy/operation/PolicyOperationTest.java index 6dbf8da..3afec9a 100644 --- a/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/policy/operation/PolicyOperationTest.java +++ b/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/policy/operation/PolicyOperationTest.java @@ -103,7 +103,7 @@ public class PolicyOperationTest extends AbstractBusClientServerTestBase { service.getPort(portQName, DoubleItPortType2.class); updateAddressPort(port, PORT); - assertEquals(50, port.doubleIt(25)); + assertEquals(50, port.doubleIt2(25)); ((java.io.Closeable)port).close(); bus.shutdown(true);