[CXF-6334] - Moved remaining policy validation functionality from the PolicyBasedWSS4JInInterceptor
Project: http://git-wip-us.apache.org/repos/asf/cxf/repo Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/449a10ca Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/449a10ca Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/449a10ca Branch: refs/heads/master Commit: 449a10ca63d5b3507861eb4da9f56c215eddccfb Parents: 8de3bac Author: Colm O hEigeartaigh <[email protected]> Authored: Wed Apr 8 14:47:16 2015 +0100 Committer: Colm O hEigeartaigh <[email protected]> Committed: Wed Apr 8 14:51:26 2015 +0100 ---------------------------------------------------------------------- .../cxf/ws/security/policy/PolicyUtils.java | 65 ++++- .../wss4j/PolicyBasedWSS4JInInterceptor.java | 274 +------------------ .../PolicyValidatorParameters.java | 29 ++ .../RequiredElementsPolicyValidator.java | 86 ++++++ .../RequiredPartsPolicyValidator.java | 68 +++++ .../SecuredElementsPolicyValidator.java | 133 +++++++++ .../SecuredPartsPolicyValidator.java | 168 ++++++++++++ 7 files changed, 545 insertions(+), 278 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cxf/blob/449a10ca/rt/ws/security/src/main/java/org/apache/cxf/ws/security/policy/PolicyUtils.java ---------------------------------------------------------------------- diff --git a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/policy/PolicyUtils.java b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/policy/PolicyUtils.java index 95a2f6b..d493f05 100644 --- a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/policy/PolicyUtils.java +++ b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/policy/PolicyUtils.java @@ -31,6 +31,8 @@ import org.apache.cxf.message.Message; 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.wss4j.CryptoCoverageUtil.CoverageScope; +import org.apache.cxf.ws.security.wss4j.CryptoCoverageUtil.CoverageType; import org.apache.cxf.ws.security.wss4j.policyvalidators.AlgorithmSuitePolicyValidator; import org.apache.cxf.ws.security.wss4j.policyvalidators.AsymmetricBindingPolicyValidator; import org.apache.cxf.ws.security.wss4j.policyvalidators.ConcreteSupportingTokenPolicyValidator; @@ -40,7 +42,11 @@ import org.apache.cxf.ws.security.wss4j.policyvalidators.EndorsingTokenPolicyVal import org.apache.cxf.ws.security.wss4j.policyvalidators.IssuedTokenPolicyValidator; import org.apache.cxf.ws.security.wss4j.policyvalidators.KerberosTokenPolicyValidator; import org.apache.cxf.ws.security.wss4j.policyvalidators.LayoutPolicyValidator; +import org.apache.cxf.ws.security.wss4j.policyvalidators.RequiredElementsPolicyValidator; +import org.apache.cxf.ws.security.wss4j.policyvalidators.RequiredPartsPolicyValidator; import org.apache.cxf.ws.security.wss4j.policyvalidators.SamlTokenPolicyValidator; +import org.apache.cxf.ws.security.wss4j.policyvalidators.SecuredElementsPolicyValidator; +import org.apache.cxf.ws.security.wss4j.policyvalidators.SecuredPartsPolicyValidator; import org.apache.cxf.ws.security.wss4j.policyvalidators.SecurityContextTokenPolicyValidator; import org.apache.cxf.ws.security.wss4j.policyvalidators.SecurityPolicyValidator; import org.apache.cxf.ws.security.wss4j.policyvalidators.SignedEncryptedTokenPolicyValidator; @@ -67,7 +73,17 @@ public final class PolicyUtils { new HashMap<>(); static { - // Tokens + configureTokenValidators(); + configureBindingValidators(); + configureSupportingTokenValidators(); + configurePartsValidators(); + } + + private PolicyUtils() { + // complete + } + + private static void configureTokenValidators() { SecurityPolicyValidator validator = new X509TokenPolicyValidator(); DEFAULT_SECURITY_POLICY_VALIDATORS.put(SP12Constants.X509_TOKEN, validator); DEFAULT_SECURITY_POLICY_VALIDATORS.put(SP11Constants.X509_TOKEN, validator); @@ -89,9 +105,10 @@ public final class PolicyUtils { validator = new KerberosTokenPolicyValidator(); DEFAULT_SECURITY_POLICY_VALIDATORS.put(SP12Constants.KERBEROS_TOKEN, validator); DEFAULT_SECURITY_POLICY_VALIDATORS.put(SP11Constants.KERBEROS_TOKEN, validator); - - // Bindings - validator = new TransportBindingPolicyValidator(); + } + + private static void configureBindingValidators() { + SecurityPolicyValidator validator = new TransportBindingPolicyValidator(); DEFAULT_SECURITY_POLICY_VALIDATORS.put(SP12Constants.TRANSPORT_BINDING, validator); DEFAULT_SECURITY_POLICY_VALIDATORS.put(SP11Constants.TRANSPORT_BINDING, validator); validator = new SymmetricBindingPolicyValidator(); @@ -106,9 +123,10 @@ public final class PolicyUtils { validator = new LayoutPolicyValidator(); DEFAULT_SECURITY_POLICY_VALIDATORS.put(SP12Constants.LAYOUT, validator); DEFAULT_SECURITY_POLICY_VALIDATORS.put(SP11Constants.LAYOUT, validator); - - // Supporting Tokens - validator = new ConcreteSupportingTokenPolicyValidator(); + } + + private static void configureSupportingTokenValidators() { + SecurityPolicyValidator validator = new ConcreteSupportingTokenPolicyValidator(); DEFAULT_SECURITY_POLICY_VALIDATORS.put(SP12Constants.SUPPORTING_TOKENS, validator); DEFAULT_SECURITY_POLICY_VALIDATORS.put(SP11Constants.SUPPORTING_TOKENS, validator); validator = new SignedTokenPolicyValidator(); @@ -130,10 +148,37 @@ public final class PolicyUtils { DEFAULT_SECURITY_POLICY_VALIDATORS.put(SP12Constants.SIGNED_ENDORSING_ENCRYPTED_SUPPORTING_TOKENS, validator); } - private PolicyUtils() { - // complete + private static void configurePartsValidators() { + SecurityPolicyValidator validator = new SecuredPartsPolicyValidator(); + ((SecuredPartsPolicyValidator)validator).setCoverageType(CoverageType.SIGNED); + DEFAULT_SECURITY_POLICY_VALIDATORS.put(SP12Constants.SIGNED_PARTS, validator); + DEFAULT_SECURITY_POLICY_VALIDATORS.put(SP11Constants.SIGNED_PARTS, validator); + validator = new SecuredPartsPolicyValidator(); + ((SecuredPartsPolicyValidator)validator).setCoverageType(CoverageType.ENCRYPTED); + DEFAULT_SECURITY_POLICY_VALIDATORS.put(SP12Constants.ENCRYPTED_PARTS, validator); + DEFAULT_SECURITY_POLICY_VALIDATORS.put(SP11Constants.ENCRYPTED_PARTS, validator); + validator = new SecuredElementsPolicyValidator(); + ((SecuredElementsPolicyValidator)validator).setCoverageType(CoverageType.SIGNED); + DEFAULT_SECURITY_POLICY_VALIDATORS.put(SP12Constants.SIGNED_ELEMENTS, validator); + DEFAULT_SECURITY_POLICY_VALIDATORS.put(SP11Constants.SIGNED_ELEMENTS, validator); + validator = new SecuredElementsPolicyValidator(); + ((SecuredElementsPolicyValidator)validator).setCoverageType(CoverageType.ENCRYPTED); + ((SecuredElementsPolicyValidator)validator).setCoverageScope(CoverageScope.ELEMENT); + DEFAULT_SECURITY_POLICY_VALIDATORS.put(SP12Constants.ENCRYPTED_ELEMENTS, validator); + DEFAULT_SECURITY_POLICY_VALIDATORS.put(SP11Constants.ENCRYPTED_ELEMENTS, validator); + validator = new SecuredElementsPolicyValidator(); + ((SecuredElementsPolicyValidator)validator).setCoverageType(CoverageType.ENCRYPTED); + ((SecuredElementsPolicyValidator)validator).setCoverageScope(CoverageScope.CONTENT); + DEFAULT_SECURITY_POLICY_VALIDATORS.put(SP12Constants.CONTENT_ENCRYPTED_ELEMENTS, validator); + DEFAULT_SECURITY_POLICY_VALIDATORS.put(SP11Constants.CONTENT_ENCRYPTED_ELEMENTS, validator); + validator = new RequiredPartsPolicyValidator(); + DEFAULT_SECURITY_POLICY_VALIDATORS.put(SP12Constants.REQUIRED_PARTS, validator); + DEFAULT_SECURITY_POLICY_VALIDATORS.put(SP11Constants.REQUIRED_PARTS, validator); + validator = new RequiredElementsPolicyValidator(); + DEFAULT_SECURITY_POLICY_VALIDATORS.put(SP12Constants.REQUIRED_ELEMENTS, validator); + DEFAULT_SECURITY_POLICY_VALIDATORS.put(SP11Constants.REQUIRED_ELEMENTS, validator); } - + public static Collection<AssertionInfo> getAllAssertionsByLocalname( AssertionInfoMap aim, String localname ) { http://git-wip-us.apache.org/repos/asf/cxf/blob/449a10ca/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/PolicyBasedWSS4JInInterceptor.java ---------------------------------------------------------------------- diff --git a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/PolicyBasedWSS4JInInterceptor.java b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/PolicyBasedWSS4JInInterceptor.java index 833c8f9..6b09107 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 @@ -20,39 +20,25 @@ package org.apache.cxf.ws.security.wss4j; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; 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 javax.xml.xpath.XPath; -import javax.xml.xpath.XPathConstants; -import javax.xml.xpath.XPathExpressionException; -import javax.xml.xpath.XPathFactory; import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; import org.apache.cxf.binding.soap.SoapMessage; -import org.apache.cxf.common.logging.LogUtils; import org.apache.cxf.helpers.CastUtils; -import org.apache.cxf.helpers.DOMUtils; -import org.apache.cxf.helpers.MapNamespaceContext; import org.apache.cxf.interceptor.Fault; import org.apache.cxf.message.MessageUtils; -import org.apache.cxf.security.transport.TLSSessionInfo; 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.PolicyUtils; -import org.apache.cxf.ws.security.wss4j.CryptoCoverageUtil.CoverageScope; -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.wss4j.common.crypto.Crypto; @@ -65,16 +51,10 @@ import org.apache.wss4j.dom.handler.RequestData; import org.apache.wss4j.dom.handler.WSHandlerConstants; import org.apache.wss4j.dom.handler.WSHandlerResult; import org.apache.wss4j.dom.message.token.Timestamp; -import org.apache.wss4j.policy.SP11Constants; import org.apache.wss4j.policy.SP12Constants; import org.apache.wss4j.policy.SP13Constants; import org.apache.wss4j.policy.SPConstants; import org.apache.wss4j.policy.model.AlgorithmSuite; -import org.apache.wss4j.policy.model.Attachments; -import org.apache.wss4j.policy.model.Header; -import org.apache.wss4j.policy.model.RequiredElements; -import org.apache.wss4j.policy.model.RequiredParts; -import org.apache.wss4j.policy.model.SignedParts; import org.apache.wss4j.policy.model.UsernameToken; import org.apache.wss4j.policy.model.UsernameToken.PasswordType; import org.apache.wss4j.policy.model.Wss11; @@ -85,7 +65,6 @@ import org.apache.wss4j.policy.model.Wss11; public class PolicyBasedWSS4JInInterceptor extends WSS4JInInterceptor { public static final PolicyBasedWSS4JInInterceptor INSTANCE = new PolicyBasedWSS4JInInterceptor(); - private static final Logger LOG = LogUtils.getL7dLogger(PolicyBasedWSS4JInInterceptor.class); /** * @@ -368,107 +347,6 @@ public class PolicyBasedWSS4JInInterceptor extends WSS4JInInterceptor { return WSS4JUtils.getSignatureCrypto(s, message, passwordEncryptor); } - private boolean assertXPathTokens(AssertionInfoMap aim, - String name, - Collection<WSDataRef> refs, - Element soapEnvelope, - CoverageType type, - CoverageScope scope, - final XPath xpath) throws SOAPException { - Collection<AssertionInfo> ais = PolicyUtils.getAllAssertionsByLocalname(aim, name); - if (!ais.isEmpty()) { - for (AssertionInfo ai : ais) { - ai.setAsserted(true); - - RequiredElements elements = (RequiredElements)ai.getAssertion(); - - if (elements != null && elements.getXPaths() != null && !elements.getXPaths().isEmpty()) { - List<String> expressions = new ArrayList<>(); - MapNamespaceContext namespaceContext = new MapNamespaceContext(); - - for (org.apache.wss4j.policy.model.XPath xPath : elements.getXPaths()) { - expressions.add(xPath.getXPath()); - Map<String, String> namespaceMap = xPath.getPrefixNamespaceMap(); - if (namespaceMap != null) { - namespaceContext.addNamespaces(namespaceMap); - } - } - - xpath.setNamespaceContext(namespaceContext); - try { - CryptoCoverageUtil.checkCoverage(soapEnvelope, refs, - xpath, expressions, type, scope); - } catch (WSSecurityException e) { - ai.setNotAsserted("No " + type - + " element found matching one of the XPaths " - + Arrays.toString(expressions.toArray())); - } - } - } - } - return true; - } - - - private boolean assertTokens(AssertionInfoMap aim, - String name, - Collection<WSDataRef> dataRefs, - SoapMessage msg, - Element soapHeader, - Element soapBody, - CoverageType type) throws SOAPException { - Collection<AssertionInfo> ais = PolicyUtils.getAllAssertionsByLocalname(aim, name); - if (!ais.isEmpty()) { - for (AssertionInfo ai : ais) { - ai.setAsserted(true); - SignedParts p = (SignedParts)ai.getAssertion(); - - if (p.isBody()) { - try { - if (CoverageType.SIGNED.equals(type)) { - CryptoCoverageUtil.checkBodyCoverage( - soapBody, dataRefs, type, CoverageScope.ELEMENT - ); - } else { - CryptoCoverageUtil.checkBodyCoverage( - soapBody, dataRefs, type, CoverageScope.CONTENT - ); - } - } catch (WSSecurityException e) { - ai.setNotAsserted(msg.getVersion().getBody() + " not " + type); - continue; - } - } - - for (Header h : p.getHeaders()) { - try { - CryptoCoverageUtil.checkHeaderCoverage(soapHeader, dataRefs, h - .getNamespace(), h.getName(), type, - CoverageScope.ELEMENT); - } catch (WSSecurityException e) { - ai.setNotAsserted(h.getNamespace() + ":" + h.getName() + " not + " + type); - } - } - - Attachments attachments = p.getAttachments(); - if (attachments != null) { - try { - CoverageScope scope = CoverageScope.ELEMENT; - if (attachments.isContentSignatureTransform()) { - scope = CoverageScope.CONTENT; - } - CryptoCoverageUtil.checkAttachmentsCoverage(msg.getAttachments(), dataRefs, - type, scope); - } catch (WSSecurityException e) { - ai.setNotAsserted("An attachment was not signed/encrypted"); - } - } - } - } - return true; - } - - /** * Set a WSS4J AlgorithmSuite object on the RequestData context, to restrict the * algorithms that are allowed for encryption, signature, etc. @@ -620,22 +498,23 @@ public class PolicyBasedWSS4JInInterceptor extends WSS4JInInterceptor { } } + CryptoCoverageUtil.reconcileEncryptedSignedRefs(signed, encrypted); + // // Check policies // - AssertionInfoMap aim = msg.get(AssertionInfoMap.class); - if (!checkSignedEncryptedCoverage(aim, msg, soapHeader, soapBody, signed, encrypted)) { - LOG.fine("Incoming request failed signed-encrypted policy validation"); - } - PolicyValidatorParameters parameters = new PolicyValidatorParameters(); + AssertionInfoMap aim = msg.get(AssertionInfoMap.class); parameters.setAssertionInfoMap(aim); parameters.setMessage(msg); parameters.setSoapBody(soapBody); + parameters.setSoapHeader(soapHeader); parameters.setResults(results); parameters.setSignedResults(signedResults); parameters.setEncryptedResults(encryptResults); parameters.setUtWithCallbacks(utWithCallbacks); + parameters.setSigned(signed); + parameters.setEncrypted(encrypted); List<WSSecurityEngineResult> utResults = new ArrayList<>(); if (results.getActionResults().containsKey(WSConstants.UT)) { @@ -679,145 +558,4 @@ public class PolicyBasedWSS4JInInterceptor extends WSS4JInInterceptor { super.doResults(msg, actor, soapHeader, soapBody, results, utWithCallbacks); } - /** - * Check SignedParts, EncryptedParts, SignedElements, EncryptedElements, RequiredParts, etc. - */ - private boolean checkSignedEncryptedCoverage( - AssertionInfoMap aim, - SoapMessage msg, - Element soapHeader, - Element soapBody, - Collection<WSDataRef> signed, - Collection<WSDataRef> encrypted - ) throws SOAPException { - CryptoCoverageUtil.reconcileEncryptedSignedRefs(signed, encrypted); - // - // SIGNED_PARTS and ENCRYPTED_PARTS only apply to non-Transport bindings - // - boolean check = true; - if (!isTransportBinding(aim, msg)) { - assertTokens( - aim, SPConstants.SIGNED_PARTS, signed, msg, soapHeader, soapBody, CoverageType.SIGNED - ); - assertTokens( - aim, SPConstants.ENCRYPTED_PARTS, encrypted, msg, soapHeader, soapBody, - CoverageType.ENCRYPTED - ); - } - Element soapEnvelope = soapHeader.getOwnerDocument().getDocumentElement(); - if (containsXPathPolicy(aim)) { - // XPathFactory and XPath are not thread-safe so we must recreate them - // each request. - final XPathFactory factory = XPathFactory.newInstance(); - final XPath xpath = factory.newXPath(); - - assertXPathTokens(aim, SPConstants.SIGNED_ELEMENTS, signed, soapEnvelope, - CoverageType.SIGNED, CoverageScope.ELEMENT, xpath); - assertXPathTokens(aim, SPConstants.ENCRYPTED_ELEMENTS, encrypted, soapEnvelope, - CoverageType.ENCRYPTED, CoverageScope.ELEMENT, xpath); - assertXPathTokens(aim, SPConstants.CONTENT_ENCRYPTED_ELEMENTS, encrypted, - soapEnvelope, CoverageType.ENCRYPTED, CoverageScope.CONTENT, xpath); - } - - assertHeadersExists(aim, msg, soapHeader); - return check; - } - - private boolean assertHeadersExists(AssertionInfoMap aim, SoapMessage msg, Node header) - throws SOAPException { - - Collection<AssertionInfo> ais = PolicyUtils.getAllAssertionsByLocalname(aim, SPConstants.REQUIRED_PARTS); - if (!ais.isEmpty()) { - for (AssertionInfo ai : ais) { - RequiredParts rp = (RequiredParts)ai.getAssertion(); - ai.setAsserted(true); - for (Header h : rp.getHeaders()) { - QName qName = new QName(h.getNamespace(), h.getName()); - if (header == null || DOMUtils.getFirstChildWithName((Element)header, qName) == null) { - ai.setNotAsserted("No header element of name " + qName + " found."); - } - } - } - } - - ais = PolicyUtils.getAllAssertionsByLocalname(aim, SPConstants.REQUIRED_ELEMENTS); - if (!ais.isEmpty()) { - for (AssertionInfo ai : ais) { - RequiredElements rp = (RequiredElements)ai.getAssertion(); - ai.setAsserted(true); - - if (rp != null && rp.getXPaths() != null && !rp.getXPaths().isEmpty()) { - XPathFactory factory = XPathFactory.newInstance(); - for (org.apache.wss4j.policy.model.XPath xPath : rp.getXPaths()) { - Map<String, String> namespaces = xPath.getPrefixNamespaceMap(); - String expression = xPath.getXPath(); - - XPath xpath = factory.newXPath(); - if (namespaces != null) { - xpath.setNamespaceContext(new MapNamespaceContext(namespaces)); - } - NodeList list; - try { - list = (NodeList)xpath.evaluate(expression, - header, - XPathConstants.NODESET); - if (list.getLength() == 0) { - ai.setNotAsserted("No header element matching XPath " + expression + " found."); - } - } catch (XPathExpressionException e) { - ai.setNotAsserted("Invalid XPath expression " + expression + " " + e.getMessage()); - } - } - } - } - } - - return true; - } - - private boolean isTransportBinding(AssertionInfoMap aim, SoapMessage message) { - AssertionInfo symAis = PolicyUtils.getFirstAssertionByLocalname(aim, SPConstants.SYMMETRIC_BINDING); - if (symAis != null) { - return false; - } - - AssertionInfo asymAis = PolicyUtils.getFirstAssertionByLocalname(aim, SPConstants.ASYMMETRIC_BINDING); - if (asymAis != null) { - return false; - } - - AssertionInfo transAis = PolicyUtils.getFirstAssertionByLocalname(aim, SPConstants.TRANSPORT_BINDING); - if (transAis != null) { - return true; - } - - // No bindings, check if we are using TLS - TLSSessionInfo tlsInfo = message.get(TLSSessionInfo.class); - if (tlsInfo != null) { - // We don't need to check these policies for TLS - PolicyUtils.assertPolicy(aim, SP12Constants.ENCRYPTED_PARTS); - PolicyUtils.assertPolicy(aim, SP11Constants.ENCRYPTED_PARTS); - PolicyUtils.assertPolicy(aim, SP12Constants.SIGNED_PARTS); - PolicyUtils.assertPolicy(aim, SP11Constants.SIGNED_PARTS); - return true; - } - - return false; - } - - private boolean containsXPathPolicy(AssertionInfoMap aim) { - AssertionInfo ai = PolicyUtils.getFirstAssertionByLocalname(aim, SPConstants.SIGNED_ELEMENTS); - if (ai != null) { - return true; - } - - ai = PolicyUtils.getFirstAssertionByLocalname(aim, SPConstants.ENCRYPTED_ELEMENTS); - if (ai != null) { - return true; - } - - ai = PolicyUtils.getFirstAssertionByLocalname(aim, SPConstants.CONTENT_ENCRYPTED_ELEMENTS); - return ai != null; - } - } http://git-wip-us.apache.org/repos/asf/cxf/blob/449a10ca/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/policyvalidators/PolicyValidatorParameters.java ---------------------------------------------------------------------- diff --git a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/policyvalidators/PolicyValidatorParameters.java b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/policyvalidators/PolicyValidatorParameters.java index 5c032e5..647f8e6 100644 --- a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/policyvalidators/PolicyValidatorParameters.java +++ b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/policyvalidators/PolicyValidatorParameters.java @@ -19,11 +19,13 @@ package org.apache.cxf.ws.security.wss4j.policyvalidators; +import java.util.Collection; import java.util.List; import org.w3c.dom.Element; import org.apache.cxf.message.Message; import org.apache.cxf.ws.policy.AssertionInfoMap; +import org.apache.wss4j.dom.WSDataRef; import org.apache.wss4j.dom.WSSecurityEngineResult; import org.apache.wss4j.dom.handler.WSHandlerResult; @@ -34,6 +36,7 @@ public class PolicyValidatorParameters { private AssertionInfoMap assertionInfoMap; private Message message; private Element soapBody; + private Element soapHeader; private WSHandlerResult results; private List<WSSecurityEngineResult> signedResults; private List<WSSecurityEngineResult> encryptedResults; @@ -41,6 +44,8 @@ public class PolicyValidatorParameters { private List<WSSecurityEngineResult> samlResults; private Element timestampElement; private boolean utWithCallbacks; + private Collection<WSDataRef> signed; + private Collection<WSDataRef> encrypted; public Message getMessage() { return message; @@ -122,4 +127,28 @@ public class PolicyValidatorParameters { this.utWithCallbacks = utWithCallbacks; } + public Element getSoapHeader() { + return soapHeader; + } + + public void setSoapHeader(Element soapHeader) { + this.soapHeader = soapHeader; + } + + public Collection<WSDataRef> getSigned() { + return signed; + } + + public void setSigned(Collection<WSDataRef> signed) { + this.signed = signed; + } + + public Collection<WSDataRef> getEncrypted() { + return encrypted; + } + + public void setEncrypted(Collection<WSDataRef> encrypted) { + this.encrypted = encrypted; + } + } http://git-wip-us.apache.org/repos/asf/cxf/blob/449a10ca/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/policyvalidators/RequiredElementsPolicyValidator.java ---------------------------------------------------------------------- diff --git a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/policyvalidators/RequiredElementsPolicyValidator.java b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/policyvalidators/RequiredElementsPolicyValidator.java new file mode 100644 index 0000000..eb93edb --- /dev/null +++ b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/policyvalidators/RequiredElementsPolicyValidator.java @@ -0,0 +1,86 @@ +/** + * 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.policyvalidators; + +import java.util.Collection; +import java.util.Map; + +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathExpressionException; +import javax.xml.xpath.XPathFactory; + +import org.w3c.dom.NodeList; +import org.apache.cxf.helpers.MapNamespaceContext; +import org.apache.cxf.ws.policy.AssertionInfo; +import org.apache.wss4j.policy.SP11Constants; +import org.apache.wss4j.policy.SP12Constants; +import org.apache.wss4j.policy.model.RequiredElements; + +/** + * Validate a RequiredElements policy + */ +public class RequiredElementsPolicyValidator implements SecurityPolicyValidator { + + /** + * Return true if this SecurityPolicyValidator implementation is capable of validating a + * policy defined by the AssertionInfo parameter + */ + public boolean canValidatePolicy(AssertionInfo assertionInfo) { + return assertionInfo.getAssertion() != null + && (SP12Constants.REQUIRED_ELEMENTS.equals(assertionInfo.getAssertion().getName()) + || SP11Constants.REQUIRED_ELEMENTS.equals(assertionInfo.getAssertion().getName())); + } + + /** + * Validate policies. + */ + public void validatePolicies(PolicyValidatorParameters parameters, Collection<AssertionInfo> ais) { + for (AssertionInfo ai : ais) { + RequiredElements rp = (RequiredElements)ai.getAssertion(); + ai.setAsserted(true); + + if (rp != null && rp.getXPaths() != null && !rp.getXPaths().isEmpty()) { + XPathFactory factory = XPathFactory.newInstance(); + for (org.apache.wss4j.policy.model.XPath xPath : rp.getXPaths()) { + Map<String, String> namespaces = xPath.getPrefixNamespaceMap(); + String expression = xPath.getXPath(); + + XPath xpath = factory.newXPath(); + if (namespaces != null) { + xpath.setNamespaceContext(new MapNamespaceContext(namespaces)); + } + NodeList list; + try { + list = (NodeList)xpath.evaluate(expression, + parameters.getSoapHeader(), + XPathConstants.NODESET); + if (list.getLength() == 0) { + ai.setNotAsserted("No header element matching XPath " + expression + " found."); + } + } catch (XPathExpressionException e) { + ai.setNotAsserted("Invalid XPath expression " + expression + " " + e.getMessage()); + } + } + } + } + } + +} http://git-wip-us.apache.org/repos/asf/cxf/blob/449a10ca/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/policyvalidators/RequiredPartsPolicyValidator.java ---------------------------------------------------------------------- diff --git a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/policyvalidators/RequiredPartsPolicyValidator.java b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/policyvalidators/RequiredPartsPolicyValidator.java new file mode 100644 index 0000000..6066d12 --- /dev/null +++ b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/policyvalidators/RequiredPartsPolicyValidator.java @@ -0,0 +1,68 @@ +/** + * 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.policyvalidators; + +import java.util.Collection; + +import javax.xml.namespace.QName; + +import org.w3c.dom.Element; + +import org.apache.cxf.helpers.DOMUtils; +import org.apache.cxf.ws.policy.AssertionInfo; +import org.apache.wss4j.policy.SP11Constants; +import org.apache.wss4j.policy.SP12Constants; +import org.apache.wss4j.policy.model.Header; +import org.apache.wss4j.policy.model.RequiredParts; + +/** + * Validate a RequiredParts policy + */ +public class RequiredPartsPolicyValidator implements SecurityPolicyValidator { + + /** + * Return true if this SecurityPolicyValidator implementation is capable of validating a + * policy defined by the AssertionInfo parameter + */ + public boolean canValidatePolicy(AssertionInfo assertionInfo) { + return assertionInfo.getAssertion() != null + && (SP12Constants.REQUIRED_PARTS.equals(assertionInfo.getAssertion().getName()) + || SP11Constants.REQUIRED_PARTS.equals(assertionInfo.getAssertion().getName())); + } + + /** + * Validate policies. + */ + public void validatePolicies(PolicyValidatorParameters parameters, Collection<AssertionInfo> ais) { + Element header = parameters.getSoapHeader(); + + for (AssertionInfo ai : ais) { + RequiredParts rp = (RequiredParts)ai.getAssertion(); + ai.setAsserted(true); + for (Header h : rp.getHeaders()) { + QName qName = new QName(h.getNamespace(), h.getName()); + if (header == null || DOMUtils.getFirstChildWithName((Element)header, qName) == null) { + ai.setNotAsserted("No header element of name " + qName + " found."); + } + } + } + } + +} http://git-wip-us.apache.org/repos/asf/cxf/blob/449a10ca/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/policyvalidators/SecuredElementsPolicyValidator.java ---------------------------------------------------------------------- diff --git a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/policyvalidators/SecuredElementsPolicyValidator.java b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/policyvalidators/SecuredElementsPolicyValidator.java new file mode 100644 index 0000000..d1c086a --- /dev/null +++ b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/policyvalidators/SecuredElementsPolicyValidator.java @@ -0,0 +1,133 @@ +/** + * 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.policyvalidators; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathFactory; + +import org.w3c.dom.Element; +import org.apache.cxf.helpers.MapNamespaceContext; +import org.apache.cxf.ws.policy.AssertionInfo; +import org.apache.cxf.ws.security.wss4j.CryptoCoverageUtil; +import org.apache.cxf.ws.security.wss4j.CryptoCoverageUtil.CoverageScope; +import org.apache.cxf.ws.security.wss4j.CryptoCoverageUtil.CoverageType; +import org.apache.wss4j.common.ext.WSSecurityException; +import org.apache.wss4j.dom.WSDataRef; +import org.apache.wss4j.policy.SP11Constants; +import org.apache.wss4j.policy.SP12Constants; +import org.apache.wss4j.policy.model.RequiredElements; + +/** + * Validate either a SignedElements, EncryptedElements or ContentEncryptedElements policy + */ +public class SecuredElementsPolicyValidator implements SecurityPolicyValidator { + + private CoverageType coverageType = CoverageType.ENCRYPTED; + private CoverageScope coverageScope = CoverageScope.ELEMENT; + + /** + * Return true if this SecurityPolicyValidator implementation is capable of validating a + * policy defined by the AssertionInfo parameter + */ + public boolean canValidatePolicy(AssertionInfo assertionInfo) { + if (coverageType == CoverageType.SIGNED) { + return assertionInfo.getAssertion() != null + && (SP12Constants.SIGNED_ELEMENTS.equals(assertionInfo.getAssertion().getName()) + || SP11Constants.SIGNED_ELEMENTS.equals(assertionInfo.getAssertion().getName())); + } else if (coverageScope == CoverageScope.CONTENT) { + return assertionInfo.getAssertion() != null + && (SP12Constants.CONTENT_ENCRYPTED_ELEMENTS.equals(assertionInfo.getAssertion().getName()) + || SP11Constants.CONTENT_ENCRYPTED_ELEMENTS.equals(assertionInfo.getAssertion().getName())); + } else { + return assertionInfo.getAssertion() != null + && (SP12Constants.ENCRYPTED_ELEMENTS.equals(assertionInfo.getAssertion().getName()) + || SP11Constants.ENCRYPTED_ELEMENTS.equals(assertionInfo.getAssertion().getName())); + } + } + + /** + * Validate policies. + */ + public void validatePolicies(PolicyValidatorParameters parameters, Collection<AssertionInfo> ais) { + + // XPathFactory and XPath are not thread-safe so we must recreate them + // each request. + final XPathFactory factory = XPathFactory.newInstance(); + final XPath xpath = factory.newXPath(); + + Element soapEnvelope = + parameters.getSoapHeader().getOwnerDocument().getDocumentElement(); + Collection<WSDataRef> dataRefs = parameters.getEncrypted(); + if (coverageType == CoverageType.SIGNED) { + dataRefs = parameters.getSigned(); + } + + for (AssertionInfo ai : ais) { + RequiredElements elements = (RequiredElements)ai.getAssertion(); + ai.setAsserted(true); + + if (elements != null && elements.getXPaths() != null && !elements.getXPaths().isEmpty()) { + List<String> expressions = new ArrayList<>(); + MapNamespaceContext namespaceContext = new MapNamespaceContext(); + + for (org.apache.wss4j.policy.model.XPath xPath : elements.getXPaths()) { + expressions.add(xPath.getXPath()); + Map<String, String> namespaceMap = xPath.getPrefixNamespaceMap(); + if (namespaceMap != null) { + namespaceContext.addNamespaces(namespaceMap); + } + } + + xpath.setNamespaceContext(namespaceContext); + try { + CryptoCoverageUtil.checkCoverage(soapEnvelope, dataRefs, + xpath, expressions, coverageType, coverageScope); + } catch (WSSecurityException e) { + ai.setNotAsserted("No " + coverageType + + " element found matching one of the XPaths " + + Arrays.toString(expressions.toArray())); + } + } + } + } + + public CoverageType getCoverageType() { + return coverageType; + } + + public void setCoverageType(CoverageType coverageType) { + this.coverageType = coverageType; + } + + public CoverageScope getCoverageScope() { + return coverageScope; + } + + public void setCoverageScope(CoverageScope coverageScope) { + this.coverageScope = coverageScope; + } + +} http://git-wip-us.apache.org/repos/asf/cxf/blob/449a10ca/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/policyvalidators/SecuredPartsPolicyValidator.java ---------------------------------------------------------------------- diff --git a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/policyvalidators/SecuredPartsPolicyValidator.java b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/policyvalidators/SecuredPartsPolicyValidator.java new file mode 100644 index 0000000..381a2c9 --- /dev/null +++ b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/policyvalidators/SecuredPartsPolicyValidator.java @@ -0,0 +1,168 @@ +/** + * 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.policyvalidators; + +import java.util.Collection; + +import org.w3c.dom.Element; +import org.apache.cxf.message.Message; +import org.apache.cxf.security.transport.TLSSessionInfo; +import org.apache.cxf.ws.policy.AssertionInfo; +import org.apache.cxf.ws.policy.AssertionInfoMap; +import org.apache.cxf.ws.security.policy.PolicyUtils; +import org.apache.cxf.ws.security.wss4j.CryptoCoverageUtil; +import org.apache.cxf.ws.security.wss4j.CryptoCoverageUtil.CoverageScope; +import org.apache.cxf.ws.security.wss4j.CryptoCoverageUtil.CoverageType; +import org.apache.wss4j.common.ext.WSSecurityException; +import org.apache.wss4j.dom.WSDataRef; +import org.apache.wss4j.policy.SP11Constants; +import org.apache.wss4j.policy.SP12Constants; +import org.apache.wss4j.policy.SPConstants; +import org.apache.wss4j.policy.model.Attachments; +import org.apache.wss4j.policy.model.Header; +import org.apache.wss4j.policy.model.SignedParts; + +/** + * Validate either a SignedParts or EncryptedParts policy + */ +public class SecuredPartsPolicyValidator implements SecurityPolicyValidator { + + private CoverageType coverageType = CoverageType.ENCRYPTED; + + /** + * Return true if this SecurityPolicyValidator implementation is capable of validating a + * policy defined by the AssertionInfo parameter + */ + public boolean canValidatePolicy(AssertionInfo assertionInfo) { + if (coverageType == CoverageType.SIGNED) { + return assertionInfo.getAssertion() != null + && (SP12Constants.SIGNED_PARTS.equals(assertionInfo.getAssertion().getName()) + || SP11Constants.SIGNED_PARTS.equals(assertionInfo.getAssertion().getName())); + } else { + return assertionInfo.getAssertion() != null + && (SP12Constants.ENCRYPTED_PARTS.equals(assertionInfo.getAssertion().getName()) + || SP11Constants.ENCRYPTED_PARTS.equals(assertionInfo.getAssertion().getName())); + } + } + + /** + * Validate policies. + */ + public void validatePolicies(PolicyValidatorParameters parameters, Collection<AssertionInfo> ais) { + // + // SIGNED_PARTS and ENCRYPTED_PARTS only apply to non-Transport bindings + // + if (isTransportBinding(parameters.getAssertionInfoMap(), parameters.getMessage())) { + return; + } + + Message msg = parameters.getMessage(); + Element soapBody = parameters.getSoapBody(); + Collection<WSDataRef> dataRefs = parameters.getEncrypted(); + if (coverageType == CoverageType.SIGNED) { + dataRefs = parameters.getSigned(); + } + + for (AssertionInfo ai : ais) { + SignedParts p = (SignedParts)ai.getAssertion(); + ai.setAsserted(true); + + if (p.isBody()) { + try { + if (coverageType == CoverageType.SIGNED) { + CryptoCoverageUtil.checkBodyCoverage( + soapBody, dataRefs, CoverageType.SIGNED, CoverageScope.ELEMENT + ); + } else { + CryptoCoverageUtil.checkBodyCoverage( + soapBody, dataRefs, CoverageType.ENCRYPTED, CoverageScope.CONTENT + ); + } + } catch (WSSecurityException e) { + ai.setNotAsserted("Soap Body is not " + coverageType); + continue; + } + } + + for (Header h : p.getHeaders()) { + try { + CryptoCoverageUtil.checkHeaderCoverage(parameters.getSoapHeader(), dataRefs, + h.getNamespace(), h.getName(), coverageType, + CoverageScope.ELEMENT); + } catch (WSSecurityException e) { + ai.setNotAsserted(h.getNamespace() + ":" + h.getName() + " not + " + coverageType); + } + } + + Attachments attachments = p.getAttachments(); + if (attachments != null) { + try { + CoverageScope scope = CoverageScope.ELEMENT; + if (attachments.isContentSignatureTransform()) { + scope = CoverageScope.CONTENT; + } + CryptoCoverageUtil.checkAttachmentsCoverage(msg.getAttachments(), dataRefs, + coverageType, scope); + } catch (WSSecurityException e) { + ai.setNotAsserted("An attachment was not signed/encrypted"); + } + } + + } + } + + private boolean isTransportBinding(AssertionInfoMap aim, Message message) { + AssertionInfo symAis = PolicyUtils.getFirstAssertionByLocalname(aim, SPConstants.SYMMETRIC_BINDING); + if (symAis != null) { + return false; + } + + AssertionInfo asymAis = PolicyUtils.getFirstAssertionByLocalname(aim, SPConstants.ASYMMETRIC_BINDING); + if (asymAis != null) { + return false; + } + + AssertionInfo transAis = PolicyUtils.getFirstAssertionByLocalname(aim, SPConstants.TRANSPORT_BINDING); + if (transAis != null) { + return true; + } + + // No bindings, check if we are using TLS + TLSSessionInfo tlsInfo = message.get(TLSSessionInfo.class); + if (tlsInfo != null) { + // We don't need to check these policies for TLS + PolicyUtils.assertPolicy(aim, SP12Constants.ENCRYPTED_PARTS); + PolicyUtils.assertPolicy(aim, SP11Constants.ENCRYPTED_PARTS); + PolicyUtils.assertPolicy(aim, SP12Constants.SIGNED_PARTS); + PolicyUtils.assertPolicy(aim, SP11Constants.SIGNED_PARTS); + return true; + } + + return false; + } + + public CoverageType getCoverageType() { + return coverageType; + } + + public void setCoverageType(CoverageType coverageType) { + this.coverageType = coverageType; + } +}
