You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ws.apache.org by co...@apache.org on 2015/01/16 12:40:01 UTC

svn commit: r1652392 - in /webservices/wss4j/branches/1_6_x-fixes/src: main/java/org/apache/ws/security/handler/ main/java/org/apache/ws/security/validate/ test/java/org/apache/ws/security/saml/

Author: coheigea
Date: Fri Jan 16 11:40:01 2015
New Revision: 1652392

URL: http://svn.apache.org/r1652392
Log:
[WSS-523] - Add the ability to supply AudienceRestrictions when validating SAML tokens - DOM part


Conflicts:
	src/main/java/org/apache/ws/security/handler/RequestData.java
	src/main/java/org/apache/ws/security/saml/ext/AssertionWrapper.java
	src/main/java/org/apache/ws/security/validate/SamlAssertionValidator.java
	src/test/java/org/apache/ws/security/saml/SamlConditionsTest.java

Modified:
    webservices/wss4j/branches/1_6_x-fixes/src/main/java/org/apache/ws/security/handler/RequestData.java
    webservices/wss4j/branches/1_6_x-fixes/src/main/java/org/apache/ws/security/validate/SamlAssertionValidator.java
    webservices/wss4j/branches/1_6_x-fixes/src/test/java/org/apache/ws/security/saml/SamlConditionsTest.java

