/*
* 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.commons.jexl2;
import java.util.logging.Logger;
import org.apache.commons.jexl2.introspection.Sandbox;
import org.apache.commons.jexl2.introspection.SandboxUberspectImpl;
import org.apache.commons.jexl2.introspection.Uberspect;
/**
* Tests sandbox features.
*/
public class SandboxTest extends JexlTestCase {
static final Logger LOGGER = Logger.getLogger(VarTest.class.getName());
public static class Foo {
String name;
public String alias;
public Foo(String name) {
this.name = name;
this.alias = name + "-alias";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String Quux() {
return name + "-quux";
}
}
public void testCtorBlack() throws Exception {
String expr = "new('" + Foo.class.getName() + "', '42')";
Script script = JEXL.createScript(expr);
Object result;
result = script.execute(null);
assertEquals("42", ((Foo) result).getName());
Sandbox sandbox = new Sandbox();
sandbox.black(Foo.class.getName()).execute("");
Uberspect uber = new SandboxUberspectImpl(null, sandbox);
JexlEngine sjexl = new JexlEngine(uber, null, null, null);
sjexl.setStrict(true);
script = sjexl.createScript(expr);
try {
result = script.execute(null);
fail("ctor should not be accessible");
} catch (JexlException.Method xmethod) {
// ok, ctor should not have been accessible
LOGGER.info(xmethod.toString());
}
}
public void testMethodBlack() throws Exception {
String expr = "foo.Quux()";
Script script = JEXL.createScript(expr, "foo");
Foo foo = new Foo("42");
Object result;
result = script.execute(null, foo);
assertEquals(foo.Quux(), result);
Sandbox sandbox = new Sandbox();
sandbox.black(Foo.class.getName()).execute("Quux");
Uberspect uber = new SandboxUberspectImpl(null, sandbox);
JexlEngine sjexl = new JexlEngine(uber, null, null, null);
sjexl.setStrict(true);
script = sjexl.createScript(expr, "foo");
try {
result = script.execute(null, foo);
fail("Quux should not be accessible");
} catch (JexlException.Method xmethod) {
// ok, Quux should not have been accessible
LOGGER.info(xmethod.toString());
}
}
public void testGetBlack() throws Exception {
String expr = "foo.alias";
Script script = JEXL.createScript(expr, "foo");
Foo foo = new Foo("42");
Object result;
result = script.execute(null, foo);
assertEquals(foo.alias, result);
Sandbox sandbox = new Sandbox();
sandbox.black(Foo.class.getName()).read("alias");
Uberspect uber = new SandboxUberspectImpl(null, sandbox);
JexlEngine sjexl = new JexlEngine(uber, null, null, null);
sjexl.setStrict(true);
script = sjexl.createScript(expr, "foo");
try {
result = script.execute(null, foo);
fail("alias should not be accessible");
} catch (JexlException.Property xvar) {
// ok, alias should not have been accessible
LOGGER.info(xvar.toString());
}
}
public void testSetBlack() throws Exception {
String expr = "foo.alias = $0";
Script script = JEXL.createScript(expr, "foo", "$0");
Foo foo = new Foo("42");
Object result;
result = script.execute(null, foo, "43");
assertEquals("43", result);
Sandbox sandbox = new Sandbox();
sandbox.black(Foo.class.getName()).write("alias");
Uberspect uber = new SandboxUberspectImpl(null, sandbox);
JexlEngine sjexl = new JexlEngine(uber, null, null, null);
sjexl.setStrict(true);
script = sjexl.createScript(expr, "foo", "$0");
try {
result = script.execute(null, foo, "43");
fail("alias should not be accessible");
} catch (JexlException.Property xvar) {
// ok, alias should not have been accessible
LOGGER.info(xvar.toString());
}
}
public void testCtorWhite() throws Exception {
String expr = "new('" + Foo.class.getName() + "', '42')";
Script script;
Object result;
Sandbox sandbox = new Sandbox();
sandbox.white(Foo.class.getName()).execute("");
Uberspect uber = new SandboxUberspectImpl(null, sandbox);
JexlEngine sjexl = new JexlEngine(uber, null, null, null);
sjexl.setStrict(true);
script = sjexl.createScript(expr);
result = script.execute(null);
assertEquals("42", ((Foo) result).getName());
}
public void testMethodWhite() throws Exception {
Foo foo = new Foo("42");
String expr = "foo.Quux()";
Script script;
Object result;
Sandbox sandbox = new Sandbox();
sandbox.white(Foo.class.getName()).execute("Quux");
Uberspect uber = new SandboxUberspectImpl(null, sandbox);
JexlEngine sjexl = new JexlEngine(uber, null, null, null);
sjexl.setStrict(true);
script = sjexl.createScript(expr, "foo");
result = script.execute(null, foo);
assertEquals(foo.Quux(), result);
}
public void testGetWhite() throws Exception {
Foo foo = new Foo("42");
String expr = "foo.alias";
Script script;
Object result;
Sandbox sandbox = new Sandbox();
sandbox.white(Foo.class.getName()).read("alias");
sandbox.get(Foo.class.getName()).read().alias("alias", "ALIAS");
Uberspect uber = new SandboxUberspectImpl(null, sandbox);
JexlEngine sjexl = new JexlEngine(uber, null, null, null);
sjexl.setStrict(true);
script = sjexl.createScript(expr, "foo");
result = script.execute(null, foo);
assertEquals(foo.alias, result);
script = sjexl.createScript("foo.ALIAS", "foo");
result = script.execute(null, foo);
assertEquals(foo.alias, result);
}
public void testSetWhite() throws Exception {
Foo foo = new Foo("42");
String expr = "foo.alias = $0";
Script script;
Object result;
Sandbox sandbox = new Sandbox();
sandbox.white(Foo.class.getName()).write("alias");
Uberspect uber = new SandboxUberspectImpl(null, sandbox);
JexlEngine sjexl = new JexlEngine(uber, null, null, null);
sjexl.setStrict(true);
script = sjexl.createScript(expr, "foo", "$0");
result = script.execute(null, foo, "43");
assertEquals("43", result);
assertEquals("43", foo.alias);
}
public void testRestrict() throws Exception {
JexlContext context = new MapContext();
context.set("System", System.class);
Sandbox sandbox = new Sandbox();
// only allow call to currentTimeMillis (avoid exit, gc, loadLibrary, etc)
sandbox.white(System.class.getName()).execute("currentTimeMillis");
// can not create a new file
sandbox.black(java.io.File.class.getName()).execute("");
Uberspect uber = new SandboxUberspectImpl(null, sandbox);
JexlEngine sjexl = new JexlEngine(uber, null, null, null);
sjexl.setStrict(true);
String expr;
Script script;
Object result;
script = sjexl.createScript("System.exit()");
try {
result = script.execute(context);
fail("should not allow calling exit!");
} catch (JexlException xjexl) {
LOGGER.info(xjexl.toString());
}
script = sjexl.createScript("new('java.io.File', '/tmp/should-not-be-created')");
try {
result = script.execute(context);
fail("should not allow creating a file");
} catch (JexlException xjexl) {
LOGGER.info(xjexl.toString());
}
expr = "System.currentTimeMillis()";
script = sjexl.createScript("System.currentTimeMillis()");
result = script.execute(context);
assertNotNull(result);
}
}