You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by se...@apache.org on 2011/08/12 22:14:37 UTC

svn commit: r1157233 - in /cxf/trunk: rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/xml/ systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/xml/

Author: sergeyb
Date: Fri Aug 12 20:14:37 2011
New Revision: 1157233

URL: http://svn.apache.org/viewvc?rev=1157233&view=rev
Log:
[CXF-3661] Support for enveloping signatures

Modified:
    cxf/trunk/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/xml/XmlSigInHandler.java
    cxf/trunk/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/xml/XmlSigOutInterceptor.java
    cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/xml/JAXRSXmlSecTest.java

Modified: cxf/trunk/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/xml/XmlSigInHandler.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/xml/XmlSigInHandler.java?rev=1157233&r1=1157232&r2=1157233&view=diff
==============================================================================
--- cxf/trunk/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/xml/XmlSigInHandler.java (original)
+++ cxf/trunk/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/xml/XmlSigInHandler.java Fri Aug 12 20:14:37 2011
@@ -30,9 +30,9 @@ import javax.xml.stream.XMLStreamReader;
 
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
+import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
 
-
 import org.apache.cxf.common.logging.LogUtils;
 import org.apache.cxf.helpers.DOMUtils;
 import org.apache.cxf.jaxrs.ext.RequestHandler;
@@ -133,9 +133,15 @@ public class XmlSigInHandler implements 
         if (!valid) {
             throwFault("Signature validation failed", null);
         }
-        
-        root.removeAttribute("ID");
-        root.removeChild(sigElement);
+        if (!isEnveloping(root)) {
+            root.removeAttribute("ID");
+            root.removeChild(sigElement);
+        } else {
+            Element actualBody = getActualBody(root);
+            Document newDoc = DOMUtils.createDocument();
+            newDoc.adoptNode(actualBody);
+            root = actualBody;
+        }
         message.setContent(XMLStreamReader.class, 
                            new W3CDOMStreamReader(root));
         message.setContent(InputStream.class, null);
@@ -148,10 +154,40 @@ public class XmlSigInHandler implements 
         return null;
     }
     
+    private Element getActualBody(Element envelopingSigElement) {
+        Element objectNode = getNode(envelopingSigElement, Constants.SignatureSpecNS, "Object", 0);
+        if (objectNode == null) {
+            throwFault("Object envelope is not available", null);
+        }
+        NodeList list = objectNode.getChildNodes();
+        for (int i = 0; i < list.getLength(); i++) {
+            Node node = list.item(i);
+            if (node instanceof Element) {
+                objectNode.removeChild(node);
+                return (Element)node;
+            }
+        }
+        throwFault("No signed data is found", null);
+        return null;
+       
+    }
+    
     private Element getSignatureElement(Element root) {
-        NodeList list = root.getElementsByTagNameNS(Constants.SignatureSpecNS, "Signature");
-        if (list != null && list.getLength() == 1) {
-            return (Element)list.item(0);
+        if (isEnveloping(root)) {    
+            return root;
+        }
+        return getNode(root, Constants.SignatureSpecNS, "Signature", 0);
+    }
+    
+    protected boolean isEnveloping(Element root) {
+        return Constants.SignatureSpecNS.equals(root.getNamespaceURI())
+                && "Signature".equals(root.getLocalName());
+    }
+    
+    private Element getNode(Element parent, String ns, String name, int index) {
+        NodeList list = parent.getElementsByTagNameNS(ns, name);
+        if (list != null && list.getLength() >= index + 1) {
+            return (Element)list.item(index);
         } 
         return null;
     }
@@ -175,16 +211,16 @@ public class XmlSigInHandler implements 
         } catch (XMLSecurityException ex) {
             throwFault("Signature Reference is not available", ex);
         }
