[jbossws-commits] JBossWS SVN: r16554 - stack/cxf/branches/jbossws-cxf-3.1.2/modules/server/src/main/java/org/jboss/wsf/stack/cxf.

jbossws-commits at lists.jboss.org jbossws-commits at lists.jboss.org
Fri Jul 27 12:20:28 EDT 2012


Author: alessio.soldano at jboss.com
Date: 2012-07-27 12:20:28 -0400 (Fri, 27 Jul 2012)
New Revision: 16554

Added:
   stack/cxf/branches/jbossws-cxf-3.1.2/modules/server/src/main/java/org/jboss/wsf/stack/cxf/StAXUtils.java
Modified:
   stack/cxf/branches/jbossws-cxf-3.1.2/modules/server/src/main/java/org/jboss/wsf/stack/cxf/DescriptorDeploymentAspect.java
Log:
[JBPAPP-9224] Workaround for preventing potentially vulnerable scenarios


Modified: stack/cxf/branches/jbossws-cxf-3.1.2/modules/server/src/main/java/org/jboss/wsf/stack/cxf/DescriptorDeploymentAspect.java
===================================================================
--- stack/cxf/branches/jbossws-cxf-3.1.2/modules/server/src/main/java/org/jboss/wsf/stack/cxf/DescriptorDeploymentAspect.java	2012-07-27 11:04:16 UTC (rev 16553)
+++ stack/cxf/branches/jbossws-cxf-3.1.2/modules/server/src/main/java/org/jboss/wsf/stack/cxf/DescriptorDeploymentAspect.java	2012-07-27 16:20:28 UTC (rev 16554)
@@ -21,21 +21,29 @@
  */
 package org.jboss.wsf.stack.cxf;
 
+import static javax.xml.stream.XMLStreamConstants.START_ELEMENT;
+
 import java.io.IOException;
+import java.io.InputStream;
 import java.net.URL;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Map;
+import java.util.Set;
 
+import javax.jws.WebService;
+import javax.xml.stream.XMLStreamReader;
 import javax.xml.ws.BindingType;
+import javax.xml.ws.WebServiceProvider;
 import javax.xml.ws.soap.MTOM;
 import javax.xml.ws.soap.SOAPBinding;
 
 import org.jboss.logging.Logger;
 import org.jboss.wsf.spi.deployment.ArchiveDeployment;
 import org.jboss.wsf.spi.deployment.Deployment;
+import org.jboss.wsf.spi.deployment.Deployment.DeploymentType;
 import org.jboss.wsf.spi.deployment.DeploymentAspect;
 import org.jboss.wsf.spi.deployment.Endpoint;
-import org.jboss.wsf.spi.deployment.Deployment.DeploymentType;
 import org.jboss.wsf.stack.cxf.metadata.services.DDBeans;
 import org.jboss.wsf.stack.cxf.metadata.services.DDEndpoint;
 
@@ -71,7 +79,7 @@
 			cxfURL = generateCXFConfigFromDeployment(dep);
 		}
 		putCXFConfigToDeployment(dep, cxfURL);
-      
+		checkCVE20122379(dep, cxfURL);
    }
 
    @Override
