[jboss-cvs] Picketlink SVN: r479 - in trust/trunk/jbossws-native/src/main/java/org/picketlink/trust/jbossws: handler and 1 other directory.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Fri Oct 15 12:08:26 EDT 2010


Author: alessio.soldano at jboss.com
Date: 2010-10-15 12:08:25 -0400 (Fri, 15 Oct 2010)
New Revision: 479

Added:
   trust/trunk/jbossws-native/src/main/java/org/picketlink/trust/jbossws/Constants.java
   trust/trunk/jbossws-native/src/main/java/org/picketlink/trust/jbossws/Util.java
Modified:
   trust/trunk/jbossws-native/src/main/java/org/picketlink/trust/jbossws/handler/SAML2Handler.java
Log:
Removing jbossws-native specific references from the SAML2Handler and prevent DOM exception when the assertion element does not come from the same document as the SOAP message


Added: trust/trunk/jbossws-native/src/main/java/org/picketlink/trust/jbossws/Constants.java
===================================================================
--- trust/trunk/jbossws-native/src/main/java/org/picketlink/trust/jbossws/Constants.java	                        (rev 0)
+++ trust/trunk/jbossws-native/src/main/java/org/picketlink/trust/jbossws/Constants.java	2010-10-15 16:08:25 UTC (rev 479)
@@ -0,0 +1,76 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2010, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.picketlink.trust.jbossws;
+
+import javax.xml.namespace.QName;
+
+import org.apache.xml.security.utils.EncryptionConstants;
+
+/**
+ * @author Jason T. Greene
+ */
+public class Constants
+{
+   public static final String WSS_SOAP_NS = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0";
+
+   public static final String JBOSS_WSSE_NS = "http://www.jboss.com/jbossws/ws-security";
+
+   public static final String JBOSS_WSSE_PREFIX = "jboss-wsse";
+
+   public static final String WSSE_PREFIX = "wsse";
+
+   public static final String WSSE_NS = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";
+
+   public static final String WSU_PREFIX = "wsu";
+
+   public static final String WSU_NS = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd";
+
+   public static final String XML_SIGNATURE_NS = org.apache.xml.security.utils.Constants.SignatureSpecNS;
+
+   public static final String XML_ENCRYPTION_NS = EncryptionConstants.EncryptionSpecNS;
+
+   public static final String XML_ENCRYPTION_PREFIX = "ds"; //xmlsec 1.4.2 requires this to be "ds" to correctly create KeyInfo elements
+
+   public static final String ID = "Id";
+
+   public static final String WSU_ID = WSU_PREFIX + ":" + ID;
+
+   public static final String BASE64_ENCODING_TYPE = WSS_SOAP_NS + "#Base64Binary";
+   
+   public static final String PASSWORD_TEXT_TYPE = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText";
+   
+   public static final String PASSWORD_DIGEST_TYPE = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest";
+
+   public static final String WSSE_HEADER = WSSE_PREFIX + ":Security";
+
+   public static final String XMLNS_NS = "http://www.w3.org/2000/xmlns/";
+
+   public static final String XENC_DATAREFERENCE = "DataReference";
+
+   public static final String XENC_REFERENCELIST = "ReferenceList";
+
+   public static final String XENC_ELEMENT_TYPE = EncryptionConstants.TYPE_ELEMENT;
+
+   public static final String XENC_CONTENT_TYPE = EncryptionConstants.TYPE_CONTENT;
+   
+   public static final QName WSSE_HEADER_QNAME = new QName(WSSE_NS, "Security");
+}

