You are viewing a plain text version of this content. The canonical link for it is here.
Posted to wss4j-dev@ws.apache.org by co...@apache.org on 2010/09/18 16:04:05 UTC

svn commit: r998472 - in /webservices/wss4j/trunk: src/org/apache/ws/security/processor/ src/org/apache/ws/security/saml/ test/ test/wssec/

Author: coheigea
Date: Sat Sep 18 14:04:04 2010
New Revision: 998472

URL: http://svn.apache.org/viewvc?rev=998472&view=rev
Log:
[WSS-240] - Support KeyValue in SAML subject
 - Patch applied, thanks.

Added:
    webservices/wss4j/trunk/test/saml4sendKeyValue.properties
Modified:
    webservices/wss4j/trunk/src/org/apache/ws/security/processor/SignatureProcessor.java
    webservices/wss4j/trunk/src/org/apache/ws/security/saml/SAMLIssuerImpl.java
    webservices/wss4j/trunk/src/org/apache/ws/security/saml/SAMLKeyInfo.java
    webservices/wss4j/trunk/src/org/apache/ws/security/saml/SAMLUtil.java
    webservices/wss4j/trunk/src/org/apache/ws/security/saml/WSSecSignatureSAML.java
    webservices/wss4j/trunk/test/saml4.properties
    webservices/wss4j/trunk/test/wssec/TestWSSecurityNewST3.java

Modified: webservices/wss4j/trunk/src/org/apache/ws/security/processor/SignatureProcessor.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/org/apache/ws/security/processor/SignatureProcessor.java?rev=998472&r1=998471&r2=998472&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/org/apache/ws/security/processor/SignatureProcessor.java (original)
+++ webservices/wss4j/trunk/src/org/apache/ws/security/processor/SignatureProcessor.java Sat Sep 18 14:04:04 2010
@@ -328,6 +328,7 @@ public class SignatureProcessor implemen
                         certs = samlKi.getCerts();
                         validateCertificates(certs, crypto);
                         secretKey = samlKi.getSecret();
