You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@uima.apache.org by ch...@apache.org on 2014/11/20 16:22:36 UTC

svn commit: r1640754 - in /uima/sandbox/uima-ducc/trunk: uima-ducc-cli/src/test/java/org/apache/uima/ducc/cli/test/ uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/dispatcher/

Author: challngr
Date: Thu Nov 20 15:22:36 2014
New Revision: 1640754

URL: http://svn.apache.org/r1640754
Log:
UIMA-4064 Add classpath poisoning test, and fix the bugs it revealed.

Added:
    uima/sandbox/uima-ducc/trunk/uima-ducc-cli/src/test/java/org/apache/uima/ducc/cli/test/ClassSeparation.java
Modified:
    uima/sandbox/uima-ducc/trunk/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/dispatcher/ClassManager.java
    uima/sandbox/uima-ducc/trunk/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/dispatcher/DuccEventHttpDispatcher.java

Added: uima/sandbox/uima-ducc/trunk/uima-ducc-cli/src/test/java/org/apache/uima/ducc/cli/test/ClassSeparation.java
URL: http://svn.apache.org/viewvc/uima/sandbox/uima-ducc/trunk/uima-ducc-cli/src/test/java/org/apache/uima/ducc/cli/test/ClassSeparation.java?rev=1640754&view=auto
==============================================================================
--- uima/sandbox/uima-ducc/trunk/uima-ducc-cli/src/test/java/org/apache/uima/ducc/cli/test/ClassSeparation.java (added)
+++ uima/sandbox/uima-ducc/trunk/uima-ducc-cli/src/test/java/org/apache/uima/ducc/cli/test/ClassSeparation.java Thu Nov 20 15:22:36 2014
@@ -0,0 +1,174 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+*/
+
+package org.apache.uima.ducc.cli.test;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+import org.apache.uima.ducc.cli.DuccReservationCancel;
+import org.apache.uima.ducc.cli.DuccReservationSubmit;
+
+import com.google.gson.Gson;
+// Note: this is required for compilation but DO NOT put it into the runtime
+//       classpath or the tests will fail.
+import com.thoughtworks.xstream.XStream;
+import com.thoughtworks.xstream.io.xml.DomDriver;
+
+/**
+ * Test CLI classpath separation
+ * 
+ * To run this test, compile with the google Gson jar and the poisoned xstream class from the
+ * test package.  Then run WITHOUT Gson, but still with the poisoned xstream.
+ *
+ * The CLI uses both gson and xstream.  The gson test must throw to succeed, because the test tries
+ * to load it and gson should be on the other side of the classloader barrier.
+ *
+ * The reservation should go through becase the poisoned xstream is kept on "this" side of the
+ * classloader barrier and only the good one is used.
+ */
+public class ClassSeparation
+    extends ATestDriver
+{
+    public ClassSeparation()
+    {
+    }
+
+    public String[] testsToRun()
+    {
+        return new String[] {
+            "VerifyWrongXstream",          // insure poisoned classes are provided by the "user"
+            "LoadGson",                    // Insure we can't get at any of the CLI's open source stuff
+            "PoisonedCLI",                 // Insure our poisoned classes don't leak into the CLI
+        };
+    }
+
+    public void testVerifyWrongXstream(String testid)
+        throws Exception
+    {
+        DomDriver dd = null;
+        try {
+            dd = new DomDriver();
+        } catch ( IllegalStateException e ) {
+            String msg = e.getMessage();
+            if ( msg.equals("I am not the DomDriver.") ) {
+                success(testid, "DomDriver is properly bogus.");
+            } else {
+                fail(testid, "DomDriver may not be bogus, test is invalid.");
+            }
+        }
+
+        try {
+            XStream xs = new XStream(dd);
+        } catch ( IllegalStateException e ) {
+            String msg = e.getMessage();
+            if ( msg.equals("I am not XStream.") ) {
+                success(testid, "XStream is properly bogus.");
+            } else {
+                fail(testid, "XStream may not be bogus, test is invalid.");
+            }
+        }
+
+    }
+
+    /**
+     * Try to load gson - it must fail.  The CLI uses gson, which it will load, but across a
+     * classloader barrier so it can't "leak" back into here.
+     */
+    public void testLoadGson(String testid)
+        throws Exception
+    {
+        try {
+            Map<Integer, String> m = new HashMap<Integer, String>();
+            for ( int i = 0; i < 20; i++ ) {
+                m.put(i, ""+i);
+            }
+            Gson g = new Gson();
+            String gs = g.toJson(m);
+            System.out.println(gs);
+            fail(testid, "Loaded gson, should have failed.");
+        } catch ( NoClassDefFoundError e ) {
+        	success("Test succeeded, gson did not leak from CLI into the test code:"  + e.toString());
+        }
+    }
+
+    /**
+     * Try to poison the CLI.  The CLI needs xstream. We'll put a deliberately poisoned xstream into
+     * the classpath when running this test.  The CLI should succeed nonetheless.
+     */
+    public void testPoisonedCLI(String testid)
+        throws Exception
+    {
+
+        Properties reserve_props = new Properties();
+        DuccReservationSubmit reserve;
+        String resid = null;
+
+        reserve_props.setProperty("description", "Reserve And Cancel");
+        reserve_props.setProperty("instance_memory_size", "4");
+        reserve_props.setProperty("number_of_instances", "2");
+        reserve_props.setProperty("scheduling_class", "fixed");
+        try {
+            reserve = new DuccReservationSubmit(reserve_props);
+            if ( reserve.execute() ) {
+                resid = "" + reserve.getDuccId();
+                success(testid, "Reservation", resid, "successful, rc =", ""+reserve.getReturnCode(), ":", reserve.getHostsAsString());
+                String[] hosts = reserve.getHosts();
+                System.out.println("" + hosts.length + " hosts assigned");
+                if ( hosts.length > 0 ) {
+                    for ( String h : reserve.getHosts() ) {
+                        System.out.println("   " + h);
+                    }
+                }            
+            } else {
+                fail(testid, "Reservation failed, rc = " + reserve.getReturnCode());
+            }
+        } catch ( Throwable e ) {
+            fail(testid, "Reservation cannot execute.");
+            e.printStackTrace();
+        }
+
+        if ( resid == null ) {
+            fail(testid, "Bypass cancel because reserve failed.");
+            return;
+        }
+
+        Properties cancel_props = new Properties();
+        cancel_props.setProperty("id", resid);
+        try {
+            DuccReservationCancel cancel = new DuccReservationCancel(cancel_props);
+            if ( cancel.execute() ) {
+                success(testid, "Reservation " + ""+cancel.getDuccId() + " cancelled, rc = " + cancel.getReturnCode() + " " + cancel.getResponseMessage());
+            } else {                
+                fail(testid, "Reservation " + ""+cancel.getDuccId() + " cancel failed, rc = " + cancel.getReturnCode() + " " + cancel.getResponseMessage());
+            }
+        } catch ( Throwable t ) {
+            fail(testid, "Cancel reseration cannot execute.");
+        }
+
+    }
+
+    public static void main(String[] args)
+    {
+        ClassSeparation tester = new ClassSeparation();
+        tester.runTests();
+    }
+
+}