Added: trust/trunk/jbossws-native/src/main/java/org/picketlink/trust/jbossws/Util.java
===================================================================
--- trust/trunk/jbossws-native/src/main/java/org/picketlink/trust/jbossws/Util.java	                        (rev 0)
+++ trust/trunk/jbossws-native/src/main/java/org/picketlink/trust/jbossws/Util.java	2010-10-15 16:08:25 UTC (rev 479)
@@ -0,0 +1,216 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2010, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.picketlink.trust.jbossws;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.namespace.QName;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+/**
+ * @author Jason T. Greene
+ */
+public class Util
+{
+   public static int count = 0;
+   
+   public static String assignWsuId(Element element)
+   {
+      String id = element.getAttributeNS(Constants.WSU_NS, Constants.ID);
+
+      if (id == null || id.length() < 1)
+      {
+         id = generateId();
+         element.setAttributeNS(Constants.WSU_NS, Constants.WSU_ID, id);
+         addNamespace(element, Constants.WSU_PREFIX, Constants.WSU_NS);
+      }
+
+      return id;
+   }
+
+   public static Element getFirstChildElement(Node node)
+   {
+      Node child = node.getFirstChild();
+      while (child != null && child.getNodeType() != Node.ELEMENT_NODE)
+         child = child.getNextSibling();
+
+      return (Element)child;
+   }
+
+   public static Element getNextSiblingElement(Element element)
+   {
+      Node sibling = element.getNextSibling();
+      while (sibling != null && sibling.getNodeType() != Node.ELEMENT_NODE)
+         sibling = sibling.getNextSibling();
+
+      return (Element)sibling;
+   }
+
+   public static Element getPreviousSiblingElement(Element element)
+   {
+      Node sibling = element.getPreviousSibling();
+      while (sibling != null && sibling.getNodeType() != Node.ELEMENT_NODE)
+         sibling = sibling.getPreviousSibling();
+
+      return (Element)sibling;
+   }
+
+   public static Element findElement(Element root, String localName, String namespace)
+   {
+      return findElement(root, new QName(namespace, localName));
+   }
+
+   public static Element findElement(Element root, QName name)
+   {
+      // Here lies your standard recusive DFS.....
+      if (matchNode(root, name))
+         return root;
+
+      // Search children
+      for (Node child = root.getFirstChild(); child != null; child = child.getNextSibling())
+      {
+         if (child.getNodeType() != Node.ELEMENT_NODE)
+            continue;
+
+         Node possibleMatch = findElement((Element)child, name);
+         if (possibleMatch != null)
+            return (Element)possibleMatch;
+      }
+
+      return null;
+   }
+
+   public static List<Node> findAllElements(Element root, QName name, boolean local)
+   {
+      List<Node> list = new ArrayList<Node>();
+      if (matchNode(root, name, local))
+         list.add(root);
+
+      for (Node child = root.getFirstChild(); child != null; child = child.getNextSibling())
+      {
+         if (child.getNodeType() != Node.ELEMENT_NODE)
+            continue;
+
+         list.addAll(findAllElements((Element) child, name, local));
+      }
+
+      return list;
+   }
+
+   public static Element findElementByWsuId(Element root, String id)
+   {
+      // Here lies another standard recusive DFS.....
+      if (id.equals(getWsuId(root)))
+         return root;
+
+      // Search children
+      for (Node child = root.getFirstChild(); child != null; child = child.getNextSibling())
+      {
+         if (child.getNodeType() != Node.ELEMENT_NODE)
+            continue;
+
+         Node possibleMatch = findElementByWsuId((Element)child, id);
+         if (possibleMatch != null)
+            return (Element)possibleMatch;
+      }
+
+      return null;
+   }
+
+   public static Element findOrCreateSoapHeader(Element envelope)
+   {
+      String prefix = envelope.getPrefix();
+      String uri = envelope.getNamespaceURI();
+      QName name = new QName(uri, "Header");
+      Element header = findElement(envelope, name);
+      if (header == null)
+      {
+         header = envelope.getOwnerDocument().createElementNS(uri, prefix + ":Header");
+         envelope.insertBefore(header, envelope.getFirstChild());
+      }
+
+      return header;
+   }
+
+   public static String getWsuId(Element element)
+   {
+      if (element.hasAttributeNS(Constants.WSU_NS, Constants.ID))
+         return element.getAttributeNS(Constants.WSU_NS, Constants.ID);
+
+      if (element.hasAttribute(Constants.ID))
+      {
+         String ns = element.getNamespaceURI();
+         if (Constants.XML_SIGNATURE_NS.equals(ns) || Constants.XML_ENCRYPTION_NS.equals(ns))
+            return element.getAttribute(Constants.ID);
+      }
+
+      return null;
+   }
+
+   public static boolean equalStrings(String string1, String string2)
+   {
+      if (string1 == null && string2 == null)
+         return true;
+
+      return string1 != null && string1.equals(string2);
+   }
+
+   public static boolean matchNode(Node node, QName name)
+   {
+      return matchNode(node, name, false);
+   }
+
+   public static boolean matchNode(Node node, QName name, boolean local)
+   {
+      return equalStrings(node.getLocalName(), name.getLocalPart())
+          && (local || equalStrings(node.getNamespaceURI(), name.getNamespaceURI()));
+   }
+
+   public static String generateId()
+   {
+      return generateId("element");
+   }
+
+   public static void addNamespace(Element element, String prefix, String uri)
+   {
+      element.setAttributeNS(Constants.XMLNS_NS, "xmlns:" + prefix, uri);
+   }
+
+   public static String generateId(String prefix)
+   {
+      StringBuilder id = new StringBuilder();
+      long time = System.currentTimeMillis();
+
+      // reasonably gaurantee uniqueness
+      synchronized (Util.class)
+      {
+         count++;
+      }
+
+      id.append(prefix).append("-").append(count).append("-").append(time).append("-").append(id.hashCode());
+
+      return id.toString();
+   }
+}

Modified: trust/trunk/jbossws-native/src/main/java/org/picketlink/trust/jbossws/handler/SAML2Handler.java
===================================================================
--- trust/trunk/jbossws-native/src/main/java/org/picketlink/trust/jbossws/handler/SAML2Handler.java	2010-10-15 14:20:10 UTC (rev 478)
+++ trust/trunk/jbossws-native/src/main/java/org/picketlink/trust/jbossws/handler/SAML2Handler.java	2010-10-15 16:08:25 UTC (rev 479)
@@ -21,20 +21,24 @@
  */
 package org.picketlink.trust.jbossws.handler;
 
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
 import javax.security.auth.Subject;
 import javax.xml.namespace.QName;
