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]