cxf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cohei...@apache.org
Subject svn commit: r1563980 - /cxf/fediz/trunk/plugins/core/src/main/java/org/apache/cxf/fediz/core/saml/SamlAssertionValidator.java
Date Mon, 03 Feb 2014 16:59:13 GMT
Author: coheigea
Date: Mon Feb  3 16:59:13 2014
New Revision: 1563980

URL: http://svn.apache.org/r1563980
Log:
Some fixes taken from WSS4J for the SamlAssertionValidator

Modified:
    cxf/fediz/trunk/plugins/core/src/main/java/org/apache/cxf/fediz/core/saml/SamlAssertionValidator.java

Modified: cxf/fediz/trunk/plugins/core/src/main/java/org/apache/cxf/fediz/core/saml/SamlAssertionValidator.java
URL: http://svn.apache.org/viewvc/cxf/fediz/trunk/plugins/core/src/main/java/org/apache/cxf/fediz/core/saml/SamlAssertionValidator.java?rev=1563980&r1=1563979&r2=1563980&view=diff
==============================================================================
--- cxf/fediz/trunk/plugins/core/src/main/java/org/apache/cxf/fediz/core/saml/SamlAssertionValidator.java
(original)
+++ cxf/fediz/trunk/plugins/core/src/main/java/org/apache/cxf/fediz/core/saml/SamlAssertionValidator.java
Mon Feb  3 16:59:13 2014
@@ -26,11 +26,13 @@ import java.security.cert.CertificateNot
 import java.security.cert.X509Certificate;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Date;
 import java.util.List;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.regex.PatternSyntaxException;
 
+import org.apache.wss4j.common.cache.ReplayCache;
 import org.apache.wss4j.common.crypto.Crypto;
 import org.apache.wss4j.common.ext.WSSecurityException;
 import org.apache.wss4j.common.saml.OpenSAMLUtil;
@@ -41,8 +43,6 @@ import org.apache.wss4j.dom.validate.Cre
 import org.apache.wss4j.dom.validate.Validator;
 import org.joda.time.DateTime;
 import org.opensaml.common.SAMLVersion;
-import org.opensaml.xml.validation.ValidationException;
-import org.opensaml.xml.validation.ValidatorSuite;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -64,6 +64,12 @@ public class SamlAssertionValidator impl
      * Assertion is valid. The default is 60 seconds.
      */
     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;
 
     /**
      * Defines the kind of trust which is required thus assertion signature validation is
successful.
@@ -144,6 +150,9 @@ public class SamlAssertionValidator impl
         // Check conditions
         checkConditions(assertion);
         
+        // Check OneTimeUse Condition
+        checkOneTimeUse(assertion, data);
+        
         // Validate the assertion against schemas/profiles
         validateAssertion(assertion);
 
@@ -180,7 +189,6 @@ public class SamlAssertionValidator impl
         
         if (certs != null && certs.length > 0) {
             validateCertificates(certs);
-            validateCertificates(certs);
             verifyTrustInCerts(certs, crypto, data, data.isRevocationEnabled());
             if (signatureTrustType.equals(TRUST_TYPE.CHAIN_TRUST_CONSTRAINTS)) {
                 if (matches(certs[0])) {
@@ -240,13 +248,13 @@ public class SamlAssertionValidator impl
         RequestData data,
         boolean enableRevocation
     ) throws WSSecurityException {
-        String subjectString = certificates[0].getSubjectX500Principal().getName();
         //
         // Use the validation method from the crypto to check whether the subjects' 
         // certificate was really signed by the issuer stated in the certificate
         //
         crypto.verifyTrust(certificates, enableRevocation);
         if (LOG.isDebugEnabled()) {
+            String subjectString = certificates[0].getSubjectX500Principal().getName();
             LOG.debug(
                 "Certificate path has been verified for certificate with subject " + subjectString
             );
@@ -262,73 +270,73 @@ public class SamlAssertionValidator impl
         crypto.verifyTrust(publicKey);
     }
     
+    
     /**
      * Check the Conditions of the Assertion.
      */
