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 2015/07/31 15:15:33 UTC

cxf-fediz git commit: Adding some wrapping tests

Repository: cxf-fediz
Updated Branches:
  refs/heads/master 2eab7d841 -> 3e2f6642b


Adding some wrapping tests


Project: http://git-wip-us.apache.org/repos/asf/cxf-fediz/repo
Commit: http://git-wip-us.apache.org/repos/asf/cxf-fediz/commit/3e2f6642
Tree: http://git-wip-us.apache.org/repos/asf/cxf-fediz/tree/3e2f6642
Diff: http://git-wip-us.apache.org/repos/asf/cxf-fediz/diff/3e2f6642

Branch: refs/heads/master
Commit: 3e2f6642b7bb0f23ecf191c2b1df27d6879b8c7e
Parents: 2eab7d8
Author: Colm O hEigeartaigh <co...@apache.org>
Authored: Fri Jul 31 14:15:22 2015 +0100
Committer: Colm O hEigeartaigh <co...@apache.org>
Committed: Fri Jul 31 14:15:22 2015 +0100

----------------------------------------------------------------------
 .../core/federation/FederationResponseTest.java | 308 ++++++++++++++-----
 1 file changed, 238 insertions(+), 70 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/3e2f6642/plugins/core/src/test/java/org/apache/cxf/fediz/core/federation/FederationResponseTest.java
----------------------------------------------------------------------
diff --git a/plugins/core/src/test/java/org/apache/cxf/fediz/core/federation/FederationResponseTest.java b/plugins/core/src/test/java/org/apache/cxf/fediz/core/federation/FederationResponseTest.java
index 02b8370..125a2ec 100644
--- a/plugins/core/src/test/java/org/apache/cxf/fediz/core/federation/FederationResponseTest.java
+++ b/plugins/core/src/test/java/org/apache/cxf/fediz/core/federation/FederationResponseTest.java
@@ -32,7 +32,6 @@ import javax.security.auth.callback.UnsupportedCallbackException;
 
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
-import org.w3c.dom.Node;
 import org.apache.cxf.fediz.common.STSUtil;
 import org.apache.cxf.fediz.common.SecurityTestUtil;
 import org.apache.cxf.fediz.core.AbstractSAMLCallbackHandler;
@@ -76,6 +75,7 @@ import org.apache.wss4j.common.saml.bean.ConditionsBean;
 import org.apache.wss4j.common.saml.builder.SAML1Constants;
 import org.apache.wss4j.common.saml.builder.SAML2Constants;
 import org.apache.wss4j.common.util.DOM2Writer;
+import org.apache.wss4j.common.util.XMLUtils;
 import org.apache.wss4j.dom.WSConstants;
 import org.apache.wss4j.dom.message.WSSecEncrypt;
 import org.joda.time.DateTime;
@@ -90,6 +90,20 @@ import static org.junit.Assert.fail;
  * Some tests for the WS-Federation "FederationProcessor".
  */
 public class FederationResponseTest {
+    public static final String SAMPLE_MULTIPLE_RSTR_COLL_MSG = 
+        "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+        + "<RequestSecurityTokenResponseCollection "
+        +   "xmlns=\"http://docs.oasis-open.org/ws-sx/ws-trust/200512\"> "
+        +   "<RequestSecurityTokenResponse>"
+        +     "<RequestedSecurityToken>"
+        +     "</RequestedSecurityToken>"
+        +   "</RequestSecurityTokenResponse>"
+        +   "<RequestSecurityTokenResponse>"
+        +     "<RequestedSecurityToken>"
+        +     "</RequestedSecurityToken>"
+        +   "</RequestSecurityTokenResponse>"
+        + "</RequestSecurityTokenResponseCollection>";
+    
     static final String TEST_USER = "alice";
     static final String TEST_RSTR_ISSUER = "FedizSTSIssuer";
     static final String TEST_AUDIENCE = "https://localhost/fedizhelloworld";
@@ -760,6 +774,221 @@ public class FederationResponseTest {
         }
     }
     