+import javax.xml.soap.SOAPMessage;
 import javax.xml.ws.handler.MessageContext;
+import javax.xml.ws.handler.soap.SOAPMessageContext;
 
 import org.jboss.logging.Logger;
 import org.jboss.security.SecurityContext;
-import org.jboss.ws.core.CommonMessageContext;
-import org.jboss.ws.core.soap.SOAPMessageImpl;
-import org.jboss.ws.extensions.security.Util;
-import org.jboss.ws.extensions.security.element.SecurityHeader;
-import org.jboss.ws.extensions.security.jaxws.WSSecurityHandlerServer;
+import org.jboss.wsf.common.handler.GenericSOAPHandler;
 import org.picketlink.identity.federation.bindings.jboss.subject.PicketLinkPrincipal;
 import org.picketlink.identity.federation.core.wstrust.SamlCredential;
+import org.picketlink.trust.jbossws.Constants;
 import org.picketlink.trust.jbossws.SAML2Constants;
+import org.picketlink.trust.jbossws.Util;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 
@@ -42,20 +46,36 @@
  * A SAMLv2 WS handler.
  * 
  * @author <a href="mmoyses at redhat.com">Marcus Moyses</a>
+ * @author <a href="alessio.soldano at jboss.com">Alessio Soldano</a>
  * @version $Revision: 1 $
  */
-public class SAML2Handler extends WSSecurityHandlerServer
+public class SAML2Handler extends GenericSOAPHandler
 {
 
    protected Logger log = Logger.getLogger(this.getClass());
    
+   private static Set<QName> headers;
+
+   static
+   {
+      HashSet<QName> set = new HashSet<QName>();
+      set.add(Constants.WSSE_HEADER_QNAME);
+      headers = Collections.unmodifiableSet(set);
+   }
+
+   public Set<QName> getHeaders()
+   {
+      //return a collection with just the wsse:Security header to pass the MustUnderstand check on it
+      return headers;
+   }
+   
    /**
     * Retrieves the SAML assertion from the SOAP payload and lets invocation go to JAAS for validation.
     */
    protected boolean handleInbound(MessageContext msgContext)
    {
-      CommonMessageContext ctx = (CommonMessageContext) msgContext;
-      SOAPMessageImpl soapMessage = (SOAPMessageImpl) ctx.getSOAPMessage();
+      SOAPMessageContext ctx = (SOAPMessageContext) msgContext;
+      SOAPMessage soapMessage = ctx.getMessage();
       
       // retrieve the assertion
       Document document = soapMessage.getSOAPPart();
@@ -82,8 +102,8 @@
     */
    protected boolean handleOutbound(MessageContext msgContext)
    {
-      CommonMessageContext ctx = (CommonMessageContext) msgContext;
-      SOAPMessageImpl soapMessage = (SOAPMessageImpl) ctx.getSOAPMessage();
+      SOAPMessageContext ctx = (SOAPMessageContext) msgContext;
+      SOAPMessage soapMessage = ctx.getMessage();
       
       // retrieve assertion
       Element assertion = (Element) ctx.get(SAML2Constants.SAML2_ASSERTION_PROPERTY);
@@ -91,25 +111,42 @@
       // add wsse header
       Document document = soapMessage.getSOAPPart();
       Element soapHeader = Util.findOrCreateSoapHeader(document.getDocumentElement());
-      SecurityHeader secHeader = new SecurityHeader(document);
       try
       {
-         Element wsse = secHeader.getElement();
+         Element wsse = getSecurityHeaderElement(document);
          wsse.setAttributeNS(soapHeader.getNamespaceURI(), soapHeader.getPrefix() + ":mustUnderstand", "1");
          if (assertion != null)
          {
             // add the assertion as a child of the wsse header
-            wsse.appendChild(assertion);
+            // check if the assertion element comes from the same document, otherwise import the node
+            if (document != assertion.getOwnerDocument())
+            {
+               wsse.appendChild(document.importNode(assertion, true));
+            }
+            else
+            {
+               wsse.appendChild(assertion);
+            }
          }
          soapHeader.insertBefore(wsse, soapHeader.getFirstChild());
       }
       catch (Exception e)
       {
+         e.printStackTrace();
          log.error(e);
          return false;
       }
       
       return true;
    }
-
+   
+   private Element getSecurityHeaderElement(Document document)
+   {
+      Element element = document.createElementNS(Constants.WSSE_NS, Constants.WSSE_HEADER);
+      Util.addNamespace(element, Constants.WSSE_PREFIX, Constants.WSSE_NS);
+      Util.addNamespace(element, Constants.WSU_PREFIX, Constants.WSU_NS);
+      Util.addNamespace(element, Constants.XML_ENCRYPTION_PREFIX, Constants.XML_SIGNATURE_NS);
+      return element;
+   }
+   
 }



More information about the jboss-cvs-commits mailing list