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 2014/08/21 13:12:58 UTC

svn commit: r1619359 - in /webservices/wss4j/trunk/ws-security-dom/src: main/java/org/apache/wss4j/dom/processor/ main/java/org/apache/wss4j/dom/util/ test/java/org/apache/wss4j/dom/message/

Author: coheigea
Date: Thu Aug 21 11:12:58 2014
New Revision: 1619359

URL: http://svn.apache.org/r1619359
Log:
Improving required signed elements detection

Modified:
    webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/EncryptedDataProcessor.java
    webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/EncryptedKeyProcessor.java
    webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/ReferenceListProcessor.java
    webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/util/WSSecurityUtil.java
    webservices/wss4j/trunk/ws-security-dom/src/test/java/org/apache/wss4j/dom/message/RequireSignedEncryptedDataElementsTest.java
    webservices/wss4j/trunk/ws-security-dom/src/test/java/org/apache/wss4j/dom/message/TestMessageTransformer.java

Modified: webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/EncryptedDataProcessor.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/EncryptedDataProcessor.java?rev=1619359&r1=1619358&r2=1619359&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/EncryptedDataProcessor.java (original)
+++ webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/EncryptedDataProcessor.java Thu Aug 21 11:12:58 2014
@@ -91,7 +91,7 @@ public class EncryptedDataProcessor impl
             );
         
         if (elem != null && request.isRequireSignedEncryptedDataElements()) {
-            WSSecurityUtil.verifySignedElement(elem, elem.getOwnerDocument(), wsDocInfo.getSecurityHeader());
+            WSSecurityUtil.verifySignedElement(elem, wsDocInfo);
         }
         
         SecretKey key = null;

Modified: webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/EncryptedKeyProcessor.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/EncryptedKeyProcessor.java?rev=1619359&r1=1619358&r2=1619359&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/EncryptedKeyProcessor.java (original)
+++ webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/EncryptedKeyProcessor.java Thu Aug 21 11:12:58 2014
@@ -448,7 +448,7 @@ public class EncryptedKeyProcessor imple
         Element encryptedDataElement = 
             ReferenceListProcessor.findEncryptedDataElement(doc, docInfo, dataRefURI);
         if (encryptedDataElement != null && data.isRequireSignedEncryptedDataElements()) {
-            WSSecurityUtil.verifySignedElement(encryptedDataElement, doc, docInfo.getSecurityHeader());
+            WSSecurityUtil.verifySignedElement(encryptedDataElement, docInfo);
         }
         //
         // Prepare the SecretKey object to decrypt EncryptedData

Modified: webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/ReferenceListProcessor.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/ReferenceListProcessor.java?rev=1619359&r1=1619358&r2=1619359&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/ReferenceListProcessor.java (original)
+++ webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/ReferenceListProcessor.java Thu Aug 21 11:12:58 2014
@@ -149,7 +149,7 @@ public class ReferenceListProcessor impl
         Element encryptedDataElement = findEncryptedDataElement(doc, wsDocInfo, dataRefURI);
         
         if (encryptedDataElement != null && asymBinding && data.isRequireSignedEncryptedDataElements()) {
-            WSSecurityUtil.verifySignedElement(encryptedDataElement, doc, wsDocInfo.getSecurityHeader());
+            WSSecurityUtil.verifySignedElement(encryptedDataElement, wsDocInfo);
         }
         //
         // Prepare the SecretKey object to decrypt EncryptedData

Modified: webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/util/WSSecurityUtil.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/util/WSSecurityUtil.java?rev=1619359&r1=1619358&r2=1619359&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/util/WSSecurityUtil.java (original)
+++ webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/util/WSSecurityUtil.java Thu Aug 21 11:12:58 2014
@@ -24,6 +24,7 @@ import org.apache.wss4j.dom.SOAP12Consta
 import org.apache.wss4j.dom.SOAPConstants;
 import org.apache.wss4j.dom.WSConstants;
 import org.apache.wss4j.dom.WSDataRef;
+import org.apache.wss4j.dom.WSDocInfo;
 import org.apache.wss4j.dom.WSSecurityEngineResult;
 import org.apache.wss4j.dom.WSSConfig;
 import org.apache.wss4j.common.WSEncryptionPart;
