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 =