vhardy      2004/02/24 06:04:37

  Modified:    test-sources/org/apache/batik/bridge EcmaNoLoadTest.java
                        ScriptSelfTest.java
               test-sources/org/apache/batik/test/svg
                        SVGOnLoadExceptionTest.java
               sources/org/apache/batik/bridge
                        BaseScriptingEnvironment.java BridgeContext.java
               sources/org/apache/batik/script InterpreterPool.java
               sources/org/apache/batik/script/rhino
                        BatikSecurityController.java RhinoInterpreter.java
  Log:
  Improved error reporting when failing to load interpreter. Now throw a 
SecurityException if Scripts() are used. Added code that exercises the Batik API from 
restricted permission code
  
  Revision  Changes    Path
  1.2       +26 -6     
xml-batik/test-sources/org/apache/batik/bridge/EcmaNoLoadTest.java
  
  Index: EcmaNoLoadTest.java
  ===================================================================
  RCS file: 
/home/cvs/xml-batik/test-sources/org/apache/batik/bridge/EcmaNoLoadTest.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- EcmaNoLoadTest.java       23 Feb 2004 15:24:59 -0000      1.1
  +++ EcmaNoLoadTest.java       24 Feb 2004 14:04:37 -0000      1.2
  @@ -83,19 +83,36 @@
                       SVGOnLoadExceptionTest t = buildTest(scripts,
                                                            scriptSource[i],
                                                            scriptOrigin[k],
  -                                                         secure[j]);
  +                                                         secure[j],
  +                                                         false);
                       addTest(t);
                   }
               }
           }
   
           //
  +        // If script run in restricted mode, then there should be
  +        // a security exception, no matter what the other settings are
  +        // (if we are running code under a security manager, that is,
  +        // i.e., secure is true).
  +        scripts = "text/ecmascript";
  +        for (int i=0; i<scriptSource.length; i++) {
  +            for (int k=0; k<scriptOrigin.length; k++) {
  +                SVGOnLoadExceptionTest t = buildTest(scripts,
  +                                                     scriptSource[i],
  +                                                     scriptOrigin[k],
  +                                                     true,
  +                                                     true);
  +                addTest(t);
  +            }
  +        }
  +
  +        //
           // If "applicatin/ecmascript" is allowed, but the accepted
           // script origin is lower than the candidate script, then
           // the script should not be loaded (e.g., if scriptOrigin
           // is embeded and trying to load an external script).
           //
  -        scripts = "text/ecmascript";
           for (int j=0; j<scriptOrigin.length; j++) {
               int max = j;
               if (j == scriptOrigin.length - 1) {
  @@ -105,25 +122,28 @@
                   for (int k=0; k<secure.length; k++) {
                       SVGOnLoadExceptionTest t= buildTest(scripts, scriptSource[i],
                                                           scriptOrigin[j],
  -                                                        secure[k]);
  +                                                        secure[k],
  +                                                        false);
                       addTest(t);
                   }
               }
           }
       }
   
  -    SVGOnLoadExceptionTest buildTest(String scripts, String id, String origin, 
boolean secure) {
  +    SVGOnLoadExceptionTest buildTest(String scripts, String id, String origin, 
boolean secure, boolean restricted) {
           SVGOnLoadExceptionTest t = new SVGOnLoadExceptionTest();
           String desc = 
               "(scripts=" + scripts + 
               ")(scriptOrigin=" + origin +
  -            ")(secure=" + secure + ")";
  +            ")(secure=" + secure +
  +            ")(restricted=" + restricted + ")";
           
           t.setId(id + desc);
           t.setScriptOrigin(origin);
           t.setSecure(secure);
           t.setScripts(scripts);
           t.setExpectedExceptionClass("java.lang.SecurityException");
  +        t.setRestricted(restricted);
   
           return t;
       }
  
  
  
  1.7       +11 -43    
xml-batik/test-sources/org/apache/batik/bridge/ScriptSelfTest.java
  
  Index: ScriptSelfTest.java
  ===================================================================
  RCS file: 
/home/cvs/xml-batik/test-sources/org/apache/batik/bridge/ScriptSelfTest.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- ScriptSelfTest.java       23 Feb 2004 15:24:59 -0000      1.6
  +++ ScriptSelfTest.java       24 Feb 2004 14:04:37 -0000      1.7
  @@ -57,13 +57,21 @@
   
   import java.security.AccessController;
   import java.security.AccessControlContext;
  +import java.security.CodeSource;
   import java.security.PrivilegedExceptionAction;
   import java.security.PrivilegedActionException;
   import java.security.ProtectionDomain;
  +import java.security.Permission;
  +import java.security.PermissionCollection;
   import java.security.Permissions;
  +import java.security.Policy;
   
   import java.io.FilePermission;
  +import java.io.File;
   
  +import java.net.URL;
  +
  +import java.util.Enumeration;
   /**
    * Helper class to simplify writing the unitTesting.xml file for 
    * the bridge.
  @@ -76,7 +84,6 @@
       String scripts = "text/ecmascript, application/java-archive";
       boolean secure = true;
       String scriptOrigin = "any";
  -    boolean restricted = false;
       String fileName;
   
       TestUserAgent userAgent = new TestUserAgent();
  @@ -110,14 +117,6 @@
           this.scriptOrigin = scriptOrigin;
       }
   
  -    public boolean getRestricted() {
  -        return restricted;
  -    }
  -
  -    public void setRestricted(boolean restricted) {
  -        this.restricted = restricted;
  -    }
  -
       public void setScripts(String scripts){
           this.scripts = scripts;
       }
  @@ -136,37 +135,6 @@
           }
   
           try {
  -            if (!restricted) {
  -                return superRunImpl();
  -            } else {
  -                // Emulate calling from restricted code. We create a 
  -                // calling context with only the permission to read
  -                // the file.
  -                FilePermission permission 
  -                    = new FilePermission(fileName, "read");
  -                Permissions permissions = new Permissions();
  -                permissions.add(permission);
  -                ProtectionDomain domain = new ProtectionDomain(null, permissions);
  -                AccessControlContext ctx = new AccessControlContext
  -                    (new ProtectionDomain[] {domain});
  -
  -                try {
  -                    return (TestReport)AccessController.doPrivileged(new 
PrivilegedExceptionAction() {
  -                            public Object run() throws Exception {
  -                                return superRunImpl();
  -                            }
  -                        }, ctx);
  -                } catch (PrivilegedActionException pae) {
  -                    throw pae.getException();
  -                }
  -            }
  -        } finally {
  -            ase.enforceSecurity(false);
  -        }
  -    }
  -
  -    protected TestReport superRunImpl() throws Exception {
  -        try {
               return super.runImpl();
           } catch (ExceptionInInitializerError e) {
               e.printStackTrace();
  @@ -174,6 +142,8 @@
           } catch (NoClassDefFoundError e) {
               // e.printStackTrace();
               throw new Exception(e.getMessage());
  +        } finally {
  +            ase.enforceSecurity(false);
           }
       }
   
  @@ -205,8 +175,6 @@
                   }
               }
   
  -            System.err.println(">>>>>>>>>>>>> using script security: " + 
scriptSecurity + 
  -                               " for " + scriptPURL + " referenced from " + 
docPURL);
               return scriptSecurity;
           }
       }
  
  
  
  1.6       +150 -53   
xml-batik/test-sources/org/apache/batik/test/svg/SVGOnLoadExceptionTest.java
  
  Index: SVGOnLoadExceptionTest.java
  ===================================================================
  RCS file: 
/home/cvs/xml-batik/test-sources/org/apache/batik/test/svg/SVGOnLoadExceptionTest.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- SVGOnLoadExceptionTest.java       23 Feb 2004 15:24:59 -0000      1.5
  +++ SVGOnLoadExceptionTest.java       24 Feb 2004 14:04:37 -0000      1.6
  @@ -79,6 +79,21 @@
   import org.apache.batik.util.XMLResourceDescriptor;
   import org.apache.batik.util.ApplicationSecurityEnforcer;
   
  +import java.security.AccessController;
  +import java.security.AccessControlContext;
  +import java.security.CodeSource;
  +import java.security.PrivilegedExceptionAction;
  +import java.security.PrivilegedActionException;
  +import java.security.ProtectionDomain;
  +import java.security.Permission;
  +import java.security.PermissionCollection;
  +import java.security.Permissions;
  +import java.security.Policy;
  +
  +import java.io.FilePermission;
  +
  +import java.util.Enumeration;
  +
   /**
    * This test takes an SVG file as an input. It processes the input SVG
    * (meaning it turns it into a GVT tree) and then dispatches the 'onload'
  @@ -199,6 +214,25 @@
        */
       protected Boolean validate = new Boolean(false);
   
  +    /**
  +     * The name of the test file
  +     */
  +    protected String fileName;
  +
  +    /**
  +     * Controls whether on not the document should be processed from
  +     * a 'restricted' context, one with no createClassLoader permission.
  +     */
  +    protected boolean restricted = false;
  +
  +    public boolean getRestricted() {
  +        return restricted;
  +    }
  +
  +    public void setRestricted(boolean restricted) {
  +        this.restricted = restricted;
  +    }
  +
       public void setScripts(String scripts){
           this.scripts = scripts;
       }
  @@ -272,7 +306,7 @@
               if (i != -1) {
                   id = id.substring(0, i);
               }
  -            String fileName = "test-resources/org/apache/batik/" + id + ".svg";
  +            fileName = "test-resources/org/apache/batik/" + id + ".svg";
               svgURL = resolveURL(fileName);
           }
       }
  @@ -324,70 +358,119 @@
           }
   
           try {
  -            //
  -            // First step: 
  -            //
  -            // Load the input SVG into a Document object
  -            //
  -            String parserClassName = XMLResourceDescriptor.getXMLParserClassName();
  -            SAXSVGDocumentFactory f = new SAXSVGDocumentFactory(parserClassName);
  -            f.setValidating(validate.booleanValue());
  -            Document doc = null;
  -            
  -            try {
  -                doc = f.createDocument(svgURL);
  -            } catch(Exception e){
  -                return handleException(e);
  -            } 
  -            
  -            //
  -            // Second step:
  -            // 
  -            // Now that the SVG file has been loaded, build
  -            // a GVT Tree from it
  -            //
  -            TestUserAgent userAgent = buildUserAgent();
  -            GVTBuilder builder = new GVTBuilder();
  -            BridgeContext ctx = new BridgeContext(userAgent);
  -            ctx.setDynamic(true);
  -            Exception e = null;
  -            try {
  -                builder.build(ctx, doc);
  -                BaseScriptingEnvironment scriptEnvironment 
  -                    = new BaseScriptingEnvironment(ctx);
  -                scriptEnvironment.loadScripts();
  -                scriptEnvironment.dispatchSVGLoadEvent();
  -            } catch (Exception ex){
  -                e = ex;
  -            } finally {
  -                if (e == null && userAgent.e != null) {
  -                    e = userAgent.e;
  +            if (!restricted) {
  +                return testImpl();
  +            } else {
  +                // Emulate calling from restricted code. We create a 
  +                // calling context with only the permission to read
  +                // the file.
  +                Policy policy = Policy.getPolicy();
  +                URL classesURL = (new File("classes")).toURL();
  +                CodeSource cs = new CodeSource(classesURL, null);
  +                PermissionCollection permissionsOrig
  +                    = policy.getPermissions(cs);
  +                Permissions permissions = new Permissions();
  +                Enumeration iter = permissionsOrig.elements();
  +                while (iter.hasMoreElements()) {
  +                    Permission p = (Permission)iter.nextElement();
  +                    if (!(p instanceof RuntimePermission)) {
  +                        if (!(p instanceof java.security.AllPermission)) {
  +                            permissions.add(p);
  +                        } 
  +                    } else {
  +                        if (!"createClassLoader".equals(p.getName())) {
  +                            permissions.add(p);
  +                        } 
  +                    }
                   }
   
  -                if (e != null) {
  -                    return handleException(e);
  +                permissions.add(new FilePermission(fileName, "read"));
  +                permissions.add(new RuntimePermission("accessDeclaredMembers"));
  +
  +                ProtectionDomain domain = new ProtectionDomain(null, permissions);
  +                AccessControlContext ctx = new AccessControlContext
  +                    (new ProtectionDomain[] {domain});
  +
  +                try {
  +                    return (TestReport)AccessController.doPrivileged(new 
PrivilegedExceptionAction() {
  +                            public Object run() throws Exception {
  +                                return testImpl();
  +                            }
  +                        }, ctx);
  +                } catch (PrivilegedActionException pae) {
  +                    throw pae.getException();
                   }
  -            } 
  -            
  -            //
  -            // If we got here, it means that the expected exception did not
  -            // happen. Report an error
  -            //
  -            TestReport report = reportError(ERROR_EXCEPTION_DID_NOT_OCCUR);
  -            report.addDescriptionEntry(ENTRY_KEY_EXPECTED_EXCEPTION,
  -                                       expectedExceptionClass);
  -            return report;
  +            }
           } finally {
               ase.enforceSecurity(false);
           }
       }
   
  +    /**
  +     * Implementation helper
  +     */
  +    protected TestReport testImpl() {
  +        //
  +        // First step: 
  +        //
  +        // Load the input SVG into a Document object
  +        //
  +        String parserClassName = XMLResourceDescriptor.getXMLParserClassName();
  +        SAXSVGDocumentFactory f = new SAXSVGDocumentFactory(parserClassName);
  +        f.setValidating(validate.booleanValue());
  +        Document doc = null;
  +        
  +        try {
  +            doc = f.createDocument(svgURL);
  +        } catch(Exception e){
  +            return handleException(e);
  +        } 
  +        
  +        //
  +        // Second step:
  +        // 
  +        // Now that the SVG file has been loaded, build
  +        // a GVT Tree from it
  +        //
  +        TestUserAgent userAgent = buildUserAgent();
  +        GVTBuilder builder = new GVTBuilder();
  +        BridgeContext ctx = new BridgeContext(userAgent);
  +        ctx.setDynamic(true);
  +        Exception e = null;
  +        try {
  +            builder.build(ctx, doc);
  +            BaseScriptingEnvironment scriptEnvironment 
  +                = new BaseScriptingEnvironment(ctx);
  +            scriptEnvironment.loadScripts();
  +            scriptEnvironment.dispatchSVGLoadEvent();
  +        } catch (Exception ex){
  +            e = ex;
  +        } finally {
  +            if (e == null && userAgent.e != null) {
  +                e = userAgent.e;
  +            }
  +            
  +            if (e != null) {
  +                return handleException(e);
  +            }
  +        } 
  +        
  +        //
  +        // If we got here, it means that the expected exception did not
  +        // happen. Report an error
  +        //
  +        TestReport report = reportError(ERROR_EXCEPTION_DID_NOT_OCCUR);
  +        report.addDescriptionEntry(ENTRY_KEY_EXPECTED_EXCEPTION,
  +                                   expectedExceptionClass);
  +        return report;
  +    }
  +
       /** 
        * Compares the input exception with the expected exception
        * If they match, then the test passes. Otherwise, the test fails
        */
       protected TestReport handleException(Exception e) {
  -        if (!e.getClass().getName().equals(expectedExceptionClass)) {
  +        if (!isMatch(e.getClass(), expectedExceptionClass)) {
               TestReport report = reportError(ERROR_UNEXPECTED_EXCEPTION);
               report.addDescriptionEntry(ENTRY_KEY_UNEXPECTED_EXCEPTION,
                                          e.getClass().getName());
  @@ -407,6 +490,20 @@
                   }
               }
               return reportSuccess();
  +        }
  +    }
  +
  +    /**
  +     * Check if the input class' name (or one of its base classes) matches
  +     * the input name.
  +     */
  +    protected boolean isMatch(final Class cl, final String name) {
  +        if (cl == null) {
  +            return false;
  +        } else if (cl.getName().equals(name)) {
  +            return true;
  +        } else {
  +            return isMatch(cl.getSuperclass(), name);
           }
       }
   
  
  
  
  1.29      +3 -6      