Modified: uima/sandbox/uima-ducc/trunk/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/dispatcher/ClassManager.java
URL: http://svn.apache.org/viewvc/uima/sandbox/uima-ducc/trunk/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/dispatcher/ClassManager.java?rev=1640754&r1=1640753&r2=1640754&view=diff
==============================================================================
--- uima/sandbox/uima-ducc/trunk/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/dispatcher/ClassManager.java (original)
+++ uima/sandbox/uima-ducc/trunk/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/dispatcher/ClassManager.java Thu Nov 20 15:22:36 2014
@@ -317,35 +317,25 @@ public class ClassManager
         extends URLClassLoader
     {
 
-        ClassLoader parent;
         HttpClassLoader(URL[] urls, ClassLoader parent)
         {
             super(urls, parent);
-            this.parent = parent;
-
-            //for ( URL u : urls ) {
-            //    System.out.println("XStreamClassLoader initializes from " + u);
-            // }
         }
 
-        public Class<?> findClass(final String clname)
-            throws ClassNotFoundException
+        public Class<?> loadClass(String clname, boolean resolve)
+        	throws ClassNotFoundException
         {
-            if ( DEBUG ) System.out.println("--------- HttpClassLoader -- Finding class " + clname + " from " + this.getClass() + " " + clname);
-            Class<?> ret = super.findClass(clname);
-            if ( ret == null ) {
-                if ( DEBUG ) {
-                    System.out.println("                                          Not found");
-                }
-            } else {
-                if ( DEBUG ) {
-                    System.out.println("                                          " + ret.getProtectionDomain().getCodeSource().getLocation());
-                    System.out.println("                                          " + ret.getClassLoader());
-                }
+
+            if ( DEBUG ) System.out.println("--------- HttpClassLoader ------- load class " + clname);
+            try {
+                Class<?> ret =  super.loadClass(clname, resolve);
+                if ( DEBUG ) System.out.println("--------- HttpClassLoader ------- returns " + clname);                
+                return ret;
+            } catch ( ClassNotFoundException e ) {
+                if ( DEBUG ) System.out.println("--------- HttpClassLoader ------- fails to find " + clname);                
+                throw e;
             }
-            return ret;
         }
-
     }
 
     class PrivateClassLoader
@@ -380,60 +370,22 @@ public class ClassManager
             this.grand_parent = grand_parent;
         }
 
