Author: coheigea
Date: Mon Apr 11 11:24:29 2011
New Revision: 1091032
URL: http://svn.apache.org/viewvc?rev=1091032&view=rev
Log:
[WSS-276] - Support signing a SAML Assertion using a derived key
- Added a fix plus a test.
- Also fixed another bug with using the STRTransform with a direct reference.
- Upgraded versions to 1.6.1-SNAPSHOT.
Added:
webservices/wss4j/trunk/src/test/java/org/apache/ws/security/saml/SamlTokenDerivedTest.java
Modified:
webservices/wss4j/trunk/NOTICE
webservices/wss4j/trunk/build.xml
webservices/wss4j/trunk/pom.xml
webservices/wss4j/trunk/src/main/java/org/apache/ws/security/message/WSSecDKSign.java
webservices/wss4j/trunk/src/main/java/org/apache/ws/security/message/token/SecurityTokenReference.java
Modified: webservices/wss4j/trunk/NOTICE
URL:
http://svn.apache.org/viewvc/webservices/wss4j/trunk/NOTICE?rev=1091032&r1=1091031&r2=1091032&view=diff
==============================================================================
--- webservices/wss4j/trunk/NOTICE (original)
+++ webservices/wss4j/trunk/NOTICE Mon Apr 11 11:24:29 2011
@@ -1,5 +1,5 @@
Apache WebServices - WSS4J
-Copyright 2004-2009 The Apache Software Foundation
+Copyright 2004-2011 The Apache Software Foundation
This product includes software developed by
The Apache Software Foundation (http://www.apache.org/).
Modified: webservices/wss4j/trunk/build.xml
URL:
http://svn.apache.org/viewvc/webservices/wss4j/trunk/build.xml?rev=1091032&r1=1091031&r2=1091032&view=diff
==============================================================================
--- webservices/wss4j/trunk/build.xml (original)
+++ webservices/wss4j/trunk/build.xml Mon Apr 11 11:24:29 2011
@@ -27,10 +27,10 @@ Build Instructions:
<property name='product.version.major' value='1'/>
<property name='product.version.minor' value='6'/>
- <!--<property name='product.version.level' value='0'/>-->
+ <property name='product.version.level' value='1'/>
<property name='product.version.qualifier' value='-SNAPSHOT'/>
- <property name='product.version'
value='${product.version.major}.${product.version.minor}${product.version.qualifier}'/>
- <property name="year" value="2010"/>
+ <property name='product.version'
value='${product.version.major}.${product.version.minor}.${product.version.level}${product.version.qualifier}'/>
+ <property name="year" value="2011"/>
<property name="copyright" value="Copyright © ${year} Apache
WSS4J Project. All Rights Reserved."/>
<!-- Give user a chance to override without editing this file
Modified: webservices/wss4j/trunk/pom.xml
URL:
http://svn.apache.org/viewvc/webservices/wss4j/trunk/pom.xml?rev=1091032&r1=1091031&r2=1091032&view=diff
==============================================================================
--- webservices/wss4j/trunk/pom.xml (original)
+++ webservices/wss4j/trunk/pom.xml Mon Apr 11 11:24:29 2011
@@ -24,7 +24,7 @@
<artifactId>wss4j</artifactId>
<packaging>bundle</packaging>
<name>WSS4J</name>
- <version>1.6-SNAPSHOT</version>
+ <version>1.6.1-SNAPSHOT</version>
<description>
The Apache WSS4J project provides a Java implementation of the primary
security standards
for Web Services, namely the OASIS Web Services Security (WS-Security)
specifications
Modified:
webservices/wss4j/trunk/src/main/java/org/apache/ws/security/message/WSSecDKSign.java
URL:
http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/main/java/org/apache/ws/security/message/WSSecDKSign.java?rev=1091032&r1=1091031&r2=1091032&view=diff
==============================================================================
---
webservices/wss4j/trunk/src/main/java/org/apache/ws/security/message/WSSecDKSign.java
(original)
+++
webservices/wss4j/trunk/src/main/java/org/apache/ws/security/message/WSSecDKSign.java
Mon Apr 11 11:24:29 2011
@@ -27,6 +27,7 @@ import org.apache.ws.security.WSSecurity
import org.apache.ws.security.conversation.ConversationException;
import org.apache.ws.security.message.token.Reference;
import org.apache.ws.security.message.token.SecurityTokenReference;
+import org.apache.ws.security.transform.STRTransform;
import org.apache.ws.security.util.WSSecurityUtil;
import org.w3c.dom.Document;
@@ -269,6 +270,7 @@ public class WSSecDKSign extends WSSecDe
);
}
URIDereferencer dereferencer = new DOMURIDereferencer();
+ signContext.setProperty(STRTransform.TRANSFORM_WS_DOC_INFO,
wsDocInfo);
wsDocInfo.setCallbackLookup(callbackLookup);
((DOMURIDereferencer)dereferencer).setWsDocInfo(wsDocInfo);
signContext.setURIDereferencer(dereferencer);
Modified:
webservices/wss4j/trunk/src/main/java/org/apache/ws/security/message/token/SecurityTokenReference.java
URL:
http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/main/java/org/apache/ws/security/message/token/SecurityTokenReference.java?rev=1091032&r1=1091031&r2=1091032&view=diff
==============================================================================
---
webservices/wss4j/trunk/src/main/java/org/apache/ws/security/message/token/SecurityTokenReference.java
(original)
+++
webservices/wss4j/trunk/src/main/java/org/apache/ws/security/message/token/SecurityTokenReference.java
Mon Apr 11 11:24:29 2011
@@ -270,7 +270,7 @@ public class SecurityTokenReference {
if (callbackLookup == null) {
callbackLookup = new DOMCallbackLookup(doc);
}
- return callbackLookup.getElement(uri, type, true);
+ return callbackLookup.getElement(id, type, true);
}
/**
Added:
webservices/wss4j/trunk/src/test/java/org/apache/ws/security/saml/SamlTokenDerivedTest.java
URL:
http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/test/java/org/apache/ws/security/saml/SamlTokenDerivedTest.java?rev=1091032&view=auto
==============================================================================
---
webservices/wss4j/trunk/src/test/java/org/apache/ws/security/saml/SamlTokenDerivedTest.java
(added)
+++
webservices/wss4j/trunk/src/test/java/org/apache/ws/security/saml/SamlTokenDerivedTest.java
Mon Apr 11 11:24:29 2011
@@ -0,0 +1,208 @@
+/**
+ * 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 org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSDataRef;
+import org.apache.ws.security.WSEncryptionPart;
+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.KeystoreCallbackHandler;
+import org.apache.ws.security.common.SAML1CallbackHandler;
+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.WSSecDKSign;
+import org.apache.ws.security.message.WSSecHeader;
+import org.apache.ws.security.message.token.SecurityTokenReference;
+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.util.WSSecurityUtil;
+
+import org.w3c.dom.Document;
+
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.security.auth.callback.CallbackHandler;
+
+/**
+ * Test-case for sending and processing a signed (sender vouches) SAML
Assertion using a
+ * derived key.
+ */
+public class SamlTokenDerivedTest extends org.junit.Assert {
+ private static final org.apache.commons.logging.Log LOG =
+
org.apache.commons.logging.LogFactory.getLog(SamlTokenDerivedTest.class);
+ private WSSecurityEngine secEngine = new WSSecurityEngine();
+ private CallbackHandler callbackHandler = new KeystoreCallbackHandler();
+ private Crypto crypto = null;
+
+ public SamlTokenDerivedTest() throws Exception {
+ WSSConfig.init();
+ crypto = CryptoFactory.getInstance("crypto.properties");
+ }
+
+ /**
+ * Test that creates, sends and processes a signed SAML 1.1 authentication
assertion
+ * using a derived key.
+ */
+ @org.junit.Test
+ @SuppressWarnings("unchecked")
+ public void testSAML1AuthnAssertionDerived() throws Exception {
+ //
+ // Create a SAML Assertion + STR, and add both to the security header
+ //
+ SAML1CallbackHandler callbackHandler = new SAML1CallbackHandler();
+ callbackHandler.setStatement(SAML1CallbackHandler.Statement.AUTHN);
+
callbackHandler.setConfirmationMethod(SAML1Constants.CONF_SENDER_VOUCHES);
+ 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);
+ WSSecHeader secHeader = new WSSecHeader();
+ secHeader.insertSecurityHeader(doc);
+
+ SecurityTokenReference secRefSaml =
+ createSamlSTR(doc, assertion, WSSConfig.getNewInstance());
+ secHeader.getSecurityHeader().appendChild(assertion.toDOM(doc));
+ secHeader.getSecurityHeader().appendChild(secRefSaml.getElement());
+
+ //
+ // Create a Derived Key object for signature
+ //
+ WSSecDKSign sigBuilder = createDKSign(doc, secRefSaml);
+ Document signedDoc = sigBuilder.build(doc, secHeader);
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("SAML 1.1 Authn Assertion Derived (sender vouches):");
+ String outputString =
+
org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(signedDoc);
+ LOG.debug(outputString);
+ }
+
+ // Test we processed a SAML assertion
+ List<WSSecurityEngineResult> results = verify(signedDoc);
+ WSSecurityEngineResult actionResult =
+ WSSecurityUtil.fetchActionResult(results, WSConstants.ST_UNSIGNED);
+ AssertionWrapper receivedAssertion =
+ (AssertionWrapper)
actionResult.get(WSSecurityEngineResult.TAG_SAML_ASSERTION);
+ assertTrue(receivedAssertion != null);
+
+ // Test we processed a signature (SAML assertion + SOAP body)
+ actionResult = WSSecurityUtil.fetchActionResult(results,
WSConstants.SIGN);
+ assertTrue(actionResult != null);
+ assertFalse(actionResult.isEmpty());
+ final List<WSDataRef> refs =
+ (List<WSDataRef>)
actionResult.get(WSSecurityEngineResult.TAG_DATA_REF_URIS);
+ assertTrue(refs.size() == 2);
+
+ WSDataRef wsDataRef = (WSDataRef)refs.get(0);
+ String xpath = wsDataRef.getXpath();
+ assertEquals("/SOAP-ENV:Envelope/SOAP-ENV:Body", xpath);
+
+ wsDataRef = (WSDataRef)refs.get(1);
+ xpath = wsDataRef.getXpath();
+
assertEquals("/SOAP-ENV:Envelope/SOAP-ENV:Header/wsse:Security/saml1:Assertion",
xpath);
+ }
+
+ /**
+ * Create a SecurityTokenReference to a SAML Assertion
+ */
+ private SecurityTokenReference createSamlSTR(
+ Document doc,
+ AssertionWrapper assertion,
+ WSSConfig wssConfig
+ ) {
+ SecurityTokenReference secRefSaml = new SecurityTokenReference(doc);
+ String secRefID =
wssConfig.getIdAllocator().createSecureId("STRSAMLId-", secRefSaml);
+ secRefSaml.setID(secRefID);
+
+ org.apache.ws.security.message.token.Reference ref =
+ new org.apache.ws.security.message.token.Reference(doc);
+ ref.setURI("#" + assertion.getId());
+ ref.setValueType(WSConstants.WSS_SAML_KI_VALUE_TYPE);
+ secRefSaml.addTokenType(WSConstants.WSS_SAML_TOKEN_TYPE);
+ secRefSaml.setReference(ref);
+
+ return secRefSaml;
+ }
+
+ /**
+ * Create a WSSecDKSign object, that signs the SOAP Body as well as the
SAML Assertion
+ * via a STR Transform.
+ */
+ private WSSecDKSign createDKSign(
+ Document doc,
+ SecurityTokenReference secRefSaml
+ ) throws WSSecurityException {
+ SecurityTokenReference secToken = new SecurityTokenReference(doc);
+ CryptoType cryptoType = new CryptoType(CryptoType.TYPE.ALIAS);
+ cryptoType.setAlias("16c73ab6-b892-458f-abf5-2f875f74882e");
+ X509Certificate[] certs = crypto.getX509Certificates(cryptoType);
+ secToken.setKeyIdentifierThumb(certs[0]);
+
+ WSSecDKSign sigBuilder = new WSSecDKSign();
+ java.security.Key key =
+ crypto.getPrivateKey("16c73ab6-b892-458f-abf5-2f875f74882e",
"security");
+ sigBuilder.setExternalKey(key.getEncoded(), secToken.getElement());
+ sigBuilder.setSignatureAlgorithm(WSConstants.HMAC_SHA1);
+ List<WSEncryptionPart> parts = new ArrayList<WSEncryptionPart>(2);
+ String soapNamespace =
WSSecurityUtil.getSOAPNamespace(doc.getDocumentElement());
+ WSEncryptionPart encP =
+ new WSEncryptionPart(
+ WSConstants.ELEM_BODY,
+ soapNamespace,
+ "Content"
+ );
+ parts.add(encP);
+ encP = new WSEncryptionPart("STRTransform", "", "Element");
+ encP.setId(secRefSaml.getID());
+ encP.setElement(secRefSaml.getElement());
+ parts.add(encP);
+ sigBuilder.setParts(parts);
+
+ return sigBuilder;
+ }
+
+ /**
+ * Verifies the soap envelope
+ * <p/>
+ *
+ * @param envelope
+ * @throws Exception Thrown when there is a problem in verification
+ */
+ private List<WSSecurityEngineResult> verify(Document doc) throws Exception
{
+ List<WSSecurityEngineResult> results =
+ secEngine.processSecurityHeader(doc, null, callbackHandler,
crypto);
+ String outputString =
+ org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(doc);
+ assertTrue(outputString.indexOf("counter_port_type") > 0 ? true :
false);
+ return results;
+ }
+
+}