Modified: webservices/wss4j/branches/1_6_x-fixes/src/main/java/org/apache/ws/security/handler/RequestData.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/branches/1_6_x-fixes/src/main/java/org/apache/ws/security/handler/RequestData.java?rev=1652392&r1=1652391&r2=1652392&view=diff
==============================================================================
--- webservices/wss4j/branches/1_6_x-fixes/src/main/java/org/apache/ws/security/handler/RequestData.java (original)
+++ webservices/wss4j/branches/1_6_x-fixes/src/main/java/org/apache/ws/security/handler/RequestData.java Fri Jan 16 11:40:01 2015
@@ -91,6 +91,7 @@ public class RequestData {
     private int originalSignatureActionPosition;
     private AlgorithmSuite algorithmSuite;
     private AlgorithmSuite samlAlgorithmSuite;
+    private final List<String> audienceRestrictions = new ArrayList<String>();
 
     public void clear() {
         soapConstants = null;
@@ -122,6 +123,7 @@ public class RequestData {
         algorithmSuite = null;
         samlAlgorithmSuite = null;
         setOriginalSignatureActionPosition(0);
+        audienceRestrictions.clear();
     }
 
     public String getSignatureC14nAlgorithm() {
@@ -547,7 +549,23 @@ public class RequestData {
     public Collection<Pattern> getSubjectCertConstraints() {
         return subjectDNPatterns;
     }
-
+    
+    /**
+     * Set the Audience Restrictions
+     */
+    public void setAudienceRestrictions(List<String> audienceRestrictions) {
+        if (audienceRestrictions != null) {
+            this.audienceRestrictions.addAll(audienceRestrictions);
+        }
+    }
+    
+    /**
+     * Get the Audience Restrictions
+     */
+    public List<String> getAudienceRestrictions() {
+        return audienceRestrictions;
+    }
+    
     public boolean isAppendSignatureAfterTimestamp() {
         return appendSignatureAfterTimestamp;
     }

Modified: webservices/wss4j/branches/1_6_x-fixes/src/main/java/org/apache/ws/security/validate/SamlAssertionValidator.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/branches/1_6_x-fixes/src/main/java/org/apache/ws/security/validate/SamlAssertionValidator.java?rev=1652392&r1=1652391&r2=1652392&view=diff
==============================================================================
--- webservices/wss4j/branches/1_6_x-fixes/src/main/java/org/apache/ws/security/validate/SamlAssertionValidator.java (original)
+++ webservices/wss4j/branches/1_6_x-fixes/src/main/java/org/apache/ws/security/validate/SamlAssertionValidator.java Fri Jan 16 11:40:01 2015
@@ -106,8 +106,11 @@ public class SamlAssertionValidator exte
         
         // Check conditions
         checkConditions(assertion);
-
-        // Check the AuthnStatements of the Assertion (if any)
+        
+        // Check the audience restrictions
+        checkAudienceRestrictions(assertion, data.getAudienceRestrictions());
+        
+        // Check the AuthnStatements of the assertion (if any)
         checkAuthnStatements(assertion);
         
         // Check OneTimeUse Condition
@@ -257,6 +260,70 @@ public class SamlAssertionValidator exte
             }
         }
     }
+    
+    /**
+     * Check the AudienceRestrictions of the Assertion
+     */
+    public void checkAudienceRestrictions(
+        AssertionWrapper assertion, List<String> audienceRestrictions
+    ) throws WSSecurityException {
+        // Now check the audience restriction conditions
+        if (audienceRestrictions == null || audienceRestrictions.isEmpty()) {
+            return;
+        }
+        
+        if (assertion.getSamlVersion().equals(SAMLVersion.VERSION_20) 
+            && assertion.getSaml2().getConditions() != null) {
+            org.opensaml.saml2.core.Conditions conditions = 
+                assertion.getSaml2().getConditions();
+            if (conditions != null && conditions.getAudienceRestrictions() != null) {
+                boolean foundAddress = false;
+                for (org.opensaml.saml2.core.AudienceRestriction audienceRestriction 
+                    : conditions.getAudienceRestrictions()) {
+                    if (audienceRestriction.getAudiences() != null) {
+                        List<org.opensaml.saml2.core.Audience> audiences = 
+                            audienceRestriction.getAudiences();
+                        for (org.opensaml.saml2.core.Audience audience : audiences) {
+                            String audienceURI = audience.getAudienceURI();
+                            if (audienceRestrictions.contains(audienceURI)) {
+                                foundAddress = true;
+                                break;
+                            }
+                        }
+                    }
+                }
+                
+                if (!foundAddress) {
+                    throw new WSSecurityException(WSSecurityException.FAILURE, "invalidSAMLsecurity");
+                }
+            }
+        } else if (assertion.getSamlVersion().equals(SAMLVersion.VERSION_11) 
+            && assertion.getSaml1().getConditions() != null) {
+            org.opensaml.saml1.core.Conditions conditions = 
+                assertion.getSaml1().getConditions();
+            if (conditions != null && conditions.getAudienceRestrictionConditions() != null) {
+                boolean foundAddress = false;
+                for (org.opensaml.saml1.core.AudienceRestrictionCondition audienceRestriction 
+                    : conditions.getAudienceRestrictionConditions()) {
+                    if (audienceRestriction.getAudiences() != null) {
+                        List<org.opensaml.saml1.core.Audience> audiences = 
+                            audienceRestriction.getAudiences();
+                        for (org.opensaml.saml1.core.Audience audience : audiences) {
+                            String audienceURI = audience.getUri();
+                            if (audienceRestrictions.contains(audienceURI)) {
+                                foundAddress = true;
+                                break;
+                            }
+                        }
+                    }
+                }
+                
+                if (!foundAddress) {
+                    throw new WSSecurityException(WSSecurityException.FAILURE, "invalidSAMLsecurity");
+                }
+            }
+        }
+    }
 
     /**
      * Check the AuthnStatements of the Assertion (if any)

Modified: webservices/wss4j/branches/1_6_x-fixes/src/test/java/org/apache/ws/security/saml/SamlConditionsTest.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/branches/1_6_x-fixes/src/test/java/org/apache/ws/security/saml/SamlConditionsTest.java?rev=1652392&r1=1652391&r2=1652392&view=diff
==============================================================================
--- webservices/wss4j/branches/1_6_x-fixes/src/test/java/org/apache/ws/security/saml/SamlConditionsTest.java (original)
+++ webservices/wss4j/branches/1_6_x-fixes/src/test/java/org/apache/ws/security/saml/SamlConditionsTest.java Fri Jan 16 11:40:01 2015
@@ -32,6 +32,7 @@ import org.apache.ws.security.common.Cus
 import org.apache.ws.security.common.SAML1CallbackHandler;
 import org.apache.ws.security.common.SAML2CallbackHandler;
 import org.apache.ws.security.common.SOAPUtil;
+import org.apache.ws.security.handler.RequestData;
 import org.apache.ws.security.message.WSSecHeader;
 import org.apache.ws.security.message.WSSecSAMLToken;
 import org.apache.ws.security.saml.ext.AssertionWrapper;
@@ -42,6 +43,7 @@ import org.apache.ws.security.saml.ext.b
 import org.apache.ws.security.util.WSSecurityUtil;
 import org.joda.time.DateTime;
 import org.w3c.dom.Document;
+import org.w3c.dom.Element;
 
 /**
  * Test-case for sending and processing an a SAML Token with a custom Conditions element.
@@ -507,6 +509,133 @@ public class SamlConditionsTest extends
         verify(unsignedDoc);
     }
     
+    // Now test AudienceRestrictions with supplied restrictions
+    @org.junit.Test
+    public void testSAML2AudienceRestrictionVerification() throws Exception {
+        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
+        callbackHandler.setStatement(SAML2CallbackHandler.Statement.AUTHN);
+        callbackHandler.setIssuer("www.example.com");
+        
+        ConditionsBean conditions = new ConditionsBean();
+        conditions.setTokenPeriodMinutes(5);
+        List<String> audiences = new ArrayList<String>();
+        audiences.add("http://apache.org/one");
+        audiences.add("http://apache.org/two");
+        AudienceRestrictionBean audienceRestrictionBean = new AudienceRestrictionBean();
+        audienceRestrictionBean.setAudienceURIs(audiences);
+        conditions.setAudienceRestrictions(Collections.singletonList(audienceRestrictionBean));
+        
+        callbackHandler.setConditions(conditions);
+        
+        SAMLParms samlParms = new SAMLParms();
+        samlParms.setCallbackHandler(callbackHandler);
+        AssertionWrapper assertion = new AssertionWrapper(samlParms);
+
+        WSSecSAMLToken wsSign = new WSSecSAMLToken();
+
+        Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);
+        
+        Document unsignedDoc = wsSign.build(doc, assertion, secHeader);
+
+        String outputString = 
+            org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(unsignedDoc);
+        assertTrue(outputString.contains("AudienceRestriction"));
+        if (LOG.isDebugEnabled()) {
+            LOG.debug(outputString);
+        }
+        
+        // This should fail as the expected audience isn't in the assertion
+        audiences.clear();
+        audiences.add("http://apache.org/three");
+     
+        WSSecurityEngine newEngine = new WSSecurityEngine();
+        RequestData data = new RequestData();
+        data.setAudienceRestrictions(audiences);
+        
+        Element securityHeader = 
+            WSSecurityUtil.findWsseSecurityHeaderBlock(unsignedDoc, 
+                                                       unsignedDoc.getDocumentElement(), 
+                                                       false);
+        try {
+            newEngine.processSecurityHeader(securityHeader, data);
+            fail("Failure expected on a bad audience restriction");
+        } catch (WSSecurityException ex) {
+            // expected
+        }
+        
+        // Now add the correct audience back in...
+        audiences.add("http://apache.org/one");
+        data.setAudienceRestrictions(audiences);
+        
+        newEngine.processSecurityHeader(securityHeader, data);
+    }
+    
+    // Now test AudienceRestrictions with supplied restrictions
+    @org.junit.Test
+    public void testSAML1AudienceRestrictionVerification() throws Exception {
+        SAML1CallbackHandler callbackHandler = new SAML1CallbackHandler();
+        callbackHandler.setStatement(SAML1CallbackHandler.Statement.AUTHN);
+        callbackHandler.setIssuer("www.example.com");
+        
+        ConditionsBean conditions = new ConditionsBean();
+        conditions.setTokenPeriodMinutes(5);
+        List<String> audiences = new ArrayList<String>();
+        audiences.add("http://apache.org/one");
+        audiences.add("http://apache.org/two");
+        AudienceRestrictionBean audienceRestrictionBean = new AudienceRestrictionBean();
+        audienceRestrictionBean.setAudienceURIs(audiences);
+        conditions.setAudienceRestrictions(Collections.singletonList(audienceRestrictionBean));
+        
+        callbackHandler.setConditions(conditions);
+        
+        SAMLParms samlParms = new SAMLParms();
+        samlParms.setCallbackHandler(callbackHandler);
+        AssertionWrapper assertion = new AssertionWrapper(samlParms);
+
+        WSSecSAMLToken wsSign = new WSSecSAMLToken();
+
+        Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);
+        
+        Document unsignedDoc = wsSign.build(doc, assertion, secHeader);
+
+        String outputString = 
+            org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(unsignedDoc);
+        assertTrue(outputString.contains("AudienceRestriction"));
+        if (LOG.isDebugEnabled()) {
+            LOG.debug(outputString);
+        }
+        
+        // This should fail as the expected audience isn't in the assertion
+        audiences.clear();
+        audiences.add("http://apache.org/three");
+     
+        WSSecurityEngine newEngine = new WSSecurityEngine();
+        RequestData data = new RequestData();
+        data.setAudienceRestrictions(audiences);
+        
+        Element securityHeader = 
+            WSSecurityUtil.findWsseSecurityHeaderBlock(unsignedDoc, 
+                                                       unsignedDoc.getDocumentElement(), 
+                                                       false);
+        
+        try {
+            newEngine.processSecurityHeader(securityHeader, data);
+            fail("Failure expected on a bad audience restriction");
+        } catch (WSSecurityException ex) {
+            // expected
+        }
+        
+        // Now add the correct audience back in...
+        audiences.add("http://apache.org/one");
+        data.setAudienceRestrictions(audiences);
+        
+        newEngine.processSecurityHeader(securityHeader, data);
+    }
+    
     /**
      * Test that creates, sends and processes an unsigned SAML 2 authentication assertion
      * with two AudienceRestriction Elements
@@ -556,6 +685,76 @@ public class SamlConditionsTest extends
         verify(unsignedDoc);
     }
     
+    // Now test AudienceRestrictions with supplied restrictions
+    @org.junit.Test
+    public void testSAML2AudienceRestrictionSeparateRestrictionsValidation() throws Exception {
+        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
+        callbackHandler.setStatement(SAML2CallbackHandler.Statement.AUTHN);
+        callbackHandler.setIssuer("www.example.com");
+        
+        ConditionsBean conditions = new ConditionsBean();
+        conditions.setTokenPeriodMinutes(5);
+        
+        List<AudienceRestrictionBean> audiencesRestrictions = 
+            new ArrayList<AudienceRestrictionBean>();
+        AudienceRestrictionBean audienceRestrictionBean = new AudienceRestrictionBean();
+        audienceRestrictionBean.setAudienceURIs(Collections.singletonList("http://apache.org/one"));
+        audiencesRestrictions.add(audienceRestrictionBean);
+        
+        audienceRestrictionBean = new AudienceRestrictionBean();
+        audienceRestrictionBean.setAudienceURIs(Collections.singletonList("http://apache.org/two"));
+        audiencesRestrictions.add(audienceRestrictionBean);
+        
+        conditions.setAudienceRestrictions(audiencesRestrictions);
+        
+        callbackHandler.setConditions(conditions);
+        
+        SAMLParms samlParms = new SAMLParms();
+        samlParms.setCallbackHandler(callbackHandler);
+        AssertionWrapper assertion = new AssertionWrapper(samlParms);
+
+        WSSecSAMLToken wsSign = new WSSecSAMLToken();
+
+        Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);
+        
+        Document unsignedDoc = wsSign.build(doc, assertion, secHeader);
+
+        String outputString = 
+            org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(unsignedDoc);
+        assertTrue(outputString.contains("AudienceRestriction"));
+        if (LOG.isDebugEnabled()) {
+            LOG.debug(outputString);
+        }
+        
+        // This should fail as the expected audience isn't in the assertion
+        List<String> audiences = new ArrayList<String>();
+        audiences.add("http://apache.org/three");
+     
+        WSSecurityEngine newEngine = new WSSecurityEngine();
+        RequestData data = new RequestData();
+        data.setAudienceRestrictions(audiences);
+
+        Element securityHeader = 
+            WSSecurityUtil.findWsseSecurityHeaderBlock(unsignedDoc, 
+                                                       unsignedDoc.getDocumentElement(), 
+                                                       false);
+        
+        try {
+            newEngine.processSecurityHeader(securityHeader, data);
+            fail("Failure expected on a bad audience restriction");
+        } catch (WSSecurityException ex) {
+            // expected
+        }
+        
+        // Now add the correct audience back in...
+        audiences.add("http://apache.org/one");
+        data.setAudienceRestrictions(audiences);
+        
+        newEngine.processSecurityHeader(securityHeader, data);
+    }
+    
     /**
      * Verifies the soap envelope
      * <p/>