You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ws.apache.org by co...@apache.org on 2015/12/21 16:02:19 UTC
svn commit: r1721177 - in
/webservices/wss4j/branches/2_1_x-fixes/ws-security-dom/src:
main/java/org/apache/wss4j/dom/processor/
test/java/org/apache/wss4j/dom/saml/
Author: coheigea
Date: Mon Dec 21 15:02:19 2015
New Revision: 1721177
URL: http://svn.apache.org/viewvc?rev=1721177&view=rev
Log:
[WSS-562] - Support processing EncryptedAssertions that contain EncryptedKey children
Modified:
webservices/wss4j/branches/2_1_x-fixes/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/EncryptedAssertionProcessor.java
webservices/wss4j/branches/2_1_x-fixes/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/EncryptedDataProcessor.java
webservices/wss4j/branches/2_1_x-fixes/ws-security-dom/src/test/java/org/apache/wss4j/dom/saml/SamlTokenTest.java
Modified: webservices/wss4j/branches/2_1_x-fixes/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/EncryptedAssertionProcessor.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/branches/2_1_x-fixes/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/EncryptedAssertionProcessor.java?rev=1721177&r1=1721176&r2=1721177&view=diff
==============================================================================
--- webservices/wss4j/branches/2_1_x-fixes/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/EncryptedAssertionProcessor.java (original)
+++ webservices/wss4j/branches/2_1_x-fixes/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/EncryptedAssertionProcessor.java Mon Dec 21 15:02:19 2015
@@ -20,21 +20,23 @@
package org.apache.wss4j.dom.processor;
import java.util.Collections;
+import java.util.LinkedList;
import java.util.List;
import javax.xml.namespace.QName;
import org.w3c.dom.Element;
+import org.w3c.dom.Node;
import org.apache.wss4j.common.ext.WSSecurityException;
import org.apache.wss4j.common.util.XMLUtils;
import org.apache.wss4j.dom.WSConstants;
+import org.apache.wss4j.dom.WSDataRef;
import org.apache.wss4j.dom.WSDocInfo;
import org.apache.wss4j.dom.engine.WSSecurityEngineResult;
import org.apache.wss4j.dom.handler.RequestData;
/**
- * This will process incoming <code>saml2:EncryptedAssertion</code> elements. EncryptedKey
- * children are not supported, only an EncryptedData structure.
+ * This will process incoming <code>saml2:EncryptedAssertion</code> elements.
*/
public class EncryptedAssertionProcessor implements Processor {
@@ -57,6 +59,57 @@ public class EncryptedAssertionProcessor
return Collections.emptyList();
}
+ List<WSSecurityEngineResult> completeResults = new LinkedList<>();
+
+ // Check all EncryptedKey elements
+ for (Node currentChild = elem.getFirstChild();
+ currentChild != null;
+ currentChild = currentChild.getNextSibling()
+ ) {
+ if (Node.ELEMENT_NODE == currentChild.getNodeType()
+ && "EncryptedKey".equals(currentChild.getLocalName())
+ && WSConstants.ENC_NS.equals(currentChild.getNamespaceURI())) {
+ QName el =
+ new QName(((Element)currentChild).getNamespaceURI(),
+ ((Element)currentChild).getLocalName());
+ Processor proc = request.getWssConfig().getProcessor(el);
+ if (proc != null) {
+ completeResults.addAll(proc.handleToken(((Element)currentChild), request, wsDocInfo));
+ }
+ }
+ }
+
+ // If we have processed EncryptedKey elements, then the Assertion is already decrypted
+ // at this point. Process it accordingly.
+ if (!completeResults.isEmpty()) {
+ for (WSSecurityEngineResult r : completeResults) {
+ List<WSDataRef> dataRefs =
+ (List<WSDataRef>)r.get(WSSecurityEngineResult.TAG_DATA_REF_URIS);
+ if (dataRefs != null) {
+ for (WSDataRef dataRef : dataRefs) {
+ if (WSConstants.SAML_TOKEN.equals(dataRef.getName())
+ || WSConstants.SAML2_TOKEN.equals(dataRef.getName())) {
+ // Get hold of the plain text element
+ Element decryptedElem = dataRef.getProtectedElement();
+ QName el = new QName(decryptedElem.getNamespaceURI(), decryptedElem.getLocalName());
+ Processor proc = request.getWssConfig().getProcessor(el);
+ if (proc != null) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Processing decrypted element with: " + proc.getClass().getName());
+ }
+ List<WSSecurityEngineResult> results =
+ proc.handleToken(decryptedElem, request, wsDocInfo);
+ completeResults.addAll(0, results);
+ return completeResults;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Otherwise decrypt the element ourselves
+
// Type must be "Element" if specified
String typeStr = encryptedDataElement.getAttributeNS(null, "Type");
if (typeStr != null && !(WSConstants.ENC_NS + "Element").equals(typeStr)) {
Modified: webservices/wss4j/branches/2_1_x-fixes/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/EncryptedDataProcessor.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/branches/2_1_x-fixes/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/EncryptedDataProcessor.java?rev=1721177&r1=1721176&r2=1721177&view=diff
==============================================================================
--- webservices/wss4j/branches/2_1_x-fixes/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/EncryptedDataProcessor.java (original)
+++ webservices/wss4j/branches/2_1_x-fixes/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/EncryptedDataProcessor.java Mon Dec 21 15:02:19 2015
@@ -93,6 +93,10 @@ public class EncryptedDataProcessor impl
XMLUtils.getDirectChildElement(
kiElem, WSConstants.ENC_KEY_LN, WSConstants.ENC_NS
);
+ Element retrievalMethodElement =
+ XMLUtils.getDirectChildElement(
+ kiElem, "RetrievalMethod", WSConstants.SIG_NS
+ );
if (request.isRequireSignedEncryptedDataElements()) {
List<WSSecurityEngineResult> signedResults =
@@ -124,6 +128,16 @@ public class EncryptedDataProcessor impl
byte[] symmKey =
(byte[])encrKeyResults.get(0).get(WSSecurityEngineResult.TAG_SECRET);
key = KeyUtils.prepareSecretKey(symEncAlgo, symmKey);
+ } else if (retrievalMethodElement != null
+ && "http://www.w3.org/2001/04/xmlenc#EncryptedKey".equals(
+ retrievalMethodElement.getAttributeNS(null, "Type"))) {
+ String uri = retrievalMethodElement.getAttributeNS(null, "URI");
+ uri = XMLUtils.getIDFromReference(uri);
+ WSSecurityEngineResult result = wsDocInfo.getResult(uri);
+ if (result != null) {
+ byte[] symmKey = (byte[])result.get(WSSecurityEngineResult.TAG_SECRET);
+ key = KeyUtils.prepareSecretKey(symEncAlgo, symmKey);
+ }
} else {
throw new WSSecurityException(
WSSecurityException.ErrorCode.UNSUPPORTED_ALGORITHM, "noEncKey"
Modified: webservices/wss4j/branches/2_1_x-fixes/ws-security-dom/src/test/java/org/apache/wss4j/dom/saml/SamlTokenTest.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/branches/2_1_x-fixes/ws-security-dom/src/test/java/org/apache/wss4j/dom/saml/SamlTokenTest.java?rev=1721177&r1=1721176&r2=1721177&view=diff
==============================================================================
--- webservices/wss4j/branches/2_1_x-fixes/ws-security-dom/src/test/java/org/apache/wss4j/dom/saml/SamlTokenTest.java (original)
+++ webservices/wss4j/branches/2_1_x-fixes/ws-security-dom/src/test/java/org/apache/wss4j/dom/saml/SamlTokenTest.java Mon Dec 21 15:02:19 2015
@@ -67,9 +67,13 @@ import org.apache.wss4j.dom.message.WSSe
import org.apache.wss4j.dom.validate.SamlAssertionValidator;
import org.apache.xml.security.encryption.EncryptedData;
import org.apache.xml.security.encryption.EncryptedKey;
+import org.apache.xml.security.encryption.Reference;
+import org.apache.xml.security.encryption.ReferenceList;
import org.apache.xml.security.encryption.XMLCipher;
import org.apache.xml.security.keys.KeyInfo;
+import org.apache.xml.security.keys.content.RetrievalMethod;
import org.apache.xml.security.keys.content.X509Data;
+import org.apache.xml.security.stax.impl.util.IDGenerator;
import org.joda.time.DateTime;
import org.junit.Test;
import org.opensaml.core.xml.XMLObjectBuilder;
@@ -762,6 +766,119 @@ public class SamlTokenTest extends org.j
WSHandlerResult results = secEngine.processSecurityHeader(doc, requestData);
WSSecurityEngineResult actionResult =
+ results.getActionResults().get(WSConstants.ST_UNSIGNED).get(0);
+
+ SamlAssertionWrapper receivedSamlAssertion =
+ (SamlAssertionWrapper) actionResult.get(WSSecurityEngineResult.TAG_SAML_ASSERTION);
+ assertTrue(receivedSamlAssertion != null);
+ assertTrue(receivedSamlAssertion.getElement() != null);
+ assertTrue("Assertion".equals(receivedSamlAssertion.getElement().getLocalName()));
+
+ actionResult = results.getActionResults().get(WSConstants.ENCR).get(0);
+ assertTrue(actionResult != null);
+ }
+
+ @Test
+ public void testSAML2EncryptedAssertionViaSeparateEncryptedKey() throws Exception {
+ SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
+ callbackHandler.setStatement(SAML2CallbackHandler.Statement.AUTHN);
+ callbackHandler.setIssuer("www.example.com");
+
+ SAMLCallback samlCallback = new SAMLCallback();
+ SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
+ SamlAssertionWrapper samlAssertion = new SamlAssertionWrapper(samlCallback);
+
+ WSSecSAMLToken wsSign = new WSSecSAMLToken();
+
+ Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
+ WSSecHeader secHeader = new WSSecHeader(doc);
+ secHeader.insertSecurityHeader();
+
+ wsSign.prepare(doc, samlAssertion);
+
+ // Get the Element + add it to the security header as an EncryptedAssertion
+ Element assertionElement = wsSign.getElement();
+ Element encryptedAssertionElement =
+ doc.createElementNS(WSConstants.SAML2_NS, WSConstants.ENCRYPED_ASSERTION_LN);
+ encryptedAssertionElement.appendChild(assertionElement);
+ secHeader.getSecurityHeader().appendChild(encryptedAssertionElement);
+
+ // Encrypt the Assertion
+ KeyGenerator keygen = KeyGenerator.getInstance("AES");
+ keygen.init(128);
+ SecretKey secretKey = keygen.generateKey();
+ Crypto crypto = CryptoFactory.getInstance("wss40.properties");
+ CryptoType cryptoType = new CryptoType(CryptoType.TYPE.ALIAS);
+ cryptoType.setAlias("wss40");
+ X509Certificate[] certs = crypto.getX509Certificates(cryptoType);
+ assertTrue(certs != null && certs.length > 0 && certs[0] != null);
+
+ XMLCipher cipher = XMLCipher.getInstance(WSConstants.AES_128);
+ cipher.init(XMLCipher.ENCRYPT_MODE, secretKey);
+
+ // Create a KeyInfo for the EncryptedData
+ EncryptedData builder = cipher.getEncryptedData();
+ KeyInfo builderKeyInfo = builder.getKeyInfo();
+ if (builderKeyInfo == null) {
+ builderKeyInfo = new KeyInfo(doc);
+ builderKeyInfo.getElement().setAttributeNS(
+ "http://www.w3.org/2000/xmlns/", "xmlns:dsig",
+ "http://www.w3.org/2000/09/xmldsig#"
+ );
+ builder.setKeyInfo(builderKeyInfo);
+ }
+ String encryptedKeyId = IDGenerator.generateID(null);
+ RetrievalMethod retrievalMethod = new RetrievalMethod(doc, "#" + encryptedKeyId,
+ null, "http://www.w3.org/2001/04/xmlenc#EncryptedKey");
+ builderKeyInfo.add(retrievalMethod);
+
+ cipher.doFinal(doc, assertionElement, false);
+
+ String id = IDGenerator.generateID(null);
+ Element encryptedData =
+ (Element)encryptedAssertionElement.getElementsByTagNameNS(WSConstants.ENC_NS, "EncryptedData").item(0);
+ encryptedData.setAttributeNS(null, "Id", id);
+
+ XMLCipher newCipher = XMLCipher.getInstance(WSConstants.KEYTRANSPORT_RSAOEP);
+ newCipher.init(XMLCipher.WRAP_MODE, certs[0].getPublicKey());
+ EncryptedKey encryptedKey = newCipher.encryptKey(doc, secretKey);
+
+ KeyInfo encryptedKeyKeyInfo = encryptedKey.getKeyInfo();
+ if (encryptedKeyKeyInfo == null) {
+ encryptedKeyKeyInfo = new KeyInfo(doc);
+ encryptedKeyKeyInfo.getElement().setAttributeNS(
+ "http://www.w3.org/2000/xmlns/", "xmlns:dsig", "http://www.w3.org/2000/09/xmldsig#"
+ );
+ encryptedKey.setKeyInfo(encryptedKeyKeyInfo);
+ }
+ X509Data x509Data = new X509Data(doc);
+ x509Data.addIssuerSerial(certs[0].getIssuerX500Principal().getName(),
+ certs[0].getSerialNumber());
+ encryptedKeyKeyInfo.add(x509Data);
+
+ ReferenceList referenceList = newCipher.createReferenceList(ReferenceList.DATA_REFERENCE);
+ Reference reference = referenceList.newDataReference("#" + id);
+ referenceList.add(reference);
+ encryptedKey.setReferenceList(referenceList);
+ Element encryptedKeyElement = newCipher.martial(encryptedKey);
+ encryptedKeyElement.setAttributeNS(null, "Id", encryptedKeyId);
+ encryptedAssertionElement.appendChild(encryptedKeyElement);
+
+ if (LOG.isDebugEnabled()) {
+ String outputString =
+ XMLUtils.PrettyDocumentToString(doc);
+ LOG.debug(outputString);
+ }
+
+ RequestData requestData = new RequestData();
+ requestData.setValidateSamlSubjectConfirmation(false);
+ requestData.setCallbackHandler(new KeystoreCallbackHandler());
+ requestData.setDecCrypto(crypto);
+ requestData.setSigVerCrypto(crypto);
+ requestData.setDisableBSPEnforcement(true);
+ WSHandlerResult results = secEngine.processSecurityHeader(doc, requestData);
+
+ WSSecurityEngineResult actionResult =
results.getActionResults().get(WSConstants.ST_UNSIGNED).get(0);
SamlAssertionWrapper receivedSamlAssertion =