ws-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cohei...@apache.org
Subject svn commit: r1443495 - in /webservices/wss4j/trunk: ws-security-common/src/main/java/org/apache/ws/security/common/saml/ ws-security-dom/src/main/java/org/apache/ws/security/dom/validate/ ws-security-dom/src/test/java/org/apache/ws/security/dom/saml/
Date Thu, 07 Feb 2013 14:15:49 GMT
Author: coheigea
Date: Thu Feb  7 14:15:49 2013
New Revision: 1443495

URL: http://svn.apache.org/viewvc?rev=1443495&view=rev
Log:
[WSS-422] - Move SAML Signature Profile Validation to the SamlAssertionValidator


Conflicts:
	ws-security-common/src/main/java/org/apache/ws/security/common/saml/SamlAssertionWrapper.java
	ws-security-dom/src/main/java/org/apache/ws/security/dom/validate/SamlAssertionValidator.java

Added:
    webservices/wss4j/trunk/ws-security-dom/src/test/java/org/apache/ws/security/dom/saml/SamlTokenCustomSignatureTest.java
Modified:
    webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/ws/security/common/saml/SamlAssertionWrapper.java
    webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/ws/security/dom/validate/SamlAssertionValidator.java

Modified: webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/ws/security/common/saml/SamlAssertionWrapper.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/ws/security/common/saml/SamlAssertionWrapper.java?rev=1443495&r1=1443494&r2=1443495&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/ws/security/common/saml/SamlAssertionWrapper.java
(original)
+++ webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/ws/security/common/saml/SamlAssertionWrapper.java
Thu Feb  7 14:15:49 2013
@@ -499,12 +499,7 @@ public class SamlAssertionWrapper {
     public void verifySignature(
         SAMLKeyInfoProcessor keyInfoProcessor, Crypto sigCrypto
     ) throws WSSecurityException {
-        Signature sig = null;
-        if (saml2 != null && saml2.getSignature() != null) {
-            sig = saml2.getSignature();
-        } else if (saml1 != null && saml1.getSignature() != null) {
-            sig = saml1.getSignature();
-        }
+        Signature sig = getSignature();
         if (sig != null) {
             KeyInfo keyInfo = sig.getKeyInfo();
             SAMLKeyInfo samlKeyInfo = 
@@ -530,14 +525,7 @@ public class SamlAssertionWrapper {
                     "cannot get certificate or key"
                 );
             }
-            SAMLSignatureProfileValidator validator = new SAMLSignatureProfileValidator();
-            try {
-                validator.validate(sig);
-            } catch (ValidationException ex) {
-                throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE,
-                        "empty", ex, "SAML signature validation failed");
-            }
-            
+
             BasicX509Credential credential = new BasicX509Credential();
             if (samlKeyInfo.getCerts() != null) {
                 credential.setEntityCertificate(samlKeyInfo.getCerts()[0]);
@@ -563,6 +551,24 @@ public class SamlAssertionWrapper {
     }
     
     /**
+     * Validate the signature of the Assertion against the Profile. This does not actually
+     * verify the signature itself (see the verifySignature method for this)
+     * @throws WSSecurityException
+     */
+    public void validateSignatureAgainstProfile() throws WSSecurityException {
+        Signature sig = getSignature();
+        if (sig != null) {
+            SAMLSignatureProfileValidator validator = new SAMLSignatureProfileValidator();
+            try {
+                validator.validate(sig);
+            } catch (ValidationException ex) {
+                throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, 
+                    "empty", ex, "SAML signature validation failed");
+            }
+        }
+    }
+    
+    /**
      * This method parses the KeyInfo of the Subject for the holder-of-key confirmation
      * method, as required by the SAML Token spec. It then stores the SAMLKeyInfo object
that
      * has been obtained for future processing.

Modified: webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/ws/security/dom/validate/SamlAssertionValidator.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/ws/security/dom/validate/SamlAssertionValidator.java?rev=1443495&r1=1443494&r2=1443495&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/ws/security/dom/validate/SamlAssertionValidator.java
(original)
+++ webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/ws/security/dom/validate/SamlAssertionValidator.java
Thu Feb  7 14:15:49 2013
@@ -50,6 +50,12 @@ public class SamlAssertionValidator exte
     private int futureTTL = 60;
     
     /**
+     * Whether to validate the signature of the Assertion (if it exists) against the 
+     * relevant profile. Default is true.
+     */
+    private boolean validateSignatureAgainstProfile = true;
+    
+    /**
      * Set the time in seconds in the future within which the NotBefore time of an incoming

      * Assertion is valid. The default is 60 seconds.
      */
@@ -156,6 +162,10 @@ public class SamlAssertionValidator exte
      * Validate the samlAssertion against schemas/profiles
      */
     protected void validateAssertion(SamlAssertionWrapper samlAssertion) throws WSSecurityException
{
+        if (validateSignatureAgainstProfile) {
+            samlAssertion.validateSignatureAgainstProfile();
+        }
+        
         if (samlAssertion.getSaml1() != null) {
             ValidatorSuite schemaValidators = 
                 org.opensaml.Configuration.getValidatorSuite("saml1-schema-validator");
@@ -186,5 +196,21 @@ public class SamlAssertionValidator exte
             }
         }
     }
