Author: coheigea
Date: Thu Feb 7 12:33:14 2013
New Revision: 1443438
URL: http://svn.apache.org/viewvc?rev=1443438&view=rev
Log:
[WSS-422] - Move SAML Signature Profile Validation to the SamlAssertionValidator
Added:
webservices/wss4j/branches/1_6_x-fixes/src/test/java/org/apache/ws/security/saml/SamlTokenCustomSignatureTest.java
Modified:
webservices/wss4j/branches/1_6_x-fixes/src/main/java/org/apache/ws/security/saml/ext/AssertionWrapper.java
webservices/wss4j/branches/1_6_x-fixes/src/main/java/org/apache/ws/security/validate/SamlAssertionValidator.java
Modified:
webservices/wss4j/branches/1_6_x-fixes/src/main/java/org/apache/ws/security/saml/ext/AssertionWrapper.java
URL:
http://svn.apache.org/viewvc/webservices/wss4j/branches/1_6_x-fixes/src/main/java/org/apache/ws/security/saml/ext/AssertionWrapper.java?rev=1443438&r1=1443437&r2=1443438&view=diff
==============================================================================
---
webservices/wss4j/branches/1_6_x-fixes/src/main/java/org/apache/ws/security/saml/ext/AssertionWrapper.java
(original)
+++
webservices/wss4j/branches/1_6_x-fixes/src/main/java/org/apache/ws/security/saml/ext/AssertionWrapper.java
Thu Feb 7 12:33:14 2013
@@ -530,12 +530,7 @@ public class AssertionWrapper {
public void verifySignature(
RequestData data, WSDocInfo docInfo
) 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 =
@@ -561,12 +556,6 @@ public class AssertionWrapper {
new Object[]{"cannot get certificate or key"}
);
}
- SAMLSignatureProfileValidator validator = new
SAMLSignatureProfileValidator();
- try {
- validator.validate(sig);
- } catch (ValidationException ex) {
- throw new WSSecurityException("SAML signature validation
failed", ex);
- }
BasicX509Credential credential = new BasicX509Credential();
if (samlKeyInfo.getCerts() != null) {
@@ -591,6 +580,23 @@ public class AssertionWrapper {
}
}
+ /**
+ * 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("SAML signature validation
failed", ex);
+ }
+ }
+ }
+
public Signature getSignature() {
Signature sig = null;
if (saml2 != null && saml2.getSignature() != null) {
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=1443438&r1=1443437&r2=1443438&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
Thu Feb 7 12:33:14 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 assertion against schemas/profiles
*/
protected void validateAssertion(AssertionWrapper assertion) throws
WSSecurityException {
+ if (validateSignatureAgainstProfile) {
+ assertion.validateSignatureAgainstProfile();
+ }
+
if (assertion.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/branches/1_6_x-fixes/src/test/java/org/apache/ws/security/saml/SamlTokenCustomSignatureTest.java
URL:
http://svn.apache.org/viewvc/webservices/wss4j/branches/1_6_x-fixes/src/test/java/org/apache/ws/security/saml/SamlTokenCustomSignatureTest.java?rev=1443438&view=auto
==============================================================================
---
webservices/wss4j/branches/1_6_x-fixes/src/test/java/org/apache/ws/security/saml/SamlTokenCustomSignatureTest.java
(added)
+++
webservices/wss4j/branches/1_6_x-fixes/src/test/java/org/apache/ws/security/saml/SamlTokenCustomSignatureTest.java
Thu Feb 7 12:33:14 2013
@@ -0,0 +1,209 @@
+/**
+ * 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.saml;
+
+import java.security.PrivateKey;
+import java.security.cert.X509Certificate;
+import java.util.List;
+
+import org.apache.ws.security.WSSConfig;
+import org.apache.ws.security.WSSecurityEngine;
+import org.apache.ws.security.WSSecurityEngineResult;
+import org.apache.ws.security.WSSecurityException;
+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.components.crypto.Crypto;
+import org.apache.ws.security.components.crypto.CryptoFactory;
+import org.apache.ws.security.components.crypto.CryptoType;
+import org.apache.ws.security.message.WSSecHeader;
+import org.apache.ws.security.saml.ext.AssertionWrapper;
+import org.apache.ws.security.saml.ext.SAMLParms;
+import org.apache.ws.security.saml.ext.builder.SAML1Constants;
+import org.apache.ws.security.saml.ext.builder.SAML2Constants;
+import org.apache.ws.security.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");
+
+ SAMLParms samlParms = new SAMLParms();
+ samlParms.setCallbackHandler(callbackHandler);
+ AssertionWrapper assertion = new AssertionWrapper(samlParms);
+
+ Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
+ Element assertionElement = assertion.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 =
+
org.apache.ws.security.util.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");
+
+ SAMLParms samlParms = new SAMLParms();
+ samlParms.setCallbackHandler(callbackHandler);
+ AssertionWrapper assertion = new AssertionWrapper(samlParms);
+
+ Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
+ Element assertionElement = assertion.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 =
+
org.apache.ws.security.util.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 =
+ org.apache.ws.security.util.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 =
+ org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(doc);
+ assertTrue(outputString.indexOf("counter_port_type") > 0 ? true :
false);
+ return results;
+ }
+
+
+}