You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by co...@apache.org on 2011/11/08 15:04:56 UTC

svn commit: r1199249 - in /cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j: PolicyBasedWSS4JInInterceptor.java policyvalidators/AsymmetricBindingPolicyValidator.java policyvalidators/EndorsingTokenPolicyValidator.java

Author: coheigea
Date: Tue Nov  8 14:04:55 2011
New Revision: 1199249

URL: http://svn.apache.org/viewvc?rev=1199249&view=rev
Log:
Improved EndorsingSupportingToken policy validation for X.509 tokens and KerberosTokens.

Modified:
    cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/PolicyBasedWSS4JInInterceptor.java
    cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/policyvalidators/AsymmetricBindingPolicyValidator.java
    cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/policyvalidators/EndorsingTokenPolicyValidator.java

Modified: cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/PolicyBasedWSS4JInInterceptor.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/PolicyBasedWSS4JInInterceptor.java?rev=1199249&r1=1199248&r2=1199249&view=diff
==============================================================================
--- cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/PolicyBasedWSS4JInInterceptor.java (original)
+++ cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/PolicyBasedWSS4JInInterceptor.java Tue Nov  8 14:04:55 2011
@@ -574,6 +574,10 @@ public class PolicyBasedWSS4JInIntercept
         suppValidator.setValidateUsernameToken(utWithCallbacks);
         suppValidator.validatePolicy(aim);
         
+        EndorsingTokenPolicyValidator endorsingValidator = 
+            new EndorsingTokenPolicyValidator(results, signedResults, msg);
+        endorsingValidator.validatePolicy(aim);
+        
         //REVISIT - probably can verify some of these like if UT is encrypted and/or signed, etc...
         assertPolicy(aim, SP12Constants.SIGNED_ENCRYPTED_SUPPORTING_TOKENS);
         assertPolicy(aim, SP12Constants.SUPPORTING_TOKENS);
@@ -583,14 +587,6 @@ public class PolicyBasedWSS4JInIntercept
             assertPolicy(aim, SP12Constants.ENDORSING_ENCRYPTED_SUPPORTING_TOKENS);
             assertPolicy(aim, SP12Constants.SIGNED_ENDORSING_ENCRYPTED_SUPPORTING_TOKENS);
         }
-        if (isRequestor(msg)) {
-            assertPolicy(aim, SP12Constants.ENDORSING_SUPPORTING_TOKENS);
-        } else {
-            // TODO need to revisit all of the other endorsed policies
-            EndorsingTokenPolicyValidator endorsingValidator = 
-                new EndorsingTokenPolicyValidator(signedResults, msg);
-            endorsingValidator.validatePolicy(aim);
-        }
         super.doResults(msg, actor, soapHeader, soapBody, results, utWithCallbacks);
     }
     private void assertHeadersExists(AssertionInfoMap aim, SoapMessage msg, Node header) 