+    @org.junit.Test
+    public void testUnsignedAssertionAfterSignedAssertion() throws Exception {
+        // First assertion
+        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
+        callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR);
+        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
+        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
+        callbackHandler.setSubjectName(TEST_USER);
+        ConditionsBean cp = new ConditionsBean();
+        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
+        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
+        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
+        callbackHandler.setConditions(cp);
+        
+        SAMLCallback samlCallback = new SAMLCallback();
+        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
+        SamlAssertionWrapper assertion1 = new SamlAssertionWrapper(samlCallback);
+        
+        // Second assertion
+        SAML2CallbackHandler callbackHandler2 = new SAML2CallbackHandler();
+        callbackHandler2.setStatement(SAML2CallbackHandler.Statement.ATTR);
+        callbackHandler2.setConfirmationMethod(SAML2Constants.CONF_BEARER);
+        callbackHandler2.setIssuer(TEST_RSTR_ISSUER);
+        callbackHandler2.setSubjectName("bob");
+        ConditionsBean cp2 = new ConditionsBean();
+        AudienceRestrictionBean audienceRestriction2 = new AudienceRestrictionBean();
+        audienceRestriction2.getAudienceURIs().add(TEST_AUDIENCE);
+        cp2.setAudienceRestrictions(Collections.singletonList(audienceRestriction2));
+        callbackHandler2.setConditions(cp2);
+        
+        SAMLCallback samlCallback2 = new SAMLCallback();
+        SAMLUtil.doSAMLCallback(callbackHandler2, samlCallback2);
+        SamlAssertionWrapper assertion2 = new SamlAssertionWrapper(samlCallback2);
+        
+        Element rstrElement = 
+            createResponseWithMultipleAssertions(assertion1, true, assertion2, false, "mystskey");
+        String rstr = DOM2Writer.nodeToString(rstrElement);
+        FedizRequest wfReq = new FedizRequest();
+        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
+        wfReq.setResponseToken(rstr);
+        
+        // Load and update the config to enforce an error
+        configurator = null;
+        FedizContext config = getFederationConfigurator().getFedizContext("ROOT");       
+        
+        FedizProcessor wfProc = new FederationProcessorImpl();
+        FedizResponse fedizResponse = wfProc.processRequest(wfReq, config);
+        Assert.assertEquals(TEST_USER, fedizResponse.getUsername());
+    }
+    
+    @org.junit.Test
+    public void testSignedAssertionAfterUnsignedAssertion() throws Exception {
+        // First assertion
+        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
+        callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR);
+        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
+        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
+        callbackHandler.setSubjectName(TEST_USER);
+        ConditionsBean cp = new ConditionsBean();
+        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
+        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
+        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
+        callbackHandler.setConditions(cp);
+        
+        SAMLCallback samlCallback = new SAMLCallback();
+        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
+        SamlAssertionWrapper assertion1 = new SamlAssertionWrapper(samlCallback);
+        
+        // Second assertion
+        SAML2CallbackHandler callbackHandler2 = new SAML2CallbackHandler();
+        callbackHandler2.setStatement(SAML2CallbackHandler.Statement.ATTR);
+        callbackHandler2.setConfirmationMethod(SAML2Constants.CONF_BEARER);
+        callbackHandler2.setIssuer(TEST_RSTR_ISSUER);
+        callbackHandler2.setSubjectName("bob");
+        ConditionsBean cp2 = new ConditionsBean();
+        AudienceRestrictionBean audienceRestriction2 = new AudienceRestrictionBean();
+        audienceRestriction2.getAudienceURIs().add(TEST_AUDIENCE);
+        cp2.setAudienceRestrictions(Collections.singletonList(audienceRestriction2));
+        callbackHandler2.setConditions(cp2);
+        
+        SAMLCallback samlCallback2 = new SAMLCallback();
+        SAMLUtil.doSAMLCallback(callbackHandler2, samlCallback2);
+        SamlAssertionWrapper assertion2 = new SamlAssertionWrapper(samlCallback2);
+        
+        Element rstrElement = 
+            createResponseWithMultipleAssertions(assertion2, false, assertion1, true, "mystskey");
+        String rstr = DOM2Writer.nodeToString(rstrElement);
+        FedizRequest wfReq = new FedizRequest();
+        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
+        wfReq.setResponseToken(rstr);
+        
+        // Load and update the config to enforce an error
+        configurator = null;
+        FedizContext config = getFederationConfigurator().getFedizContext("ROOT");       
+        
+        FedizProcessor wfProc = new FederationProcessorImpl();
+        try {
+            wfProc.processRequest(wfReq, config);
+            Assert.fail("Processing must fail because of missing signature");
+        } catch (ProcessingException ex) {
+            if (!TYPE.TOKEN_NO_SIGNATURE.equals(ex.getType())) {
+                fail("Expected ProcessingException with TOKEN_NO_SIGNATURE type");
+            }
+        }
+    }
+    
+    @org.junit.Test
+    public void testWrappingAttack() throws Exception {
+        // First assertion
+        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
+        callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR);
+        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
+        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
+        callbackHandler.setSubjectName(TEST_USER);
+        ConditionsBean cp = new ConditionsBean();
+        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
+        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
+        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
+        callbackHandler.setConditions(cp);
+        
+        SAMLCallback samlCallback = new SAMLCallback();
+        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
+        SamlAssertionWrapper assertion1 = new SamlAssertionWrapper(samlCallback);
+        
+        // Second assertion
+        SAML2CallbackHandler callbackHandler2 = new SAML2CallbackHandler();
+        callbackHandler2.setStatement(SAML2CallbackHandler.Statement.ATTR);
+        callbackHandler2.setConfirmationMethod(SAML2Constants.CONF_BEARER);
+        callbackHandler2.setIssuer(TEST_RSTR_ISSUER);
+        callbackHandler2.setSubjectName("bob");
+        ConditionsBean cp2 = new ConditionsBean();
+        AudienceRestrictionBean audienceRestriction2 = new AudienceRestrictionBean();
+        audienceRestriction2.getAudienceURIs().add(TEST_AUDIENCE);
+        cp2.setAudienceRestrictions(Collections.singletonList(audienceRestriction2));
+        callbackHandler2.setConditions(cp2);
+        
+        SAMLCallback samlCallback2 = new SAMLCallback();
+        SAMLUtil.doSAMLCallback(callbackHandler2, samlCallback2);
+        SamlAssertionWrapper assertion2 = new SamlAssertionWrapper(samlCallback2);
+        
+        WSPasswordCallback[] cb = {
+            new WSPasswordCallback("mystskey", WSPasswordCallback.SIGNATURE)
+        };
+        cbPasswordHandler.handle(cb);
+        String password = cb[0].getPassword();
+
+        assertion1.signAssertion("mystskey", password, crypto, false);
+        assertion2.signAssertion("mystskey", password, crypto, false);
+
+        Document doc = STSUtil.toSOAPPart(SAMPLE_MULTIPLE_RSTR_COLL_MSG);
+        Element token1 = assertion2.toDOM(doc);
+        Element token2 = assertion1.toDOM(doc);
+        
+        // Now modify the first Signature to point to the other Element
+        Element sig1 = XMLUtils.findElement(token1, "Signature", WSConstants.SIG_NS);
+        Element sig2 = XMLUtils.findElement(token2, "Signature", WSConstants.SIG_NS);
+        sig1.getParentNode().replaceChild(sig2.cloneNode(true), sig1);
+
+        List<Element> requestedTokenElements = 
+            XMLUtils.findElements(doc, "RequestedSecurityToken", FederationConstants.WS_TRUST_13_NS);
+        Assert.assertEquals(2, requestedTokenElements.size());
+        requestedTokenElements.get(0).appendChild(token1);
+        requestedTokenElements.get(1).appendChild(token2);
+
+        Element rstrElement = doc.getDocumentElement();
+        
+        String rstr = DOM2Writer.nodeToString(rstrElement);
+        FedizRequest wfReq = new FedizRequest();
+        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
+        wfReq.setResponseToken(rstr);
+        
+        // Load and update the config to enforce an error
+        configurator = null;
+        FedizContext config = getFederationConfigurator().getFedizContext("ROOT");       
+        
+        FedizProcessor wfProc = new FederationProcessorImpl();
+        try {
+            wfProc.processRequest(wfReq, config);
+            Assert.fail("Processing must fail because of bad signature");
+        } catch (ProcessingException ex) {
+            // expected
+        }
+    }
+    
+    private Element createResponseWithMultipleAssertions(SamlAssertionWrapper assertion1, 
+                                          boolean signFirstAssertion,
+                                          SamlAssertionWrapper assertion2,
+                                          boolean signSecondAssertion,
+                                          String alias) throws Exception {
+        WSPasswordCallback[] cb = {
+            new WSPasswordCallback(alias, WSPasswordCallback.SIGNATURE)
+        };
+        cbPasswordHandler.handle(cb);
+        String password = cb[0].getPassword();
+
+        if (signFirstAssertion) {
+            assertion1.signAssertion(alias, password, crypto, false);
+        }
+        if (signSecondAssertion) {
+            assertion2.signAssertion(alias, password, crypto, false);
+        }
+        
+        Document doc = STSUtil.toSOAPPart(SAMPLE_MULTIPLE_RSTR_COLL_MSG);
+        Element token1 = assertion1.toDOM(doc);
+        Element token2 = assertion2.toDOM(doc);
+
+        List<Element> requestedTokenElements = 
+            XMLUtils.findElements(doc, "RequestedSecurityToken", FederationConstants.WS_TRUST_13_NS);
+        Assert.assertEquals(2, requestedTokenElements.size());
+        requestedTokenElements.get(0).appendChild(token1);
+        requestedTokenElements.get(1).appendChild(token2);
+        
+        return doc.getDocumentElement();
+    }
+    
     /**
      * Validate SAML 2 token twice which causes an exception
      * due to replay attack
@@ -1147,10 +1376,10 @@ public class FederationResponseTest {
         Document doc = STSUtil.toSOAPPart(STSUtil.SAMPLE_RSTR_COLL_MSG);
         Element token = assertion.toDOM(doc);
 
-        Element e = FederationResponseTest.findElement(doc, "RequestedSecurityToken",
+        Element e = XMLUtils.findElement(doc, "RequestedSecurityToken",
                                                         FederationConstants.WS_TRUST_13_NS);
         if (e == null) {
-            e = FederationResponseTest.findElement(doc, "RequestedSecurityToken",
+            e = XMLUtils.findElement(doc, "RequestedSecurityToken",
                                                     FederationConstants.WS_TRUST_2005_02_NS);
         }
         e.appendChild(token);
@@ -1284,10 +1513,10 @@ public class FederationResponseTest {
         issueDateTime = issueDateTime.plusSeconds(1);
         token.setAttributeNS(null, "IssueInstant", issueDateTime.toString());
 
-        Element e = FederationResponseTest.findElement(doc, "RequestedSecurityToken",
+        Element e = XMLUtils.findElement(doc, "RequestedSecurityToken",
                                                        FederationConstants.WS_TRUST_13_NS);
         if (e == null) {
-            e = FederationResponseTest.findElement(doc, "RequestedSecurityToken",
+            e = XMLUtils.findElement(doc, "RequestedSecurityToken",
                                                    FederationConstants.WS_TRUST_2005_02_NS);
         }
         e.appendChild(token);
@@ -1358,10 +1587,10 @@ public class FederationResponseTest {
         Document doc = STSUtil.toSOAPPart(STSUtil.SAMPLE_RSTR_COLL_MSG);
         Element token = assertion.toDOM(doc);
 
-        Element e = FederationResponseTest.findElement(doc, "RequestedSecurityToken",
+        Element e = XMLUtils.findElement(doc, "RequestedSecurityToken",
                                                         FederationConstants.WS_TRUST_13_NS);
         if (e == null) {
-            e = FederationResponseTest.findElement(doc, "RequestedSecurityToken",
+            e = XMLUtils.findElement(doc, "RequestedSecurityToken",
                                                     FederationConstants.WS_TRUST_2005_02_NS);
         }
         e.appendChild(token);
@@ -1404,77 +1633,16 @@ public class FederationResponseTest {
         Document doc = STSUtil.toSOAPPart(rstr);
         Element token = assertion.toDOM(doc);
 
-        Element e = FederationResponseTest.findElement(doc, "RequestedSecurityToken",
+        Element e = XMLUtils.findElement(doc, "RequestedSecurityToken",
                                                         FederationConstants.WS_TRUST_13_NS);
         if (e == null) {
-            e = FederationResponseTest.findElement(doc, "RequestedSecurityToken",
+            e = XMLUtils.findElement(doc, "RequestedSecurityToken",
                                                     FederationConstants.WS_TRUST_2005_02_NS);
         }
         e.appendChild(token);
         return DOM2Writer.nodeToString(doc);
     }
     
-
-    
-    
-    /**
-     * Returns the first element that matches <code>name</code> and
-     * <code>namespace</code>. <p/> This is a replacement for a XPath lookup
-     * <code>//name</code> with the given namespace. It's somewhat faster than
-     * XPath, and we do not deal with prefixes, just with the real namespace URI
-     * 
-     * @param startNode Where to start the search
-     * @param name Local name of the element
-     * @param namespace Namespace URI of the element
-     * @return The found element or <code>null</code>
-     */
-    public static Element findElement(Node startNode, String name, String namespace) {
-        //
-        // Replace the formerly recursive implementation with a depth-first-loop
-        // lookup
-        //
-        if (startNode == null) {
-            return null;
-        }
-        Node startParent = startNode.getParentNode();
-        Node processedNode = null;
-
-        while (startNode != null) {
-            // start node processing at this point
-            if (startNode.getNodeType() == Node.ELEMENT_NODE
-                && startNode.getLocalName().equals(name)) {
-                String ns = startNode.getNamespaceURI();
-                if (ns != null && ns.equals(namespace)) {
-                    return (Element)startNode;
-                }
-
-                if ((namespace == null || namespace.length() == 0)
-                    && (ns == null || ns.length() == 0)) {
-                    return (Element)startNode;
-                }
-            }
-            processedNode = startNode;
-            startNode = startNode.getFirstChild();
-
-            // no child, this node is done.
-            if (startNode == null) {
-                // close node processing, get sibling
-                startNode = processedNode.getNextSibling();
-            }
-            // no more siblings, get parent, all children
-            // of parent are processed.
-            while (startNode == null) {
-                processedNode = processedNode.getParentNode();
-                if (processedNode == startParent) {
-                    return null;
-                }
-                // close parent node processing (processed node now)
-                startNode = processedNode.getNextSibling();
-            }
-        }
-        return null;
-    }
-
     private void assertClaims(List<Claim> claims, String roleClaimType) {
         for (Claim c : claims) {
             Assert.assertTrue("Invalid ClaimType URI: " + c.getClaimType(),