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 2016/02/01 12:38:38 UTC
cxf git commit: Weaken SAML Bearer Subject Confirmation Requirements
if the Response is signed
Repository: cxf
Updated Branches:
refs/heads/master 1ed42aa85 -> 3cabac07f
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/3cabac07
Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/3cabac07
Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/3cabac07
Branch: refs/heads/master
Commit: 3cabac07f4325cbc1e5953f178a257827f09608d
Parents: 1ed42aa
Author: Colm O hEigeartaigh <co...@apache.org>
Authored: Mon Feb 1 11:38:10 2016 +0000
Committer: Colm O hEigeartaigh <co...@apache.org>
Committed: Mon Feb 1 11:38:10 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/3cabac07/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 4c084f8..590ed64 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
@@ -51,7 +51,6 @@ import org.apache.wss4j.dom.engine.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;
@@ -81,7 +80,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;
@@ -150,7 +148,7 @@ public class SAMLProtocolResponseValidator {
// Validate Assertions
for (org.opensaml.saml.saml2.core.Assertion assertion : samlResponse.getAssertions()) {
SamlAssertionWrapper wrapper = new SamlAssertionWrapper(assertion);
- validateAssertion(wrapper, sigCrypto, callbackHandler, doc);
+ validateAssertion(wrapper, sigCrypto, callbackHandler, doc, samlResponse.isSigned());
}
}
@@ -205,7 +203,8 @@ public class SAMLProtocolResponseValidator {
for (org.opensaml.saml.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()
);
}
}
@@ -351,7 +350,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);
@@ -405,6 +405,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/3cabac07/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");
+ }
+ }
+}