-    protected void checkConditions(SamlAssertionWrapper assertion) throws WSSecurityException
{
-        DateTime validFrom = null;
-        DateTime validTill = null;
-        if (assertion.getSamlVersion().equals(SAMLVersion.VERSION_20)
-            && assertion.getSaml2().getConditions() != null) {
-            validFrom = assertion.getSaml2().getConditions().getNotBefore();
-            validTill = assertion.getSaml2().getConditions().getNotOnOrAfter();
-        } else if (assertion.getSamlVersion().equals(SAMLVersion.VERSION_11)
-            && assertion.getSaml1().getConditions() != null) {
-            validFrom = assertion.getSaml1().getConditions().getNotBefore();
-            validTill = assertion.getSaml1().getConditions().getNotOnOrAfter();
-        }
-        
-        if (validFrom != null) {
-            DateTime currentTime = new DateTime();
-            currentTime = currentTime.plusSeconds(futureTTL);
-            if (validFrom.isAfter(currentTime)) {
-                LOG.debug("SAML Token condition (Not Before) not met");
-                throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity");
-            }
-        }
-
-        if (validTill != null && validTill.isBeforeNow()) {
-            LOG.debug("SAML Token condition (Not On Or After) not met");
-            throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity");
-        }
+    protected void checkConditions(SamlAssertionWrapper samlAssertion) throws WSSecurityException
{
+        samlAssertion.checkConditions(futureTTL);
     }
     
     /**
-     * Validate the assertion against schemas/profiles
-     */
-    protected void validateAssertion(SamlAssertionWrapper assertion) throws WSSecurityException
{
-        if (assertion.getSaml1() != null) {
-            ValidatorSuite schemaValidators = 
-                org.opensaml.Configuration.getValidatorSuite("saml1-schema-validator");
-            ValidatorSuite specValidators = 
-                org.opensaml.Configuration.getValidatorSuite("saml1-spec-validator");
-            try {
-                schemaValidators.validate(assertion.getSaml1());
-                specValidators.validate(assertion.getSaml1());
-            } catch (ValidationException e) {
-                LOG.debug("Saml Validation error: " + e.getMessage(), e);
-                throw new WSSecurityException(
-                    WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity", null, e
-                );
-            }
-        } else if (assertion.getSaml2() != null) {
-            ValidatorSuite schemaValidators = 
-                org.opensaml.Configuration.getValidatorSuite("saml2-core-schema-validator");
-            ValidatorSuite specValidators = 
-                org.opensaml.Configuration.getValidatorSuite("saml2-core-spec-validator");
-            try {
-                schemaValidators.validate(assertion.getSaml2());
-                specValidators.validate(assertion.getSaml2());
-            } catch (ValidationException e) {
-                LOG.debug("Saml Validation error: " + e.getMessage(), e);
+     * Check the "OneTimeUse" Condition of the Assertion. If this is set then the Assertion
+     * is cached (if a cache is defined), and must not have been previously cached
+     */
+    protected void checkOneTimeUse(
+        SamlAssertionWrapper samlAssertion, RequestData data
+    ) throws WSSecurityException {
+        if (samlAssertion.getSamlVersion().equals(SAMLVersion.VERSION_20)
+            && samlAssertion.getSaml2().getConditions() != null
+            && samlAssertion.getSaml2().getConditions().getOneTimeUse() != null
+            && data.getSamlOneTimeUseReplayCache() != null) {
+            String identifier = samlAssertion.getId();
+            
+            ReplayCache replayCache = data.getSamlOneTimeUseReplayCache();
+            if (replayCache.contains(identifier)) {
                 throw new WSSecurityException(
-                    WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity", null, e
-                );
+                    WSSecurityException.ErrorCode.INVALID_SECURITY,
+                    "badSamlToken",
+                    "A replay attack has been detected");
+            }
+            
+            DateTime expires = samlAssertion.getSaml2().getConditions().getNotOnOrAfter();
+            if (expires != null) {
+                Date rightNow = new Date();
+                long currentTime = rightNow.getTime();
+                long expiresTime = expires.getMillis();
+                replayCache.add(identifier, 1L + (expiresTime - currentTime) / 1000L);
+            } else {
+                replayCache.add(identifier);
             }
+            
+            replayCache.add(identifier);
         }
     }
     
     /**
+     * Validate the samlAssertion against schemas/profiles
+     */
+    protected void validateAssertion(SamlAssertionWrapper samlAssertion) throws WSSecurityException
{
+        samlAssertion.validateAssertion(validateSignatureAgainstProfile);
+    }
+    
+    /**
+     * 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;
+    }
+    
+    /**
      * @return true if the certificate's SubjectDN matches the constraints
      *         defined in the subject DNConstraints; false, otherwise. The
      *         certificate subject DN only has to match ONE of the subject cert



Mime
View raw message