-        String rootId = root.getAttribute("ID");
-        String refId = ref.getId();
-        if (refId.length() == 0 && rootId.length() == 0) {
-            // or fragment must be expected ?
-            return;
-        }
-        if (refId.startsWith("#") && refId.length() > 1 && refId.substring(1).equals(rootId)) {
-            return;
-        } else {
-            throwFault("Signature Reference ID is invalid", null);
+        if (!isEnveloping(root)) {
+            String rootId = root.getAttribute("ID");
+            String refId = ref.getURI();
+            if (refId.length() == 0 && rootId.length() == 0) {
+                // or fragment must be expected ?
+                return;
+            }
+            if (!refId.startsWith("#") || refId.length() <= 1 || !refId.substring(1).equals(rootId)) {
+                throwFault("Signature Reference ID is invalid", null);
+            }
         }
         Transforms transforms = null;
         try {
@@ -192,20 +228,22 @@ public class XmlSigInHandler implements 
         } catch (XMLSecurityException ex) {
             throwFault("Signature transforms can not be obtained", ex);
         }
-        boolean isEnveloped = false;
-        for (int i = 0; i < transforms.getLength(); i++) {
-            try {
-                Transform tr = transforms.item(i);
-                if (Transforms.TRANSFORM_ENVELOPED_SIGNATURE.equals(tr.getURI())) {
-                    isEnveloped = true;
-                    break;
+        if (!isEnveloping(root)) {
+            boolean isEnveloped = false;
+            for (int i = 0; i < transforms.getLength(); i++) {
+                try {
+                    Transform tr = transforms.item(i);
+                    if (Transforms.TRANSFORM_ENVELOPED_SIGNATURE.equals(tr.getURI())) {
+                        isEnveloped = true;
+                        break;
+                    }
+                } catch (Exception ex) {
+                    throwFault("Problem accessing Transform instance", ex);    
                 }
-            } catch (Exception ex) {
-                throwFault("Problem accessing Transform instance", ex);    
             }
-        }
-        if (!isEnveloped) {
-            throwFault("Only enveloped signatures are currently supported", null);
+            if (!isEnveloped) {
+                throwFault("Only enveloped signatures are currently supported", null);
+            }
         }
     }
 }

Modified: cxf/trunk/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/xml/XmlSigOutInterceptor.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/xml/XmlSigOutInterceptor.java?rev=1157233&r1=1157232&r2=1157233&view=diff
==============================================================================
--- cxf/trunk/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/xml/XmlSigOutInterceptor.java (original)
+++ cxf/trunk/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/xml/XmlSigOutInterceptor.java Fri Aug 12 20:14:37 2011
@@ -24,9 +24,12 @@ import java.util.UUID;
 import java.util.logging.Logger;
 
 import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
 
 import org.apache.cxf.common.logging.LogUtils;
 import org.apache.cxf.common.util.StringUtils;
+import org.apache.cxf.helpers.DOMUtils;
 import org.apache.cxf.message.Message;
 import org.apache.cxf.rs.security.common.CryptoLoader;
 import org.apache.cxf.rs.security.common.SecurityUtils;
@@ -37,7 +40,6 @@ import org.apache.ws.security.components
 import org.apache.xml.security.signature.XMLSignature;
 import org.apache.xml.security.transforms.Transforms;
 import org.apache.xml.security.utils.Constants;
-import org.apache.xml.security.utils.ElementProxy;
 import org.opensaml.xml.signature.SignatureConstants;
 
 
@@ -45,13 +47,17 @@ public class XmlSigOutInterceptor extend
     private static final Logger LOG = 
         LogUtils.getL7dLogger(XmlSigOutInterceptor.class);
     
-    private boolean createReferenceId = true;
+    private boolean enveloping;
     private String defaultSigAlgo = SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA1;
     private String digestAlgo = Constants.ALGO_ID_DIGEST_SHA1;
     
     public XmlSigOutInterceptor() {
     } 
 
+    public void setEnveloping(boolean env) {
+        this.enveloping = env;
+    }
+    
     public void setSignatureAlgorithm(String algo) {
         defaultSigAlgo = algo;
     }
@@ -60,18 +66,14 @@ public class XmlSigOutInterceptor extend
         digestAlgo = algo;
     }
     
-    public void setCreateReferenceId(boolean create) {
-        createReferenceId = create;
-    }
     
     protected Document processDocument(Message message, Document doc) 
         throws Exception {
-        createEnvelopedSignature(message, doc);
-        return doc;
+        return createEnvelopedSignature(message, doc);
     }
     
     // enveloping & detached sigs will be supported too
-    private void createEnvelopedSignature(Message message, Document doc) 
+    private Document createEnvelopedSignature(Message message, Document doc) 
         throws Exception {
         
         String userNameKey = SecurityConstants.SIGNATURE_USERNAME;
@@ -89,7 +91,7 @@ public class XmlSigOutInterceptor extend
         String user = SecurityUtils.getUserName(message, crypto, userNameKey);
          
         if (StringUtils.isEmpty(user)) {
-            return;
+            return null;
         }
 
         String password = 
@@ -110,28 +112,60 @@ public class XmlSigOutInterceptor extend
             LOG.severe(errorMessage);
             throw new WSSecurityException(errorMessage, ex);
         }
-        //
-        ElementProxy.setDefaultPrefix(Constants.SignatureSpecNS, "ds");
         
-        String referenceId = "";
-        if (createReferenceId) {
-            String id = UUID.randomUUID().toString();
-            referenceId = "#" + id;
-            doc.getDocumentElement().setAttribute("ID", id);    
-        }
+        String id = UUID.randomUUID().toString();
+        String referenceId = "#" + id;
         
-        XMLSignature sig = new XMLSignature(doc, "", sigAlgo);
-        doc.getDocumentElement().appendChild(sig.getElement());
-        Transforms transforms = new Transforms(doc);
-        transforms.addTransform(Transforms.TRANSFORM_ENVELOPED_SIGNATURE);
-        transforms.addTransform(Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS);
+        XMLSignature sig = null;
+        if (enveloping) {
+            sig = prepareEnvelopingSignature(doc, id, referenceId, sigAlgo);
+        } else {
+            sig = prepareEnvelopedSignature(doc, id, referenceId, sigAlgo);
+        }
         
-        sig.addDocument("", transforms, digestAlgo, referenceId, null);
         
         sig.addKeyInfo(issuerCerts[0]);
         sig.addKeyInfo(issuerCerts[0].getPublicKey());
         sig.sign(privateKey);
+        return sig.getElement().getOwnerDocument();
     }
     