Modified: cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/policyvalidators/AsymmetricBindingPolicyValidator.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/policyvalidators/AsymmetricBindingPolicyValidator.java?rev=1199249&r1=1199248&r2=1199249&view=diff
==============================================================================
--- cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/policyvalidators/AsymmetricBindingPolicyValidator.java (original)
+++ cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/policyvalidators/AsymmetricBindingPolicyValidator.java Tue Nov  8 14:04:55 2011
@@ -108,16 +108,21 @@ public class AsymmetricBindingPolicyVali
         if (binding.getInitiatorToken() != null) {
             Token token = binding.getInitiatorToken().getToken();
             if (token instanceof X509Token) {
+                boolean foundCert = false;
                 for (WSSecurityEngineResult result : signedResults) {
                     X509Certificate cert = 
                         (X509Certificate)result.get(WSSecurityEngineResult.TAG_X509_CERTIFICATE);
-                    if (cert == null) {
-                        String error = "An X.509 certificate was not used for the initiator token";
-                        notAssertPolicy(aim, binding.getInitiatorToken().getName(), error);
-                        ai.setNotAsserted(error);
-                        return false;
+                    if (cert != null) {
+                        foundCert = true;
+                        break;
                     }
                 }
+                if (!foundCert && !signedResults.isEmpty()) {
+                    String error = "An X.509 certificate was not used for the initiator token";
+                    notAssertPolicy(aim, binding.getInitiatorToken().getName(), error);
+                    ai.setNotAsserted(error);
+                    return false;
+                }
             }
             assertPolicy(aim, binding.getInitiatorToken());
             if (!checkDerivedKeys(

Modified: cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/policyvalidators/EndorsingTokenPolicyValidator.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/policyvalidators/EndorsingTokenPolicyValidator.java?rev=1199249&r1=1199248&r2=1199249&view=diff
==============================================================================
--- cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/policyvalidators/EndorsingTokenPolicyValidator.java (original)
+++ cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/policyvalidators/EndorsingTokenPolicyValidator.java Tue Nov  8 14:04:55 2011
@@ -19,35 +19,68 @@
 
 package org.apache.cxf.ws.security.wss4j.policyvalidators;
 
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.List;
 
 import javax.xml.namespace.QName;
 
+import org.w3c.dom.Element;
+
 import org.apache.cxf.helpers.CastUtils;
 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.SP12Constants;
+import org.apache.cxf.ws.security.policy.SPConstants;
+import org.apache.cxf.ws.security.policy.model.KerberosToken;
+import org.apache.cxf.ws.security.policy.model.SupportingToken;
+import org.apache.cxf.ws.security.policy.model.Token;
+import org.apache.cxf.ws.security.policy.model.X509Token;
+import org.apache.ws.security.WSConstants;
 import org.apache.ws.security.WSDataRef;
 import org.apache.ws.security.WSSecurityEngine;
 import org.apache.ws.security.WSSecurityEngineResult;
+import org.apache.ws.security.message.token.BinarySecurity;
+import org.apache.ws.security.message.token.KerberosSecurity;
+import org.apache.ws.security.message.token.PKIPathSecurity;
+import org.apache.ws.security.message.token.Timestamp;
+import org.apache.ws.security.message.token.X509Security;
+import org.apache.ws.security.util.WSSecurityUtil;
 
 /**
  * Validate an EndorsingSupportingToken policy. 
  */
-public class EndorsingTokenPolicyValidator {
+public class EndorsingTokenPolicyValidator extends AbstractTokenPolicyValidator {
     
+    private List<WSSecurityEngineResult> results;
     private List<WSSecurityEngineResult> signedResults;
     private Message message;
-
+    private Element timestamp;
+    private boolean tls;
+    
     public EndorsingTokenPolicyValidator(
+        List<WSSecurityEngineResult> results,
         List<WSSecurityEngineResult> signedResults,
         Message message
     ) {
+        this.results = results;
         this.signedResults = signedResults;
         this.message = message;
+        WSSecurityEngineResult result = WSSecurityUtil.fetchActionResult(results, WSConstants.TS);
+        if (result != null) {
+            Timestamp ts = (Timestamp)result.get(WSSecurityEngineResult.TAG_TIMESTAMP);
+            timestamp = ts.getElement();
+        }
+        
+        // See whether TLS is in use or not
+        TLSSessionInfo tlsInfo = message.get(TLSSessionInfo.class);
+        if (tlsInfo != null) {
+            tls = true;
+        }
     }
     
     public boolean validatePolicy(
@@ -56,16 +89,28 @@ public class EndorsingTokenPolicyValidat
         Collection<AssertionInfo> endorsingAis = aim.get(SP12Constants.ENDORSING_SUPPORTING_TOKENS);
         if (endorsingAis != null && !endorsingAis.isEmpty()) {
             for (AssertionInfo ai : endorsingAis) {
+                SupportingToken binding = (SupportingToken)ai.getAssertion();
+                if (SPConstants.SupportTokenType.SUPPORTING_TOKEN_ENDORSING != binding.getTokenType()) {
+                    continue;
+                }
                 ai.setAsserted(true);
                 
-                TLSSessionInfo tlsInfo = message.get(TLSSessionInfo.class);
-                boolean transport = false;
-                if (tlsInfo != null) {
-                    transport = true;
-                }
-                if (!checkEndorsed(transport)) {
-                    ai.setNotAsserted("Message fails endorsing supporting tokens requirements");
-                    return false;
+                List<Token> tokens = binding.getTokens();
+                for (Token token : tokens) {
+                    if (!isTokenRequired(token, message)) {
+                        continue;
+                    }
+                    if (token instanceof KerberosToken && !processKerberosTokens()) {
+                        ai.setNotAsserted(
+                             "The received token does not match the supporting token requirement"
+                        );
+                        return false;
+                    } else if (token instanceof X509Token && !processX509Tokens()) {
+                        ai.setNotAsserted(
+                            "The received token does not match the supporting token requirement"
+                        );
+                        return false;
+                    }
                 }
             }
         }
@@ -73,24 +118,66 @@ public class EndorsingTokenPolicyValidat
         return true;
     }
     
+    private boolean processKerberosTokens() {
+        List<WSSecurityEngineResult> tokenResults = new ArrayList<WSSecurityEngineResult>();
+        for (WSSecurityEngineResult wser : results) {
+            Integer actInt = (Integer)wser.get(WSSecurityEngineResult.TAG_ACTION);
+            if (actInt.intValue() == WSConstants.BST) {
+                BinarySecurity binarySecurity = 
+                    (BinarySecurity)wser.get(WSSecurityEngineResult.TAG_BINARY_SECURITY_TOKEN);
+                if (binarySecurity instanceof KerberosSecurity) {
+                    tokenResults.add(wser);
+                }
+            }
+        }
+        
+        if (tokenResults.isEmpty()) {
+            return false;
+        }
+        
+        return checkEndorsed(tokenResults, tls);
+    }
+    
+    private boolean processX509Tokens() {
+        List<WSSecurityEngineResult> tokenResults = new ArrayList<WSSecurityEngineResult>();
+        for (WSSecurityEngineResult wser : results) {
+            Integer actInt = (Integer)wser.get(WSSecurityEngineResult.TAG_ACTION);
+            if (actInt.intValue() == WSConstants.BST) {
+                BinarySecurity binarySecurity = 
+                    (BinarySecurity)wser.get(WSSecurityEngineResult.TAG_BINARY_SECURITY_TOKEN);
+                if (binarySecurity instanceof X509Security
+                    || binarySecurity instanceof PKIPathSecurity) {
+                    tokenResults.add(wser);
+                }
+            }
+        }
+        
+        if (tokenResults.isEmpty()) {
+            return false;
+        }
+        
+        return checkEndorsed(tokenResults, tls);
+    }
+    
     /**
      * Check the endorsing supporting token policy. If we're using the Transport Binding then
      * check that the Timestamp is signed. Otherwise, check that the signature is signed.
      * @param transport
      * @return true if the endorsed supporting token policy is correct
      */
-    private boolean checkEndorsed(boolean transport) {
+    private boolean checkEndorsed(List<WSSecurityEngineResult> tokenResults, boolean transport) {
         if (transport) {
-            return checkTimestampIsSigned();
+            return checkTimestampIsSigned(tokenResults);
         }
-        return checkSignatureIsSigned();
+        return checkSignatureIsSigned(tokenResults);
     }
     
     /**
-     * Return true if the Timestamp is signed
+     * Return true if the Timestamp is signed by one of the token results
+     * @param tokenResults A list of WSSecurityEngineResults corresponding to tokens
      * @return true if the Timestamp is signed
      */
-    private boolean checkTimestampIsSigned() {
+    private boolean checkTimestampIsSigned(List<WSSecurityEngineResult> tokenResults) {
         for (WSSecurityEngineResult signedResult : signedResults) {
             List<WSDataRef> sl =
                 CastUtils.cast((List<?>)signedResult.get(
@@ -98,8 +185,8 @@ public class EndorsingTokenPolicyValidat
                 ));
             if (sl != null) {
                 for (WSDataRef dataRef : sl) {
-                    QName signedQName = dataRef.getName();
-                    if (WSSecurityEngine.TIMESTAMP.equals(signedQName)) {
+                    if (timestamp == dataRef.getProtectedElement()
+                        && checkSignature(signedResult, tokenResults)) {
                         return true;
                     }
                 }
@@ -109,19 +196,21 @@ public class EndorsingTokenPolicyValidat
     }
     
     /**
-     * Return true if the Signature is itself signed
+     * Return true if the Signature is itself signed by one of the token results
+     * @param tokenResults A list of WSSecurityEngineResults corresponding to tokens
      * @return true if the Signature is itself signed
      */
-    private boolean checkSignatureIsSigned() {
+    private boolean checkSignatureIsSigned(List<WSSecurityEngineResult> tokenResults) {
         for (WSSecurityEngineResult signedResult : signedResults) {
             List<WSDataRef> sl =
                 CastUtils.cast((List<?>)signedResult.get(
                     WSSecurityEngineResult.TAG_DATA_REF_URIS
                 ));
-            if (sl != null) {
+            if (sl != null && sl.size() == 1) {
                 for (WSDataRef dataRef : sl) {
                     QName signedQName = dataRef.getName();
-                    if (WSSecurityEngine.SIGNATURE.equals(signedQName)) {
+                    if (WSSecurityEngine.SIGNATURE.equals(signedQName)
+                        && checkSignature(signedResult, tokenResults)) {
                         return true;
                     }
                 }
@@ -129,4 +218,45 @@ public class EndorsingTokenPolicyValidat
         }
         return false;
     }
+    
+    /**
+     * Check that a WSSecurityEngineResult corresponding to a signature uses the same 
+     * signing credential as one of the tokens.
+     * @param signatureResult a WSSecurityEngineResult corresponding to a signature
+     * @param tokenResult A list of WSSecurityEngineResults corresponding to tokens
+     * @return 
+     */
+    private boolean checkSignature(
+        WSSecurityEngineResult signatureResult,
+        List<WSSecurityEngineResult> tokenResult
+    ) {
+        // See what was used to sign this result
+        X509Certificate cert = 
+            (X509Certificate)signatureResult.get(WSSecurityEngineResult.TAG_X509_CERTIFICATE);
+        byte[] secret = (byte[])signatureResult.get(WSSecurityEngineResult.TAG_SECRET);
+        
+        // Now see if the same credential exists in the tokenResult list
+        for (WSSecurityEngineResult token : tokenResult) {
+            Integer actInt = (Integer)token.get(WSSecurityEngineResult.TAG_ACTION);
+            if (actInt.intValue() == WSConstants.BST) {
+                BinarySecurity binarySecurity = 
+                    (BinarySecurity)token.get(WSSecurityEngineResult.TAG_BINARY_SECURITY_TOKEN);
+                if (binarySecurity instanceof X509Security
+                    || binarySecurity instanceof PKIPathSecurity) {
+                    X509Certificate foundCert = 
+                        (X509Certificate)token.get(WSSecurityEngineResult.TAG_X509_CERTIFICATE);
+                    if (foundCert.equals(cert)) {
+                        return true;
+                    }
+                } else if (binarySecurity instanceof KerberosSecurity) {
+                    byte[] foundSecret = (byte[])token.get(WSSecurityEngineResult.TAG_SECRET);
+                    if (foundSecret != null && Arrays.equals(foundSecret, secret)) {
+                        return true;
+                    }
+                }
+            }
+        }
+        
+        return false;
+    }
 }