cxf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cohei...@apache.org
Subject [1/2] cxf git commit: Weaken SAML Bearer Subject Confirmation Requirements if the Response is signed
Date Mon, 01 Feb 2016 11:41:10 GMT
Repository: cxf
Updated Branches:
  refs/heads/3.0.x-fixes ad0f5f1a1 -> 0bdf4ebdc


Weaken SAML Bearer Subject Confirmation Requirements if the Response is signed


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

Branch: refs/heads/3.0.x-fixes
Commit: 7a3816efdb97da722e435ed19cfd17461e1ea3f6
Parents: ad0f5f1
Author: Colm O hEigeartaigh <coheigea@apache.org>
Authored: Mon Feb 1 11:38:10 2016 +0000
Committer: Colm O hEigeartaigh <coheigea@apache.org>
Committed: Mon Feb 1 11:39:51 2016 +0000

----------------------------------------------------------------------
 .../saml/sso/SAMLProtocolResponseValidator.java |  11 +-
 .../saml/sso/SamlSSOAssertionValidator.java     | 115 +++++++++++++++++++
 2 files changed, 121 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf/blob/7a3816ef/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/SAMLProtocolResponseValidator.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/SAMLProtocolResponseValidator.java
b/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/SAMLProtocolResponseValidator.java
index ef2cda7..7f1d3f6 100644
--- a/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/SAMLProtocolResponseValidator.java
+++ b/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/SAMLProtocolResponseValidator.java
@@ -50,7 +50,6 @@ import org.apache.wss4j.dom.WSSConfig;
 import org.apache.wss4j.dom.handler.RequestData;
 import org.apache.wss4j.dom.saml.WSSSAMLKeyInfoProcessor;
 import org.apache.wss4j.dom.validate.Credential;
-import org.apache.wss4j.dom.validate.SamlAssertionValidator;
 import org.apache.wss4j.dom.validate.SignatureTrustValidator;
 import org.apache.wss4j.dom.validate.Validator;
 import org.apache.xml.security.encryption.XMLCipher;