+    private XMLSignature prepareEnvelopingSignature(Document doc, 
+                                                    String id, 
+                                                    String referenceId,
+                                                    String sigAlgo) throws Exception {
+        Element docEl = doc.getDocumentElement();
+        Document newDoc = DOMUtils.createDocument();
+        doc.removeChild(docEl);
+        newDoc.adoptNode(docEl);
+        Element object = newDoc.createElementNS(Constants.SignatureSpecNS, "ds:Object");
+        object.appendChild(docEl);
+        object.setAttribute("ID", id);
+        
+        XMLSignature sig = new XMLSignature(newDoc, "", sigAlgo);
+        newDoc.appendChild(sig.getElement());
+        sig.getElement().appendChild(object);
         
+        Transforms transforms = new Transforms(newDoc);
+        transforms.addTransform(Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS);
+        
+        sig.addDocument(referenceId, transforms, digestAlgo);
+        return sig;
+    }
+    
+    private XMLSignature prepareEnvelopedSignature(Document doc, 
+            String id, 
+            String referenceURI,
+            String sigAlgo) throws Exception {
+        doc.getDocumentElement().setAttribute("ID", id);    
+    
+        XMLSignature sig = new XMLSignature(doc, "", sigAlgo);
+        doc.getDocumentElement().appendChild(sig.getElement());
+        Transforms transforms = new Transforms(doc);
+        transforms.addTransform(Transforms.TRANSFORM_ENVELOPED_SIGNATURE);
+        transforms.addTransform(Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS);
+        
+        sig.addDocument(referenceURI, transforms, digestAlgo);
+        return sig;
+    }
 }

Modified: cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/xml/JAXRSXmlSecTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/xml/JAXRSXmlSecTest.java?rev=1157233&r1=1157232&r2=1157233&view=diff
==============================================================================
--- cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/xml/JAXRSXmlSecTest.java (original)
+++ cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/xml/JAXRSXmlSecTest.java Fri Aug 12 20:14:37 2011
@@ -50,6 +50,16 @@ public class JAXRSXmlSecTest extends Abs
     @Test
     public void testPostBookWithEnvelopedSig() throws Exception {
         String address = "https://localhost:" + PORT + "/xmlsig/bookstore/books";
+        doTestSignature(address, false);
+    }
+    
+    @Test
+    public void testPostBookWithEnvelopingSig() throws Exception {
+        String address = "https://localhost:" + PORT + "/xmlsig/bookstore/books";
+        doTestSignature(address, true);
+    }
+    
+    private void doTestSignature(String address, boolean enveloping) {
         JAXRSClientFactoryBean bean = new JAXRSClientFactoryBean();
         bean.setAddress(address);
         
@@ -65,7 +75,9 @@ public class JAXRSXmlSecTest extends Abs
         properties.put("ws-security.signature.properties", 
                        "org/apache/cxf/systest/jaxrs/security/alice.properties");
         bean.setProperties(properties);
-        bean.getOutInterceptors().add(new XmlSigOutInterceptor());
+        XmlSigOutInterceptor sigInterceptor = new XmlSigOutInterceptor();
+        sigInterceptor.setEnveloping(enveloping);
+        bean.getOutInterceptors().add(sigInterceptor);
         
         
         WebClient wc = bean.createWebClient();
@@ -81,7 +93,6 @@ public class JAXRSXmlSecTest extends Abs
                 fail(ex.getMessage());
             }
         }
-        
     }
     
     @Test