@@ -96,25 +104,7 @@
     */
    private URL getCXFConfigFromDeployment(Deployment dep)
    {
-      DeploymentType depType = dep.getType();
-      
-      String metadir;
-      if (depType == DeploymentType.JAXWS_EJB3)
-      {
-         // expected resource location for EJB3 deployments
-         metadir = "META-INF";
-      }
-      else if (depType == DeploymentType.JAXWS_JSE)
-      {
-         // expected resource location for POJO deployments
-         metadir = "WEB-INF";
-      }
-      else
-      {
-         // only POJO and EJB3 deployments are supported
-         throw new IllegalStateException("Unsupported deployment type: " + depType);
-      }
-
+      final String metadir = getMetaDir(dep);
       URL cxfURL = null;
       try
       {
@@ -131,6 +121,26 @@
       return cxfURL;
    }
    
+   private String getMetaDir(Deployment dep) {
+      
+      DeploymentType depType = dep.getType();
+      if (depType == DeploymentType.JAXWS_EJB3)
+      {
+         // expected resource location for EJB3 deployments
+         return "META-INF";
+      }
+      else if (depType == DeploymentType.JAXWS_JSE)
+      {
+         // expected resource location for POJO deployments
+         return "WEB-INF";
+      }
+      else
+      {
+         // only POJO and EJB3 deployments are supported
+         throw new IllegalStateException("Unsupported deployment type: " + depType);
+      }
+   }
+   
    /**
     * Generated CXF descriptor from deployment
     * @param dep deployment
@@ -162,7 +172,6 @@
             ddep.setInvoker(invokerJSE);
          }
 
-
          log.info("Add " + ddep);
          dd.addEndpoint(ddep);
       }
@@ -210,5 +219,129 @@
       
       return mtomEnabled;
    }
+   
+   private void checkCVE20122379(Deployment dep, URL cxfURL)
+   {
+      try {
+         Set<String> wsdlLocations = new HashSet<String>();
+         //first check jbossws-cxf.xml
+         Set<String> endpoints = checkAssertionsAndGet(cxfURL, "http://cxf.apache.org/jaxws", "endpoint", "implementor");
+         ClassLoader cl = dep.getRuntimeClassLoader();
+         if (cl == null) {
+            cl = dep.getInitialClassLoader();
+         }
+         System.out.println("** CL: " + cl);
+         for (String ep : endpoints)
+         {
+            Class<?> clazz = cl.loadClass(ep);
+            String wl = null;
+            if (clazz.isAnnotationPresent(WebService.class)) {
+               WebService wsa = clazz.getAnnotation(WebService.class);
+               wl = wsa.wsdlLocation();
+               String epIf = wsa.endpointInterface();
+               if(epIf != null && !epIf.isEmpty()) {
+                  Class<?> epIfClass = cl.loadClass(epIf);
+                  WebService epIfWsa = epIfClass.getAnnotation(WebService.class);
+                  if (epIfWsa != null && epIfWsa.wsdlLocation() != null && !epIfWsa.wsdlLocation().isEmpty()) {
+                     wl = epIfWsa.wsdlLocation();
+                  }
+               }
+            } else {
+               WebServiceProvider wsp = clazz.getAnnotation(WebServiceProvider.class);
+               wl = wsp.wsdlLocation();
+            }
+            if (wl != null && !wl.trim().isEmpty()) {
+               wsdlLocations.add(wl);
+            }
+         }
+         //then check wsdl files for contract first endpoints
+         for (String w : wsdlLocations) {
+            try
+            {
+               ArchiveDeployment archDep = (ArchiveDeployment)dep;
+               URL wsdlURL = archDep.getResourceResolver().resolve(w);
+               checkAssertionsAndGet(wsdlURL, null, null, null);
+            }
+            catch (Exception e)
+            {
+               throw new RuntimeException(e);
+            }
+         }
+      }
+      catch (Exception e)
+      {
+         throw new RuntimeException(e);
+      }
+   }
+   
+   private Set<String> checkAssertionsAndGet(URL cxfUrl, String searchNS, String searchLocalName, String searchAttributeName) throws Exception
+   {
+      log.info("* checking... " + cxfUrl);
+      InputStream is = null;
+      XMLStreamReader reader = null;
+      Set<String> endpoints = new HashSet<String>();
+      final boolean search = searchNS != null || searchLocalName != null || searchAttributeName != null;
+      try
+      {
+         is = cxfUrl.openStream();
+         reader = StAXUtils.createXMLStreamReader(is);
+         while (reader.hasNext())
+         {
+            switch (reader.next())
+            {
+               case START_ELEMENT:
+               {
+                  if (StAXUtils.match(reader, NAMESPACES, ASSERTIONS))
+                  {
+                     throw new RuntimeException("WS-Security Policy SupportingTokens not allowed due to known security vulnerability! URL: " + cxfUrl);
+                  }
+                  else if (search && StAXUtils.match(reader, searchNS, searchLocalName))
+                  {
+                     String e = reader.getAttributeValue(null, searchAttributeName).trim();
+                     System.out.println("--> " + e);
+                     endpoints.add(e);
+                  }
+               }
+            }
+         }
+      }
+      finally
+      {
+         try {
+            reader.close();
+         } catch (Exception e) {}
+         try {
+            is.close();
+         } catch (Exception e) {}
+      }
+      return endpoints;
+   }
+   
+   private static final String SP_NS_11 = "http://schemas.xmlsoap.org/ws/2005/02/securitypolicy";
+   private static final String SP_NS_12 = "http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702";
+   private static final String SP_NS_13 = "http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200802";
+   private static final String SUPPORTING_TOKENS = "SupportingTokens";
+   private static final String SIGNED_SUPPORTING_TOKENS = "SignedSupportingTokens";
+   private static final String ENDORSING_SUPPORTING_TOKENS = "EndorsingSupportingTokens";
+   private static final String SIGNED_ENDORSING_SUPPORTING_TOKENS = "SignedEndorsingSupportingTokens";
+   private static final String SIGNED_ENCRYPTED_SUPPORTING_TOKENS = "SignedEncryptedSupportingTokens";
+   private static final String ENCRYPTED_SUPPORTING_TOKENS = "EncryptedSupportingTokens";
+   private static final String ENDORSING_ENCRYPTED_SUPPORTING_TOKENS = "EndorsingEncryptedSupportingTokens";
+   private static final String SIGNED_ENDORSING_ENCRYPTED_SUPPORTING_TOKENS = "SignedEndorsingEncryptedSupportingTokens";
+   private static String[] NAMESPACES = new String[3];
+   private static String[] ASSERTIONS = new String[8];
+   static {
+      NAMESPACES[0] = SP_NS_11;
+      NAMESPACES[1] = SP_NS_12;
+      NAMESPACES[2] = SP_NS_13;
+      ASSERTIONS[0] = SUPPORTING_TOKENS;
+      ASSERTIONS[1] = SIGNED_SUPPORTING_TOKENS;
+      ASSERTIONS[2] = ENDORSING_SUPPORTING_TOKENS;
+      ASSERTIONS[3] = SIGNED_ENDORSING_SUPPORTING_TOKENS;
+      ASSERTIONS[4] = SIGNED_ENCRYPTED_SUPPORTING_TOKENS;
+      ASSERTIONS[5] = ENCRYPTED_SUPPORTING_TOKENS;
+      ASSERTIONS[6] = ENDORSING_ENCRYPTED_SUPPORTING_TOKENS;
+      ASSERTIONS[7] = SIGNED_ENDORSING_ENCRYPTED_SUPPORTING_TOKENS;
+   }
 
 }

Added: stack/cxf/branches/jbossws-cxf-3.1.2/modules/server/src/main/java/org/jboss/wsf/stack/cxf/StAXUtils.java
===================================================================
--- stack/cxf/branches/jbossws-cxf-3.1.2/modules/server/src/main/java/org/jboss/wsf/stack/cxf/StAXUtils.java	                        (rev 0)
+++ stack/cxf/branches/jbossws-cxf-3.1.2/modules/server/src/main/java/org/jboss/wsf/stack/cxf/StAXUtils.java	2012-07-27 16:20:28 UTC (rev 16554)
@@ -0,0 +1,210 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2006, 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.jboss.wsf.stack.cxf;
+
+import java.io.InputStream;
+import java.util.ResourceBundle;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLResolver;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+/**
+ * StAX utils
+ * 
+ * @author alessio.soldano at jboss.com
+ * @since 27-Nov-2010
+ */
+public class StAXUtils
+{
+   private static final BlockingQueue<XMLInputFactory> INPUT_FACTORY_POOL;
+
+   static
+   {
+      int i = 10;
+      try
+      {
+         String s = System.getProperty("org.jboss.ws.staxutils.pool-size", "10");
+         i = Integer.parseInt(s);
+      }
+      catch (Throwable t)
+      {
+         i = 10;
+      }
+      if (i <= 0)
+      {
+         i = 10;
+      }
+      INPUT_FACTORY_POOL = new LinkedBlockingQueue<XMLInputFactory>(i);
+   }
+
+   /**
+    * Return a new factory so that the caller can set sticky parameters.
+    * @param nsAware
+    * @return
+    */
+   public static XMLInputFactory createXMLInputFactory(boolean nsAware)
+   {
+      XMLInputFactory factory = XMLInputFactory.newInstance();
+      factory.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, nsAware);
+      factory.setProperty(XMLInputFactory.SUPPORT_DTD, Boolean.FALSE);
+      factory.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, Boolean.FALSE);
+      factory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, Boolean.FALSE);
+      factory.setXMLResolver(new XMLResolver()
+      {
+         public Object resolveEntity(String publicID, String systemID, String baseURI, String namespace)
+               throws XMLStreamException
+         {
+            throw new XMLStreamException("READING_EXTERNAL_ENTITIES_IS_DISABLED");
+         }
+      });
+      return factory;
+   }
+
+   private static XMLInputFactory getXMLInputFactory()
+   {
+      XMLInputFactory f = INPUT_FACTORY_POOL.poll();
+      if (f == null)
+      {
+         f = createXMLInputFactory(true);
+      }
+      return f;
+   }
+
+   private static void returnXMLInputFactory(XMLInputFactory factory)
+   {
+      INPUT_FACTORY_POOL.offer(factory);
+   }
+
+   public static XMLStreamReader createXMLStreamReader(InputStream in)
+   {
+      XMLInputFactory factory = getXMLInputFactory();
+      try
+      {
+         return factory.createXMLStreamReader(in);
+      }
+      catch (XMLStreamException e)
+      {
+         throw new RuntimeException("Could not parse stream",  e);
+      }
+      finally
+      {
+         returnXMLInputFactory(factory);
+      }
+   }
+
+   public static boolean match(XMLStreamReader reader, QName name)
+   {
+      return reader.getName().equals(name);
+   }
+   
+   public static boolean match(XMLStreamReader reader, String namespace, String localName)
+   {
+      QName name = reader.getName();
+      return localName.equals(name.getLocalPart()) && namespace.equals(name.getNamespaceURI());
+   }
+   
+   public static boolean match(XMLStreamReader reader, String[] namespaces, String[] localNames)
+   {
+      QName name = reader.getName();
+      boolean matchedNS = false;
+      for (String n : namespaces) {
+         if (!matchedNS && n.equals(name.getNamespaceURI())) {
+            matchedNS = true;
+         }
+      }
+      if (matchedNS) {
+         for (String l : localNames) {
+            if (l.equals(name.getLocalPart())) {
+               return true;
+            }
+         }
+      }
+      return false;
+   }
+
+   public static String elementAsString(XMLStreamReader reader) throws XMLStreamException
+   {
+      String elementtext = reader.getElementText();
+      return elementtext == null ? null : elementtext.trim();
+   }
+
+   public static QName elementAsQName(XMLStreamReader reader) throws XMLStreamException
+   {
+      String text = elementAsString(reader);
+      return stringToQName(reader, text, reader.getNamespaceURI());
+   }
+   
+   public static boolean elementAsBoolean(XMLStreamReader reader) throws XMLStreamException
+   {
+      String text = elementAsString(reader);
+      return Boolean.parseBoolean(text);
+   }
+   
+   public static int elementAsInt(XMLStreamReader reader) throws XMLStreamException
+   {
+      String text = elementAsString(reader);
+      return Integer.parseInt(text);
+   }
+   
+   public static QName attributeAsQName(XMLStreamReader reader, String namespace, String localName) throws XMLStreamException
+   {
+      String text = reader.getAttributeValue(namespace, localName);
+      return stringToQName(reader, text, reader.getNamespaceURI());
+   }
+   
+   public static QName attributeAsQName(XMLStreamReader reader, String namespace, String localName, String targetNS) throws XMLStreamException
+   {
+      String text = reader.getAttributeValue(namespace, localName);
+      return stringToQName(reader, text, targetNS);
+   }
+   
+   private static QName stringToQName(XMLStreamReader reader, String text, String defaultNS)
+   {
+      String localPart = text.substring(text.indexOf(':') + 1, text.length());
+      int i = text.indexOf(':');
+      String prefix = i < 0 ? null : text.substring(0, i);
+      String namespaceURI = prefix == null ? defaultNS : reader.getNamespaceURI(prefix);
+      return prefix == null ? new QName(namespaceURI, localPart) : new QName(namespaceURI, localPart, prefix);
+   }
+   
+   public static int nextElement(XMLStreamReader reader)
+   {
+      try
+      {
+         int x = reader.next();
+         while (x != XMLStreamReader.START_ELEMENT && x != XMLStreamReader.END_ELEMENT && reader.hasNext())
+         {
+            x = reader.next();
+         }
+         return x;
+      }
+      catch (XMLStreamException e)
+      {
+         throw new RuntimeException("COULDN'T_PARSE_STREAM",  e);
+      }
+   }
+}



More information about the jbossws-commits mailing list