xml-batik/sources/org/apache/batik/bridge/BaseScriptingEnvironment.java
  
  Index: BaseScriptingEnvironment.java
  ===================================================================
  RCS file: 
/home/cvs/xml-batik/sources/org/apache/batik/bridge/BaseScriptingEnvironment.java,v
  retrieving revision 1.28
  retrieving revision 1.29
  diff -u -r1.28 -r1.29
  --- BaseScriptingEnvironment.java     19 Feb 2004 20:32:07 -0000      1.28
  +++ BaseScriptingEnvironment.java     24 Feb 2004 14:04:37 -0000      1.29
  @@ -294,14 +294,11 @@
       public Interpreter getInterpreter(String lang) {
           interpreter = bridgeContext.getInterpreter(lang);
           if (interpreter == null) {
  -            if (languages.contains(lang))
  +            if (languages.contains(lang)) {
                   // Already issued warning so just return null;
                   return null;
  -
  -            UserAgent ua = bridgeContext.getUserAgent();
  -            if (ua != null) {
  -                ua.displayError(new Exception("Unknown language: " + lang));
               }
  +
               // So we know we have processed this interpreter.
               languages.add(lang);
               return null;
  
  
  
  1.75      +17 -3     xml-batik/sources/org/apache/batik/bridge/BridgeContext.java
  
  Index: BridgeContext.java
  ===================================================================
  RCS file: /home/cvs/xml-batik/sources/org/apache/batik/bridge/BridgeContext.java,v
  retrieving revision 1.74
  retrieving revision 1.75
  diff -u -r1.74 -r1.75
  --- BridgeContext.java        14 Dec 2003 15:14:57 -0000      1.74
  +++ BridgeContext.java        24 Feb 2004 14:04:37 -0000      1.75
  @@ -472,9 +472,23 @@
           }
           Interpreter interpreter = (Interpreter)interpreterMap.get(language);
           if (interpreter == null) {
  -            interpreter = interpreterPool.createInterpreter(document, language);
  -            interpreterMap.put(language, interpreter);
  +            try {
  +                interpreter = interpreterPool.createInterpreter(document, language);
  +                interpreterMap.put(language, interpreter);
  +            } catch (Exception e) {
  +                if (userAgent != null) {
  +                    userAgent.displayError(e);
  +                    return null;
  +                }
  +            }
           }
  +
  +        if (interpreter == null) {
  +            if (userAgent != null) {
  +                userAgent.displayError(new Exception("Unknown language: " + 
language));
  +            }
  +        }
  +
           return interpreter;
       }
   
  
  
  
  1.17      +7 -12     xml-batik/sources/org/apache/batik/script/InterpreterPool.java
  
  Index: InterpreterPool.java
  ===================================================================
  RCS file: /home/cvs/xml-batik/sources/org/apache/batik/script/InterpreterPool.java,v
  retrieving revision 1.16
  retrieving revision 1.17
  diff -u -r1.16 -r1.17
  --- InterpreterPool.java      16 Sep 2003 01:12:52 -0000      1.16
  +++ InterpreterPool.java      24 Feb 2004 14:04:37 -0000      1.17
  @@ -149,17 +149,12 @@
           InterpreterFactory factory = (InterpreterFactory)factories.get(language);
           Interpreter interpreter = null;
           if (factory != null)
  -            try {
  -                interpreter = factory.createInterpreter
  -                    (((SVGOMDocument)document).getURLObject());
  -                if (document != null) {
  -                    interpreter.bindObject(BIND_NAME_DOCUMENT, document);
  -                }
  -            } catch (Exception t) {
  -                // may happen if the batik interpreters class is here but
  -                // not the scripting engine jar
  -                t.printStackTrace();
  -            }
  +            interpreter = factory.createInterpreter
  +                (((SVGOMDocument)document).getURLObject());
  +        if (document != null) {
  +            interpreter.bindObject(BIND_NAME_DOCUMENT, document);
  +        }
  +
           return interpreter;
       }
   
  
  
  
  1.5       +5 -2      