@@ -79,7 +78,6 @@ public class SAMLProtocolResponseValidator {
 
     private static final Logger LOG = LogUtils.getL7dLogger(SAMLProtocolResponseValidator.class);
 
-    private Validator assertionValidator = new SamlAssertionValidator();
     private Validator signatureValidator = new SignatureTrustValidator();
     private boolean keyInfoMustBeAvailable = true;
 
@@ -141,7 +139,7 @@ public class SAMLProtocolResponseValidator {
         // Validate Assertions
         for (org.opensaml.saml2.core.Assertion assertion : samlResponse.getAssertions())
{
             SamlAssertionWrapper wrapper = new SamlAssertionWrapper(assertion);
-            validateAssertion(wrapper, sigCrypto, callbackHandler, doc);
+            validateAssertion(wrapper, sigCrypto, callbackHandler, doc, samlResponse.isSigned());
         }
     }
 
@@ -189,7 +187,8 @@ public class SAMLProtocolResponseValidator {
         for (org.opensaml.saml1.core.Assertion assertion : samlResponse.getAssertions())
{
             SamlAssertionWrapper wrapper = new SamlAssertionWrapper(assertion);
             validateAssertion(
-                wrapper, sigCrypto, callbackHandler, samlResponse.getDOM().getOwnerDocument()
+                wrapper, sigCrypto, callbackHandler, samlResponse.getDOM().getOwnerDocument(),
+                samlResponse.isSigned()
             );
         }
     }
@@ -370,7 +369,8 @@ public class SAMLProtocolResponseValidator {
         SamlAssertionWrapper assertion,
         Crypto sigCrypto,
         CallbackHandler callbackHandler,
-        Document doc
+        Document doc,
+        boolean signedResponse
     ) throws WSSecurityException {
         Credential credential = new Credential();
         credential.setSamlAssertion(assertion);
@@ -424,6 +424,7 @@ public class SAMLProtocolResponseValidator {
 
         // Validate the Assertion & verify trust in the signature
         try {
+            SamlSSOAssertionValidator assertionValidator = new SamlSSOAssertionValidator(signedResponse);
             assertionValidator.validate(credential, requestData);
         } catch (WSSecurityException ex) {
             LOG.log(Level.FINE, "Assertion validation failed: " + ex.getMessage(), ex);

http://git-wip-us.apache.org/repos/asf/cxf/blob/7a3816ef/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/SamlSSOAssertionValidator.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/SamlSSOAssertionValidator.java
b/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/SamlSSOAssertionValidator.java
new file mode 100644
index 0000000..0cc8c19
--- /dev/null
+++ b/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/SamlSSOAssertionValidator.java
@@ -0,0 +1,115 @@
+/**
+ * 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.cxf.rs.security.saml.sso;
+
+import java.util.List;
+import java.util.logging.Logger;
+
+import org.apache.cxf.common.logging.LogUtils;
+import org.apache.wss4j.common.ext.WSSecurityException;
+import org.apache.wss4j.common.saml.OpenSAMLUtil;
+import org.apache.wss4j.common.saml.SamlAssertionWrapper;
+import org.apache.wss4j.common.saml.builder.SAML1Constants;
+import org.apache.wss4j.common.saml.builder.SAML2Constants;
+import org.apache.wss4j.dom.validate.SamlAssertionValidator;
+
+/**
+ * An extension of the WSS4J SamlAssertionValidator. We can weaken the subject confirmation
method requirements a bit
+ * for SAML SSO. A Bearer Assertion does not have to be signed by default if the outer Response
is signed.
+ */
+public class SamlSSOAssertionValidator extends SamlAssertionValidator {
+    
+    private static final Logger LOG = LogUtils.getL7dLogger(SamlSSOAssertionValidator.class);
+    
+    private final boolean signedResponse;
+    
+    public SamlSSOAssertionValidator(boolean signedResponse) {
+        this.signedResponse = signedResponse;
+    }
+    
+    /**
+     * Check the Subject Confirmation method requirements
+     */
+    protected void verifySubjectConfirmationMethod(
+        SamlAssertionWrapper samlAssertion
+    ) throws WSSecurityException {
+
+        List<String> methods = samlAssertion.getConfirmationMethods();
+        if (methods == null || methods.isEmpty()) {
+            if (super.getRequiredSubjectConfirmationMethod() != null) {
+                LOG.fine("A required subject confirmation method was not present");
+                throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE,
+                                          "invalidSAMLsecurity");
+            } else if (super.isRequireStandardSubjectConfirmationMethod()) {
+                LOG.fine("A standard subject confirmation method was not present");
+                throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE,
+                                          "invalidSAMLsecurity");
+            }
+        }
+
+        boolean signed = samlAssertion.isSigned();
+        boolean requiredMethodFound = false;
+        boolean standardMethodFound = false;
+        for (String method : methods) {
+            if (OpenSAMLUtil.isMethodHolderOfKey(method)) {
+                if (samlAssertion.getSubjectKeyInfo() == null) {
+                    LOG.fine("There is no Subject KeyInfo to match the holder-of-key subject
conf method");
+                    throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE,
"noKeyInSAMLToken");
+                }
+
+                // The assertion must have been signed for HOK
+                if (!signed) {
+                    LOG.fine("A holder-of-key assertion must be signed");
+                    throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE,
"invalidSAMLsecurity");
+                }
+                standardMethodFound = true;
+            }
+
+            if (method != null) {
+                if (method.equals(super.getRequiredSubjectConfirmationMethod())) {
+                    requiredMethodFound = true;
+                }
+                if (SAML2Constants.CONF_BEARER.equals(method)
+                    || SAML1Constants.CONF_BEARER.equals(method)) {
+                    standardMethodFound = true;
+                    if (super.isRequireBearerSignature() && !signed && !signedResponse)
{
+                        LOG.fine("A Bearer Assertion was not signed");
+                        throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE,
+                                                      "invalidSAMLsecurity");
+                    }
+                } else if (SAML2Constants.CONF_SENDER_VOUCHES.equals(method)
+                    || SAML1Constants.CONF_SENDER_VOUCHES.equals(method)) {
+                    standardMethodFound = true;
+                }
+            }
+        }
+
+        if (!requiredMethodFound && super.getRequiredSubjectConfirmationMethod()
!= null) {
+            LOG.fine("A required subject confirmation method was not present");
+            throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE,
+                                          "invalidSAMLsecurity");
+        }
+
+        if (!standardMethodFound && super.isRequireStandardSubjectConfirmationMethod())
{
+            LOG.fine("A standard subject confirmation method was not present");
+            throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE,
+                                      "invalidSAMLsecurity");
+        }
+    }    
+}


Mime
View raw message