+                        publicKey = samlKi.getPublicKey();
                         principal = createPrincipalFromSAMLKeyInfo(samlKi);
                     }
                 } else if (secRef.containsX509Data() || secRef.containsX509IssuerSerial()) {
@@ -351,6 +352,7 @@ public class SignatureProcessor implemen
                         certs = samlKi.getCerts();
                         validateCertificates(certs, crypto);
                         secretKey = samlKi.getSecret();
+                        publicKey = samlKi.getPublicKey();
                         principal = createPrincipalFromSAMLKeyInfo(samlKi);
                     } else {
                         certs = secRef.getKeyIdentifier(crypto);

Modified: webservices/wss4j/trunk/src/org/apache/ws/security/saml/SAMLIssuerImpl.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/org/apache/ws/security/saml/SAMLIssuerImpl.java?rev=998472&r1=998471&r2=998472&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/org/apache/ws/security/saml/SAMLIssuerImpl.java (original)
+++ webservices/wss4j/trunk/src/org/apache/ws/security/saml/SAMLIssuerImpl.java Sat Sep 18 14:04:04 2010
@@ -28,6 +28,8 @@ import org.apache.ws.security.components
 import org.apache.xml.security.exceptions.XMLSecurityException;
 import org.apache.xml.security.keys.KeyInfo;
 import org.apache.xml.security.keys.content.X509Data;
+import org.apache.xml.security.keys.content.keyvalues.DSAKeyValue;
+import org.apache.xml.security.keys.content.keyvalues.RSAKeyValue;
 import org.apache.xml.security.signature.XMLSignature;
 import org.opensaml.SAMLAssertion;
 import org.opensaml.SAMLAuthenticationStatement;
@@ -38,6 +40,7 @@ import org.opensaml.SAMLSubject;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 
+import java.security.PublicKey;
 import java.security.cert.X509Certificate;
 import java.util.Arrays;
 import java.util.Collection;
@@ -69,6 +72,14 @@ public class SAMLIssuerImpl implements S
     private String[] confirmationMethods = new String[1];
     private Crypto userCrypto = null;
     private String username = null;
+    
+    /**
+     * Flag indicating what format to put the subject's key material in when
+     * NOT using Sender Vouches as the confirmation method.  The default is
+     * to use ds:X509Data and include the entire certificate.  If this flag
+     * is set to true, a ds:KeyValue is used instead with just the key material.
+     */
+    private boolean sendKeyValue = false;
 
     /**
      * Constructor.
@@ -96,6 +107,12 @@ public class SAMLIssuerImpl implements S
             issuerKeyPassword =
                     properties.getProperty("org.apache.ws.security.saml.issuer.key.password");
         }
+        
+        String sendKeyValueProp =
+                properties.getProperty("org.apache.ws.security.saml.issuer.sendKeyValue");
+        if (sendKeyValueProp != null) {
+            sendKeyValue = Boolean.valueOf(sendKeyValueProp).booleanValue();
+        }
 
         if ("senderVouches"
                 .equals(properties.getProperty("org.apache.ws.security.saml.confirmationMethod"))) {
@@ -170,9 +187,22 @@ public class SAMLIssuerImpl implements S
                 try {
                     X509Certificate[] certs =
                             userCrypto.getCertificates(username);
-                    X509Data certElem = new X509Data(instanceDoc);
-                    certElem.addCertificate(certs[0]);
-                    ki.add(certElem);
+                    if (sendKeyValue) {
+                        PublicKey key = certs[0].getPublicKey();
+                        String pubKeyAlgo = key.getAlgorithm();
+                        
+                        if ("DSA".equalsIgnoreCase(pubKeyAlgo)) {
+                            DSAKeyValue dsaKeyValue = new DSAKeyValue(instanceDoc, key);
+                            ki.add(dsaKeyValue);
+                        } else if ("RSA".equalsIgnoreCase(pubKeyAlgo)) {
+                            RSAKeyValue rsaKeyValue = new RSAKeyValue(instanceDoc, key);
+                            ki.add(rsaKeyValue);
+                        }
+                    } else {
+                        X509Data certElem = new X509Data(instanceDoc);
+                        certElem.addCertificate(certs[0]);
+                        ki.add(certElem);
+                    }
                 } catch (WSSecurityException ex) {
                     if (log.isDebugEnabled()) {
                         log.debug(ex.getMessage(), ex);

Modified: webservices/wss4j/trunk/src/org/apache/ws/security/saml/SAMLKeyInfo.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/org/apache/ws/security/saml/SAMLKeyInfo.java?rev=998472&r1=998471&r2=998472&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/org/apache/ws/security/saml/SAMLKeyInfo.java (original)
+++ webservices/wss4j/trunk/src/org/apache/ws/security/saml/SAMLKeyInfo.java Sat Sep 18 14:04:04 2010
@@ -21,6 +21,7 @@ package org.apache.ws.security.saml;
 
 import org.opensaml.SAMLAssertion;
 
+import java.security.PublicKey;
 import java.security.cert.X509Certificate;
 
 /**
@@ -39,6 +40,11 @@ public class SAMLKeyInfo {
     private byte[] secret;
     
     /**
+     * The public key {e.g.: held in a ds:KeyInfo).
+     */
+    private PublicKey publicKey;
+    
+    /**
      * SAMLAssertion
      */
     SAMLAssertion assertion;
@@ -53,15 +59,24 @@ public class SAMLKeyInfo {
         this.assertion = assertions;
     }
     
+    public SAMLKeyInfo(SAMLAssertion assertions, PublicKey publicKey) {
+        this.publicKey = publicKey;
+        this.assertion = assertions;
+    }
+
     public X509Certificate[] getCerts() {
         return certs;
     }
+    
     public byte[] getSecret() {
         return secret;
     }
 
+    public PublicKey getPublicKey() {
+        return this.publicKey;
+    }
+
     public SAMLAssertion getAssertion() {
         return assertion;
     }
-    
-}
\ No newline at end of file
+}

Modified: webservices/wss4j/trunk/src/org/apache/ws/security/saml/SAMLUtil.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/org/apache/ws/security/saml/SAMLUtil.java?rev=998472&r1=998471&r2=998472&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/org/apache/ws/security/saml/SAMLUtil.java (original)
+++ webservices/wss4j/trunk/src/org/apache/ws/security/saml/SAMLUtil.java Sat Sep 18 14:04:04 2010
@@ -49,6 +49,7 @@ import javax.security.auth.callback.Call
 import javax.security.auth.callback.CallbackHandler;
 import javax.xml.namespace.QName;
 
+import java.security.PublicKey;
 import java.security.cert.X509Certificate;
 import java.util.Iterator;
 