xml-batik/sources/org/apache/batik/script/rhino/BatikSecurityController.java
  
  Index: BatikSecurityController.java
  ===================================================================
  RCS file: 
/home/cvs/xml-batik/sources/org/apache/batik/script/rhino/BatikSecurityController.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- BatikSecurityController.java      20 Feb 2004 16:34:52 -0000      1.4
  +++ BatikSecurityController.java      24 Feb 2004 14:04:37 -0000      1.5
  @@ -79,13 +79,14 @@
        */
       public GeneratedClassLoader createClassLoader
           (final ClassLoader parentLoader, Object securityDomain) {
  +
           if (securityDomain instanceof RhinoClassLoader) {
               return (RhinoClassLoader)securityDomain;
           }
                
           // FIXX: This should be supported by intersecting perms.
           // Calling var script = Script(source); script(); is not supported
  -        throw new RuntimeException("NOT SUPPORTED");
  +        throw new SecurityException("Script() objects are not supported");
       }
   
       /**
  @@ -95,6 +96,7 @@
        * allowed by the current stack.
        */
       public Object getDynamicSecurityDomain(Object securityDomain) {
  +
           ClassLoader loader = (RhinoClassLoader)securityDomain;
           // Already have a rhino loader in place no need to
           // do anything (normally you would want to union the
  @@ -130,6 +132,7 @@
           }
   
           try {
  +            // acc = new AccessController(acc, acc.getDomainCombiner());
               return AccessController.doPrivileged
                   (new PrivilegedExceptionAction() {
                           public Object run() throws JavaScriptException {
  
  
  
  1.38      +2 -2      
xml-batik/sources/org/apache/batik/script/rhino/RhinoInterpreter.java
  
  Index: RhinoInterpreter.java
  ===================================================================
  RCS file: 
/home/cvs/xml-batik/sources/org/apache/batik/script/rhino/RhinoInterpreter.java,v
  retrieving revision 1.37
  retrieving revision 1.38
  diff -u -r1.37 -r1.38
  --- RhinoInterpreter.java     20 Feb 2004 16:34:52 -0000      1.37
  +++ RhinoInterpreter.java     24 Feb 2004 14:04:37 -0000      1.38
  @@ -190,7 +190,7 @@
               for (int i = 0; i < TO_BE_IMPORTED.length; i++) {
                   p[i] = new NativeJavaPackage(TO_BE_IMPORTED[i], rhinoClassLoader);
               } try {
  -              ScriptableObject.callMethod(globalObject, "importPackage", p);
  +                ScriptableObject.callMethod(globalObject, "importPackage", p);
               } catch (JavaScriptException e) {
                 // cannot happen as we know the method is there and
                 // the parameters are ok
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to