@@ -51,10 +52,8 @@ import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
-import java.util.Set;
 
 /**
  * WS-Security Utility methods. <p/>
@@ -1238,56 +1237,44 @@ public final class WSSecurityUtil {
         }
     }
     
-    public static void verifySignedElement(Element elem, Document doc, Element securityHeader)
+    public static void verifySignedElement(Element elem, WSDocInfo wsDocInfo)
         throws WSSecurityException {
-        final Element envelope = doc.getDocumentElement();
-        final Set<String> signatureRefIDs = getSignatureReferenceIDs(securityHeader);
-        if (!signatureRefIDs.isEmpty()) {
-            Node cur = elem;
-            while (!cur.isSameNode(envelope)) {
-                if (cur.getNodeType() == Node.ELEMENT_NODE) {
-                    if (WSConstants.SIG_LN.equals(cur.getLocalName())
-                        && WSConstants.SIG_NS.equals(cur.getNamespaceURI())) {
-                        throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_CHECK,
-                        "requiredElementNotSigned", elem);
-                    } else if (isLinkedBySignatureRefs((Element)cur, signatureRefIDs)) {
-                        return;
+        List<WSSecurityEngineResult> signedResults = 
+            wsDocInfo.getResultsByTag(WSConstants.SIGN);
+        if (signedResults != null) {
+            for (WSSecurityEngineResult signedResult : signedResults) {
+                @SuppressWarnings("unchecked")
+                List<WSDataRef> dataRefs = 
+                    (List<WSDataRef>)signedResult.get(WSSecurityEngineResult.TAG_DATA_REF_URIS);
+                if (dataRefs != null) {
+                    for (WSDataRef dataRef : dataRefs) {
+                        if (isElementOrAncestorSigned(elem, dataRef.getProtectedElement())) {
+                            return;
+                        }
                     }
                 }
-                cur = cur.getParentNode();
             }
         }
+        
         throw new WSSecurityException(
             WSSecurityException.ErrorCode.FAILED_CHECK, "requiredElementNotSigned", elem);
     }
     
-    private static boolean isLinkedBySignatureRefs(Element elem, Set<String> allIDs) {
-        // Try the wsu:Id first
-        String attributeNS = elem.getAttributeNS(WSConstants.WSU_NS, "Id");
-        if (!"".equals(attributeNS) && allIDs.contains(attributeNS)) {
-            return true;
-        }
-        attributeNS = elem.getAttributeNS(null, "Id");
-        return !"".equals(attributeNS) && allIDs.contains(attributeNS);
-    }
-    
-    private static Set<String> getSignatureReferenceIDs(Element wsseHeader) throws WSSecurityException {
-        final Set<String> refs = new HashSet<String>();
-        final List<Element> signatures = WSSecurityUtil.getDirectChildElements(wsseHeader, WSConstants.SIG_LN, WSConstants.SIG_NS);
-        for (Element signature : signatures) {
-            Element sigInfo = WSSecurityUtil.getDirectChildElement(signature, WSConstants.SIG_INFO_LN, WSConstants.SIG_NS);
-            List<Element> references = WSSecurityUtil.getDirectChildElements(sigInfo, WSConstants.REF_LN, WSConstants.SIG_NS);
-            for (Element reference : references) {
-                String uri = reference.getAttributeNS(null, "URI");
-                if (!"".equals(uri)) {
-                    boolean added = refs.add(WSSecurityUtil.getIDFromReference(uri));
-                    if (!added) {
-                        LOG.warn("Duplicated reference uri: " + uri);
-                    }
-                }
+    /**
+     * Does the current element or some ancestor of it correspond to the known "signedElement"? 
+     */
+    private static boolean isElementOrAncestorSigned(Element elem, Element signedElement) 
+        throws WSSecurityException {
+        final Element envelope = elem.getOwnerDocument().getDocumentElement();
+        Node cur = elem;
+        while (!cur.isSameNode(envelope)) {
+            if (cur.getNodeType() == Node.ELEMENT_NODE && cur.equals(signedElement)) {
+                return true;
             }
+            cur = cur.getParentNode();
         }
-        return refs;
+        
+        return false;
     }
     
 }