@@ -148,6 +149,9 @@ public class SAMLUtil {
                                 certs[0] = cert;
                                 return new SAMLKeyInfo(assertion, certs);
                             }
+                        } else if (ki.containsKeyValue()) {
+                            PublicKey pk = ki.getPublicKey();
+                            return new SAMLKeyInfo(assertion, pk);
                         }
 
                     } catch (XMLSecurityException e3) {

Modified: webservices/wss4j/trunk/src/org/apache/ws/security/saml/WSSecSignatureSAML.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/org/apache/ws/security/saml/WSSecSignatureSAML.java?rev=998472&r1=998471&r2=998472&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/org/apache/ws/security/saml/WSSecSignatureSAML.java (original)
+++ webservices/wss4j/trunk/src/org/apache/ws/security/saml/WSSecSignatureSAML.java Sat Sep 18 14:04:04 2010
@@ -42,6 +42,7 @@ import org.opensaml.SAMLSubjectStatement
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 
+import java.security.PublicKey;
 import java.security.cert.X509Certificate;
 import java.util.Iterator;
 import java.util.List;
@@ -237,6 +238,7 @@ public class WSSecSignatureSAML extends 
         wsDocInfo = new WSDocInfo(doc);
 
         X509Certificate[] certs = null;
+        PublicKey publicKey = null;
 
         if (senderVouches) {
             certs = issuerCrypto.getCertificates(issuerKeyName);
@@ -272,6 +274,8 @@ public class WSSecSignatureSAML extends 
                         certs = new X509Certificate[1];
                         certs[0] = cert;
                     }
+                } else if (ki.containsKeyValue()) {
+                    publicKey = ki.getPublicKey();
                 }
                 // TODO: get alias name for cert, check against username set by
                 // caller
@@ -285,15 +289,24 @@ public class WSSecSignatureSAML extends 
             }
             wsDocInfo.setCrypto(userCrypto);
         }
