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-unsubscr...@ws.apache.org For additional commands, e-mail: wss4j-dev-h...@ws.apache.org