Modified: webservices/wss4j/trunk/ws-security-dom/src/test/java/org/apache/wss4j/dom/message/RequireSignedEncryptedDataElementsTest.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-dom/src/test/java/org/apache/wss4j/dom/message/RequireSignedEncryptedDataElementsTest.java?rev=1619359&r1=1619358&r2=1619359&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-dom/src/test/java/org/apache/wss4j/dom/message/RequireSignedEncryptedDataElementsTest.java (original)
+++ webservices/wss4j/trunk/ws-security-dom/src/test/java/org/apache/wss4j/dom/message/RequireSignedEncryptedDataElementsTest.java Thu Aug 21 11:12:58 2014
@@ -228,6 +228,44 @@ public class RequireSignedEncryptedDataE
         }
     }
     
+    @org.junit.Test
+    public void testEncryptedKeyRefAndDuplicatedEncDataInWsseWrapperBody() throws Exception {
+        Document encryptedSignedDoc = getRequestDocumentEncryptionFirst();
+        RequestData reqData = getRequestData(false);
+        TestMessageTransformer.duplicateEncryptedDataInWrapperBody(encryptedSignedDoc.getDocumentElement());
+        try {
+            verify(encryptedSignedDoc, reqData);
+            fail("WSSecurityException expected");
+        } catch (WSSecurityException e) {
+            assertTrue(e.getMessage().contains("The signature or decryption was invalid"));
+        }
+        
+        encryptedSignedDoc = getRequestDocumentEncryptionFirst();
+        TestMessageTransformer.duplicateEncryptedDataInWrapperBody(encryptedSignedDoc.getDocumentElement());
+        reqData = getRequestData(true);
+        
+        try {
+            verify(encryptedSignedDoc, reqData);
+            fail("WSSecurityException expected");
+        } catch (WSSecurityException e) {
+            assertTrue(e.getMessage().contains("is not included in the signature"));
+        }
+    }
+    
+    @org.junit.Test
+    public void testEncryptedKeyRefAndDuplicatedEncDataAfterWsseWrapperBody() throws Exception {
+        Document encryptedSignedDoc = getRequestDocumentEncryptionFirst();
+        TestMessageTransformer.duplicateEncryptedDataAfterWrapperBody(encryptedSignedDoc.getDocumentElement());
+        
+        RequestData reqData = getRequestData(true);
+        try {
+            verify(encryptedSignedDoc, reqData);
+            fail("WSSecurityException expected");
+        } catch (WSSecurityException e) {
+            assertTrue(e.getMessage().contains("is not included in the signature"));
+        }
+    }
+    
     private static void checkFailure(Element attackElement, WSSecurityException e) {
         final String mex = MessageFormat.format(resources.getString("requiredElementNotSigned"), attackElement);
         assertTrue(e.getMessage().contains(mex));
@@ -278,6 +316,38 @@ public class RequireSignedEncryptedDataE
         }
         return encryptedSignedDoc;
     }
+    
+    private Document getRequestDocumentEncryptionFirst() throws Exception {
+        WSSecEncrypt encrypt = new WSSecEncrypt();
+        WSSecSignature sign = new WSSecSignature();
+        encrypt.setUserInfo("16c73ab6-b892-458f-abf5-2f875f74882e");
+        sign.setUserInfo("16c73ab6-b892-458f-abf5-2f875f74882e", "security");
+        LOG.info("Before Encryption....");
+        Document doc = SOAPUtil.toSOAPPart(SOAPMSG);
+
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);
+
+        Document signedDoc = sign.build(doc, crypto, secHeader);
+        
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("After Signing....");
+            String outputString = 
+                XMLUtils.PrettyDocumentToString(signedDoc);
+            LOG.debug(outputString);
+        }
+        
+        Document encryptedDoc = encrypt.build(signedDoc, crypto, secHeader);
+        
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("After Encryption....");
+            String outputString = 
+                XMLUtils.PrettyDocumentToString(encryptedDoc);
+            LOG.debug(outputString);
+        }
+        
+        return encryptedDoc;
+    }
 
     
     private List<WSSecurityEngineResult> verify(Document doc, RequestData reqData) throws Exception {

Modified: webservices/wss4j/trunk/ws-security-dom/src/test/java/org/apache/wss4j/dom/message/TestMessageTransformer.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-dom/src/test/java/org/apache/wss4j/dom/message/TestMessageTransformer.java?rev=1619359&r1=1619358&r2=1619359&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-dom/src/test/java/org/apache/wss4j/dom/message/TestMessageTransformer.java (original)
+++ webservices/wss4j/trunk/ws-security-dom/src/test/java/org/apache/wss4j/dom/message/TestMessageTransformer.java Thu Aug 21 11:12:58 2014
@@ -119,6 +119,78 @@ public class TestMessageTransformer exte
         print(saaj.getOwnerDocument());
         return newEncData;
     }