-        if (certs == null || certs.length <= 0) {
+        if ((certs == null || certs.length == 0 || certs[0] == null) 
+                && publicKey == null) {
             throw new WSSecurityException(
                 WSSecurityException.FAILURE,
                 "noCertsFound",
                 new Object[] { "SAML signature" }
             );
         }
+        
         if (sigAlgo == null) {
-            String pubKeyAlgo = certs[0].getPublicKey().getAlgorithm();
+            PublicKey key = null;
+            if (certs != null && certs[0] != null) {
+                key = certs[0].getPublicKey();
+            } else if (publicKey != null) {
+                key = publicKey;
+            }
+            
+            String pubKeyAlgo = key.getAlgorithm();
             log.debug("automatic sig algo detection: " + pubKeyAlgo);
             if (pubKeyAlgo.equalsIgnoreCase("DSA")) {
                 sigAlgo = WSConstants.DSA;
@@ -330,7 +343,10 @@ public class WSSecSignatureSAML extends 
         secRef = new SecurityTokenReference(doc);
         strUri = wssConfig.getIdAllocator().createSecureId("STRId-", secRef);
         secRef.setID(strUri);
-        certUri = wssConfig.getIdAllocator().createSecureId("CertId-", certs[0]);  
+        
+        if (certs != null && certs.length != 0) {
+            certUri = wssConfig.getIdAllocator().createSecureId("CertId-", certs[0]);
+        }
 
         //
         // If the sender vouches, then we must sign the SAML token _and_ at

Modified: webservices/wss4j/trunk/test/saml4.properties
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/test/saml4.properties?rev=998472&r1=998471&r2=998472&view=diff
==============================================================================
--- webservices/wss4j/trunk/test/saml4.properties (original)
+++ webservices/wss4j/trunk/test/saml4.properties Sat Sep 18 14:04:04 2010
@@ -3,6 +3,7 @@ org.apache.ws.security.saml.issuer.crypt
 org.apache.ws.security.saml.issuer.key.name=16c73ab6-b892-458f-abf5-2f875f74882e
 org.apache.ws.security.saml.issuer.key.password=security
 org.apache.ws.security.saml.issuer=www.example.com
+org.apache.ws.security.saml.issuer.sendKeyValue=false
 org.apache.ws.security.saml.subjectNameId.name=uid=joe,ou=people,ou=saml-demo,o=example.com
 org.apache.ws.security.saml.subjectNameId.qualifier=www.example.com
 org.apache.ws.security.saml.authenticationMethod=password

Added: webservices/wss4j/trunk/test/saml4sendKeyValue.properties
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/test/saml4sendKeyValue.properties?rev=998472&view=auto
==============================================================================
--- webservices/wss4j/trunk/test/saml4sendKeyValue.properties (added)
+++ webservices/wss4j/trunk/test/saml4sendKeyValue.properties Sat Sep 18 14:04:04 2010
@@ -0,0 +1,13 @@
+org.apache.ws.security.saml.issuerClass=org.apache.ws.security.saml.SAMLIssuerImpl
+org.apache.ws.security.saml.issuer.cryptoProp.file=crypto.properties
+org.apache.ws.security.saml.issuer.key.name=16c73ab6-b892-458f-abf5-2f875f74882e
+org.apache.ws.security.saml.issuer.key.password=security
+org.apache.ws.security.saml.issuer=www.example.com
+org.apache.ws.security.saml.issuer.sendKeyValue=true
+org.apache.ws.security.saml.subjectNameId.name=uid=joe,ou=people,ou=saml-demo,o=example.com
+org.apache.ws.security.saml.subjectNameId.qualifier=www.example.com
+org.apache.ws.security.saml.authenticationMethod=password
+#org.apache.ws.security.saml.confirmationMethod=senderVouches
+org.apache.ws.security.saml.confirmationMethod=keyHolder
+#org.apache.ws.security.saml
+#org.apache.ws.security.saml

Modified: webservices/wss4j/trunk/test/wssec/TestWSSecurityNewST3.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/test/wssec/TestWSSecurityNewST3.java?rev=998472&r1=998471&r2=998472&view=diff
==============================================================================
--- webservices/wss4j/trunk/test/wssec/TestWSSecurityNewST3.java (original)
+++ webservices/wss4j/trunk/test/wssec/TestWSSecurityNewST3.java Sat Sep 18 14:04:04 2010
@@ -136,6 +136,55 @@ public class TestWSSecurityNewST3 extend
         assertTrue(receivedAssertion != null);
     }
     
+    /**
+     * Test that creates, sends and processes a signed SAML assertion containing
+     * only key material and not an entire X509Certificate.
+     */
+    public void testSAMLSignedKeyHolderSendKeyValue() throws Exception {
+        Document doc = SOAPUtil.toSOAPPart(SOAPMSG);
+        
+        SAMLIssuer saml = SAMLIssuerFactory.getInstance("saml4sendKeyValue.properties");
+        // Provide info to SAML issuer that it can construct a Holder-of-key
+        // SAML token.
+        saml.setInstanceDoc(doc);
+        saml.setUserCrypto(crypto);
+        saml.setUsername("16c73ab6-b892-458f-abf5-2f875f74882e");
+        SAMLAssertion assertion = saml.newAssertion();
+
+        WSSecSignatureSAML wsSign = new WSSecSignatureSAML();
+        wsSign.setDigestAlgo("http://www.w3.org/2001/04/xmlenc#sha256");
+        wsSign.setSignatureAlgorithm("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256");
+        wsSign.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
+        wsSign.setUserInfo("16c73ab6-b892-458f-abf5-2f875f74882e", "security");
+
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);
+
+        LOG.info("Before SAMLSignedKeyHolder....");
+        
+        //
+        // set up for keyHolder
+        //
+        Document signedDoc = wsSign.build(doc, crypto, assertion, null, null, null, secHeader);
+        LOG.info("After SAMLSignedKeyHolder....");
+
+        String outputString = 
+            org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(signedDoc);
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("Signed SAML message (key holder):");
+            LOG.debug(outputString);
+        }
+        assertTrue(outputString.indexOf("http://www.w3.org/2001/04/xmlenc#sha256") != -1);
+        assertTrue(outputString.indexOf("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256") != -1);
+        
+        List results = verify(signedDoc);
+        WSSecurityEngineResult actionResult =
+            WSSecurityUtil.fetchActionResult(results, WSConstants.ST_UNSIGNED);
+        SAMLAssertion receivedAssertion = 
+            (SAMLAssertion) actionResult.get(WSSecurityEngineResult.TAG_SAML_ASSERTION);
+        assertTrue(receivedAssertion != null);
+    }
+    
     
     /**
      * Test that creates, sends and processes an signed SAML assertion using a KeyIdentifier



---------------------------------------------------------------------
To unsubscribe, e-mail: wss4j-dev-unsubscribe@ws.apache.org
For additional commands, e-mail: wss4j-dev-help@ws.apache.org