-
-        public Class<?> loadClass(String clname)
-        	throws ClassNotFoundException
-        {
-            if ( DEBUG ) System.out.println("---- A ------- load class " + clname + " from " + this);
-            Class<?> ret =  super.loadClass(clname);
-            if ( DEBUG ) {
-                System.out.println("---- A ------- load class " + clname + " returns " + ret );
-                try { 
-                    throw new Exception("Stack trace:");
-                } catch ( Throwable e ) {
-                    e.printStackTrace();
-                    System.out.println("--- A -----------------------------------------------------------------------------");
-                }
-            }
-            return ret;
-        }
-
         public Class<?> loadClass(String clname, boolean resolve)
         	throws ClassNotFoundException
         {
-
-            if ( DEBUG ) System.out.println("---- B ------- load class " + clname + " from " + this);
-            Class<?> ret =  super.loadClass(clname, resolve);
-            if ( DEBUG ) {
-                System.out.println("---- B ------ load class " + clname + " returns " + ret);
-                try { 
-                    throw new Exception("Stack trace:");
-                } catch ( Throwable e ) {
-                    e.printStackTrace();
-                    System.out.println("---- B -----------------------------------------------------------------------------");
-                }
-            }
-            return ret;
-        }
-
-
-        public Class<?> findClass(final String clname)
-            throws ClassNotFoundException
-        {
-            if ( DEBUG ) System.out.println("*********** find class ********** " + clname);
-            // we want all the interfaces from "common" except UIOptions and IDuccMonitor which aren't well-placed
-            // for this exercise so we need a special case for them
-            Class<?> ret = grand_parent.findClass(clname);
-            if ( ret == null ) {
-                if ( DEBUG ) {
-                    System.out.println("*********** Looking in " + parent + " for " + clname);
-                }
-                return super.findClass(clname);
-            } else {
+            Class<?> ret = null;
+            if ( DEBUG ) System.out.println("---- A ------- load class " + clname + " from " + this);
+            try { 
+                ret = grand_parent.loadClass(clname, resolve);
+                if ( DEBUG ) System.out.println("---- A ------- returns " + clname + " from " + grand_parent);                
+                return ret;
+            }  catch ( ClassNotFoundException e ) {
+                if ( DEBUG ) System.out.println("---- A ------- looking in " + parent + " to load " + clname);
+                ret = super.loadClass(clname, resolve);
+                if ( DEBUG ) System.out.println("---- A ------- returns " + clname + " from " + parent);
                 return ret;
             }
         }
-
     }
 
 }

Modified: uima/sandbox/uima-ducc/trunk/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/dispatcher/DuccEventHttpDispatcher.java
URL: http://svn.apache.org/viewvc/uima/sandbox/uima-ducc/trunk/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/dispatcher/DuccEventHttpDispatcher.java?rev=1640754&r1=1640753&r2=1640754&view=diff
==============================================================================
--- uima/sandbox/uima-ducc/trunk/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/dispatcher/DuccEventHttpDispatcher.java (original)
+++ uima/sandbox/uima-ducc/trunk/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/dispatcher/DuccEventHttpDispatcher.java Thu Nov 20 15:22:36 2014
@@ -172,9 +172,15 @@ public class DuccEventHttpDispatcher {
     public DuccEvent dispatchAndWaitForDuccReply(DuccEvent duccEvent) 
         throws Exception
     {
-        String serBody = toXml(duccEvent);
-        String response =  dispatch(serBody, "text/xml");
-        return (DuccEvent) fromXml(response);
+        String serBody = null;
+    	try{
+    		serBody = toXml(duccEvent);
+            String response =  dispatch(serBody, "text/xml");
+            return (DuccEvent) fromXml(response);
+    	} catch ( Throwable t ) { 
+            t.printStackTrace(); 
+        }
+        return null;
     }
 
     Object fromJson(String str, Class<?> cl)