+    
+    public static Element duplicateEncryptedDataInWrapperBody(Element saaj) throws TransformerException {
+        Element body = getFirstChildElement(saaj, new QName("http://schemas.xmlsoap.org/soap/envelope/",
+                                                            "Body"), true);
+        Element encData = getFirstChildElement(body, new QName("http://www.w3.org/2001/04/xmlenc#",
+                                                               "EncryptedData"), true);
+        Element newEncData = createNewEncryptedData(encData);
+        Element sh = getFirstChildElement(saaj, new QName("http://schemas.xmlsoap.org/soap/envelope/",
+                                                          "Header"), true);
+        Element signature = getFirstChildElement(sh, new QName("http://www.w3.org/2000/09/xmldsig#",
+                                                               "Signature"), true);
+
+        Node wsseHeader = signature.getParentNode();
+        Node newWsseHeader = wsseHeader.cloneNode(false);
+        Node cur = wsseHeader.getFirstChild();
+        String newId = newEncData.getAttributeNS(null, "Id");
+        while (!cur.isSameNode(signature)) {
+            cur = copyHeadersAndUpdateRefList(cur, newWsseHeader, newId);
+        }
+        Element wrapper = encData.getOwnerDocument().createElementNS(null, "a");
+        wrapper.appendChild(newEncData);
+        
+        body.appendChild(wrapper);
+        while (cur != null) {
+            cur = copyHeadersAndUpdateRefList(cur, newWsseHeader, newId);
+        }
+
+        updateEncryptedKeyRefList(newWsseHeader, newId);
+
+        Node parent = wsseHeader.getParentNode();
+        parent.removeChild(wsseHeader);
+        parent.appendChild(newWsseHeader);
+        print(saaj.getOwnerDocument());
+        return newEncData;
+    }
+    
+    public static Element duplicateEncryptedDataAfterWrapperBody(Element saaj) throws TransformerException {
+        Element body = getFirstChildElement(saaj, new QName("http://schemas.xmlsoap.org/soap/envelope/",
+                                                            "Body"), true);
+        Element encData = getFirstChildElement(body, new QName("http://www.w3.org/2001/04/xmlenc#",
+                                                               "EncryptedData"), true);
+        Element newEncData = createNewEncryptedData(encData);
+        Element sh = getFirstChildElement(saaj, new QName("http://schemas.xmlsoap.org/soap/envelope/",
+                                                          "Header"), true);
+        Element signature = getFirstChildElement(sh, new QName("http://www.w3.org/2000/09/xmldsig#",
+                                                               "Signature"), true);
+
+        Node wsseHeader = signature.getParentNode();
+        Node newWsseHeader = wsseHeader.cloneNode(false);
+        Node cur = wsseHeader.getFirstChild();
+        String newId = newEncData.getAttributeNS(null, "Id");
+        while (!cur.isSameNode(signature)) {
+            cur = copyHeadersAndUpdateRefList(cur, newWsseHeader, newId);
+        }
+        Element wrapper = encData.getOwnerDocument().createElementNS(null, "a");
+        Node clonedBody = body.cloneNode(false);
+        clonedBody.appendChild(newEncData);
+        wrapper.appendChild(clonedBody);
+        
+        body.getParentNode().appendChild(wrapper);
+        while (cur != null) {
+            cur = copyHeadersAndUpdateRefList(cur, newWsseHeader, newId);
+        }
+
+        updateEncryptedKeyRefList(newWsseHeader, newId);
+
+        Node parent = wsseHeader.getParentNode();
+        parent.removeChild(wsseHeader);
+        parent.appendChild(newWsseHeader);
+        print(saaj.getOwnerDocument());
+        return newEncData;
+    }
 
     public static Element duplicateEncryptedDataInExternalWrapperElement(Element saaj,
                                                                          boolean moveReferenceList) throws TransformerException {