+
+    /**
+     * Whether to validate the signature of the Assertion (if it exists) against the 
+     * relevant profile. Default is true.
+     */
+    public boolean isValidateSignatureAgainstProfile() {
+        return validateSignatureAgainstProfile;
+    }
+
+    /**
+     * Whether to validate the signature of the Assertion (if it exists) against the 
+     * relevant profile. Default is true.
+     */
+    public void setValidateSignatureAgainstProfile(boolean validateSignatureAgainstProfile)
{
+        this.validateSignatureAgainstProfile = validateSignatureAgainstProfile;
+    }
     
 }

Added: webservices/wss4j/trunk/ws-security-dom/src/test/java/org/apache/ws/security/dom/saml/SamlTokenCustomSignatureTest.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-dom/src/test/java/org/apache/ws/security/dom/saml/SamlTokenCustomSignatureTest.java?rev=1443495&view=auto
==============================================================================
--- webservices/wss4j/trunk/ws-security-dom/src/test/java/org/apache/ws/security/dom/saml/SamlTokenCustomSignatureTest.java
(added)
+++ webservices/wss4j/trunk/ws-security-dom/src/test/java/org/apache/ws/security/dom/saml/SamlTokenCustomSignatureTest.java
Thu Feb  7 14:15:49 2013
@@ -0,0 +1,207 @@
+/**
+ * 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.ws.security.dom.saml;
+
+import java.security.PrivateKey;
+import java.security.cert.X509Certificate;
+import java.util.List;
+
+import org.apache.ws.security.common.crypto.Crypto;
+import org.apache.ws.security.common.crypto.CryptoFactory;
+import org.apache.ws.security.common.crypto.CryptoType;
+import org.apache.ws.security.common.ext.WSSecurityException;
+import org.apache.ws.security.common.saml.SAMLCallback;
+import org.apache.ws.security.common.saml.SAMLUtil;
+import org.apache.ws.security.common.saml.SamlAssertionWrapper;
+import org.apache.ws.security.common.saml.builder.SAML1Constants;
+import org.apache.ws.security.common.saml.builder.SAML2Constants;
+import org.apache.ws.security.common.util.XMLUtils;
+import org.apache.ws.security.dom.WSSConfig;
+import org.apache.ws.security.dom.WSSecurityEngine;
+import org.apache.ws.security.dom.WSSecurityEngineResult;
+import org.apache.ws.security.dom.common.SAML1CallbackHandler;
+import org.apache.ws.security.dom.common.SAML2CallbackHandler;
+import org.apache.ws.security.dom.common.SOAPUtil;
+import org.apache.ws.security.dom.message.WSSecHeader;
+import org.apache.ws.security.dom.validate.SamlAssertionValidator;
+import org.apache.xml.security.signature.XMLSignature;
+import org.apache.xml.security.transforms.Transforms;
+import org.apache.xml.security.transforms.params.XPath2FilterContainer;
+import org.apache.xml.security.utils.Constants;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+/**
+ */
+public class SamlTokenCustomSignatureTest extends org.junit.Assert {
+    private static final org.apache.commons.logging.Log LOG = 
+        org.apache.commons.logging.LogFactory.getLog(SamlTokenCustomSignatureTest.class);
+    
+    private Crypto crypto = null;
+    
+    public SamlTokenCustomSignatureTest() throws Exception {
+        WSSConfig.init();
+        crypto = CryptoFactory.getInstance("crypto.properties");
+    }
+
+    /**
+     * Test that creates, sends and processes a signed SAML 1.1 authentication assertion.
+     */
+    @org.junit.Test
+    public void testSAML1AuthnAssertion() throws Exception {
+        SAML1CallbackHandler callbackHandler = new SAML1CallbackHandler();
+        callbackHandler.setStatement(SAML1CallbackHandler.Statement.AUTHN);
+        callbackHandler.setConfirmationMethod(SAML1Constants.CONF_BEARER);
+        callbackHandler.setIssuer("www.example.com");
+        
+        SAMLCallback samlCallback = new SAMLCallback();
+        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
+        SamlAssertionWrapper samlAssertion = new SamlAssertionWrapper(samlCallback);
+
+        Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
+        Element assertionElement = samlAssertion.toDOM(doc);
+        
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);
+        secHeader.getSecurityHeader().appendChild(assertionElement);
+        
+        // Sign
+        signAssertion(doc, assertionElement);
+        
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("SAML 1.1 Authn Assertion (Bearer):");
+            String outputString = XMLUtils.PrettyDocumentToString(doc);
+            LOG.debug(outputString);
+        }
+        
+        try {
+            verify(doc);
+            fail("Failure expected on a signature that doesn't conform with the signature
profile");
+        } catch (WSSecurityException ex) {
+            // expected failure
+        }
+        
+        // This should pass as we are disabling signature profile validation in the Validator
+        verifyWithoutProfile(doc);
+    }
+    
+    /**
+     * Test that creates, sends and processes a signed SAML 2.0 authentication assertion.
+     */
+    @org.junit.Test
+    public void testSAML2AuthnAssertion() throws Exception {
+        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
+        callbackHandler.setStatement(SAML2CallbackHandler.Statement.AUTHN);
+        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
+        callbackHandler.setIssuer("www.example.com");
+        
+        SAMLCallback samlCallback = new SAMLCallback();
+        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
+        SamlAssertionWrapper samlAssertion = new SamlAssertionWrapper(samlCallback);
+
+        Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
+        Element assertionElement = samlAssertion.toDOM(doc);
+        
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);
+        secHeader.getSecurityHeader().appendChild(assertionElement);
+        
+        // Sign
+        signAssertion(doc, assertionElement);
+        
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("SAML 2.0 Authn Assertion (Bearer):");
+            String outputString = XMLUtils.PrettyDocumentToString(doc);
+            LOG.debug(outputString);
+        }
+        
+        try {
+            verify(doc);
+            fail("Failure expected on a signature that doesn't conform with the signature
profile");
+        } catch (WSSecurityException ex) {
+            // expected failure
+        }
+        
+        // This should pass as we are disabling signature profile validation in the Validator
+        verifyWithoutProfile(doc);
+    }
+    
+    private void signAssertion(Document doc, Element assertionElement) throws Exception {
+        XMLSignature sig = 
+            new XMLSignature(doc, null, XMLSignature.ALGO_ID_SIGNATURE_RSA);
+        assertionElement.appendChild(sig.getElement());
+
+        Transforms transforms = new Transforms(doc);
+        String filter = "here()/ancestor::ds.Signature/parent::node()/descendant-or-self::*";
+        XPath2FilterContainer xpathC = XPath2FilterContainer.newInstanceIntersect(doc, filter);
+        xpathC.setXPathNamespaceContext("dsig-xpath", Transforms.TRANSFORM_XPATH2FILTER);
+        
+        Element node = xpathC.getElement();
+        transforms.addTransform(Transforms.TRANSFORM_XPATH2FILTER, node);
+        sig.addDocument("", transforms, Constants.ALGO_ID_DIGEST_SHA1);
+
+        PrivateKey privateKey = crypto.getPrivateKey("16c73ab6-b892-458f-abf5-2f875f74882e",
"security");
+
+        sig.sign(privateKey);
+        
+        CryptoType cryptoType = new CryptoType(CryptoType.TYPE.ALIAS);
+        cryptoType.setAlias("16c73ab6-b892-458f-abf5-2f875f74882e");
+        X509Certificate cert = crypto.getX509Certificates(cryptoType)[0];
+        sig.addKeyInfo(cert);
+        sig.checkSignatureValue(cert);
+    }
+    
+    /**
+     * Verifies the soap envelope
+     * 
+     * @param doc
+     * @throws Exception Thrown when there is a problem in verification
+     */
+    private List<WSSecurityEngineResult> verify(Document doc) throws Exception {
+        WSSecurityEngine secEngine = new WSSecurityEngine();
+        List<WSSecurityEngineResult> results = 
+            secEngine.processSecurityHeader(
+                doc, null, null, crypto
+            );
+        String outputString = XMLUtils.PrettyDocumentToString(doc);
+        assertTrue(outputString.indexOf("counter_port_type") > 0 ? true : false);
+        return results;
+    }
+
+    private List<WSSecurityEngineResult> verifyWithoutProfile(Document doc) throws
Exception {
+        SamlAssertionValidator validator = new SamlAssertionValidator();
+        validator.setValidateSignatureAgainstProfile(false);
+        
+        WSSecurityEngine secEngine = new WSSecurityEngine();
+        WSSConfig config = secEngine.getWssConfig();
+        config.setValidator(WSSecurityEngine.SAML_TOKEN, validator);
+        config.setValidator(WSSecurityEngine.SAML2_TOKEN, validator);
+        
+        List<WSSecurityEngineResult> results = 
+            secEngine.processSecurityHeader(
+                doc, null, null, crypto
+            );
+        String outputString = XMLUtils.PrettyDocumentToString(doc);
+        assertTrue(outputString.indexOf("counter_port_type") > 0 ? true : false);
+        return results;
+    }
+
+
+}



Mime
View raw message