Skip to content

Commit

Permalink
ADD: Testcasce with SecurityManager
Browse files Browse the repository at this point in the history
  • Loading branch information
rPraml committed Sep 20, 2021
1 parent f150c41 commit 0e01d89
Show file tree
Hide file tree
Showing 6 changed files with 226 additions and 0 deletions.
27 changes: 27 additions & 0 deletions testsrc/com/example/securitytest/SomeFactory.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

package com.example.securitytest;

/**
* Class for SecurityControllerTest.
*
* @author Roland Praml, FOCONIS AG
*/
public class SomeFactory {

public static int TEST = 42;

public SomeInterface create() {
try {
return (SomeInterface)
Class.forName("com.example.securitytest.impl.SomeClass").newInstance();
} catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
throw new RuntimeException("Could not create impl", e);
}
}
}
18 changes: 18 additions & 0 deletions testsrc/com/example/securitytest/SomeInterface.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

package com.example.securitytest;

/**
* Class for SecurityControllerTest.
*
* @author Roland Praml, FOCONIS AG
*/
public interface SomeInterface {

String foo();
}
33 changes: 33 additions & 0 deletions testsrc/com/example/securitytest/impl/SomeClass.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

package com.example.securitytest.impl;

import com.example.securitytest.SomeInterface;
import java.util.ArrayList;

/**
* Provides an implementation for SomeInterface. Defines two methods: <code>foo</code> overridden
* (defined by interface) and <code>bar</code> defined at this class.
*
* <p>If this class is excluded by the shutter, the method <code>bar</code> should not be accessible
* in scripts.
*
* @author Roland Praml, FOCONIS AG
*/
public class SomeClass extends ArrayList<String> implements SomeInterface {
private static final long serialVersionUID = 1L;

@Override
public String foo() {
return "FOO";
}

public String bar() {
return "BAR";
}
}
123 changes: 123 additions & 0 deletions testsrc/org/mozilla/javascript/tests/SecurityControllerTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
package org.mozilla.javascript.tests;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;

import java.net.MalformedURLException;
import java.net.URL;
import java.security.CodeSource;
import java.security.Permission;
import java.security.Permissions;
import java.security.Policy;
import java.security.ProtectionDomain;
import java.security.URIParameter;
import java.util.Enumeration;
import org.junit.BeforeClass;
import org.junit.Test;
import org.mozilla.javascript.ClassShutter;
import org.mozilla.javascript.EcmaError;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.SecurityController;
import org.mozilla.javascript.tools.shell.Global;
import org.mozilla.javascript.tools.shell.JavaPolicySecurity;

/** Perform some tests when we have a securityController in place. */
public class SecurityControllerTest {

private static ProtectionDomain UNTRUSTED_JAVASCRIPT;
private static ProtectionDomain ALLOW_IMPL_ACCESS;
private static ProtectionDomain RESTRICT_IMPL_ACCESS;
protected final Global global = new Global();

/** Sets up the security manager and loads the "grant-all-java.policy". */
static void setupSecurityManager() {}
/** Setup the security */
@BeforeClass
public static void setup() throws Exception {
URL url = SecurityControllerTest.class.getResource("grant-all-java.policy");
if (url != null) {
System.out.println("Initializing security manager with grant-all-java.policy");
System.setProperty("java.security.policy", url.toString());
Policy.getPolicy().refresh();
System.setSecurityManager(new SecurityManager());
}
SecurityController.initGlobal(new JavaPolicySecurity());

url = SecurityControllerTest.class.getResource("javascript.policy");
Policy policy = Policy.getInstance("JavaPolicy", new URIParameter(url.toURI()));
RESTRICT_IMPL_ACCESS = createProtectionDomain(policy, "RESTRICT_IMPL_ACCESS");
ALLOW_IMPL_ACCESS = createProtectionDomain(policy, "ALLOW_IMPL_ACCESS");
}

/** Creates a new protectionDomain with the given Code-Source Suffix. */
private static ProtectionDomain createProtectionDomain(Policy policy, String csSuffix)
throws MalformedURLException {
URL url = new URL(SecurityController.class.getResource("/"), csSuffix);
CodeSource cs = new CodeSource(url, (java.security.cert.Certificate[]) null);
Permissions perms = new Permissions();
Enumeration<Permission> elems = policy.getPermissions(cs).elements();
while (elems.hasMoreElements()) {
perms.add(elems.nextElement());
}
perms.setReadOnly();
return new ProtectionDomain(cs, perms, null, null);
}

@Test
public void testBarAccess() {
// f.create produces "SomeClass extends ArrayList<String> implements
// SomeInterface"
// we may access array methods, like 'size' defined by ArrayList,
// but not methods like 'bar' defined by SomeClass, because it is in a restricted package
String script =
"f = new com.example.securitytest.SomeFactory();\n"
+ "var i = f.create();\n"
+ "i.size();\n"
+ "i.bar();";

// try in allowed scope
runScript(script, ALLOW_IMPL_ACCESS);

try {
// in restricted scope, we expect an EcmaError
runScript(script, RESTRICT_IMPL_ACCESS);
fail("EcmaError expected");
} catch (EcmaError ee) {
assertEquals("TypeError: Cannot find function bar in object []. (#4)", ee.getMessage());
}

// try in allowed scope again
runScript(script, ALLOW_IMPL_ACCESS);
}

/**
* This classShutter checks the "rhino.visible.{pkg}" runtime property, which can be defined in
* a policy file. Note: Every other code in your stack-chain will need this permission also.
*/
private static class PolicyClassShutter implements ClassShutter {

@Override
public boolean visibleToScripts(String fullClassName) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
int idx = fullClassName.lastIndexOf('.');
if (idx != -1) {
String pkg = fullClassName.substring(0, idx);
sm.checkPermission(new RuntimePermission("rhino.visible." + pkg));
}
}
return true;
}
}

/** Compiles and runs the script with the given protection domain. */
private void runScript(String scriptSourceText, ProtectionDomain pd) {
Utils.runWithAllOptimizationLevels(
context -> {
context.setClassShutter(new PolicyClassShutter());
Scriptable scope = context.initStandardObjects(global);

return context.evaluateString(scope, scriptSourceText, "", 1, pd);
});
}
}
5 changes: 5 additions & 0 deletions testsrc/org/mozilla/javascript/tests/grant-all-java.policy
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// Grant everyone the following permission: (required for SecurityControllerTest)
grant {
// permission all;
permission java.security.AllPermission "", "";
};
20 changes: 20 additions & 0 deletions testsrc/org/mozilla/javascript/tests/javascript.policy
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Sample script, how to define different security codebases for javaScript.

grant codebase "file:${user.dir}/bin/main/ALLOW_IMPL_ACCESS" {
permission java.lang.RuntimePermission "rhino.visible.com";
permission java.lang.RuntimePermission "rhino.visible.com.example";
permission java.lang.RuntimePermission "rhino.visible.com.example.securitytest";
permission java.lang.RuntimePermission "rhino.visible.com.example.securitytest.*";
};

grant codebase "file:${user.dir}/bin/main/RESTRICT_IMPL_ACCESS" {
permission java.lang.RuntimePermission "rhino.visible.com";
permission java.lang.RuntimePermission "rhino.visible.com.example";
permission java.lang.RuntimePermission "rhino.visible.com.example.securitytest";
};

grant {
// grant every script access to java.lang and java.util (but not to java.util.*)
permission java.lang.RuntimePermission "rhino.visible.java";
permission java.lang.RuntimePermission "rhino.visible.java.*";
};

0 comments on commit 0e01d89

Please sign in to comment.