1 /* 2 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package jdk.nashorn.api.scripting.test; 27 28 import static org.testng.Assert.fail; 29 import java.lang.reflect.InvocationHandler; 30 import java.lang.reflect.Method; 31 import java.lang.reflect.Proxy; 32 import javax.script.ScriptEngine; 33 import javax.script.ScriptEngineManager; 34 import javax.script.ScriptException; 35 import jdk.nashorn.api.scripting.ClassFilter; 36 import jdk.nashorn.api.scripting.NashornScriptEngineFactory; 37 import org.testng.annotations.Test; 38 39 /** 40 * jsr223 tests for security access checks. 41 * 42 * @test 43 * @run testng/othervm jdk.nashorn.api.scripting.test.ScriptEngineSecurityTest 44 */ 45 @SuppressWarnings("javadoc") 46 public class ScriptEngineSecurityTest { 47 48 private static void log(final String msg) { 49 org.testng.Reporter.log(msg, true); 50 } 51 52 @Test 53 public void securityPackagesTest() { 54 if (System.getSecurityManager() == null) { 55 // pass vacuously 56 return; 57 } 58 59 final ScriptEngineManager m = new ScriptEngineManager(); 60 final ScriptEngine e = m.getEngineByName("nashorn"); 61 try { 62 e.eval("var v = Packages.sun.misc.Unsafe;"); 63 fail("should have thrown SecurityException"); 64 } catch (final Exception exp) { 65 if (exp instanceof SecurityException) { 66 log("got " + exp + " as expected"); 67 } else { 68 fail(exp.getMessage()); 69 } 70 } 71 } 72 73 @Test 74 public void securityJavaTypeTest() { 75 if (System.getSecurityManager() == null) { 76 // pass vacuously 77 return; 78 } 79 80 final ScriptEngineManager m = new ScriptEngineManager(); 81 final ScriptEngine e = m.getEngineByName("nashorn"); 82 try { 83 e.eval("var v = Java.type('sun.misc.Unsafe');"); 84 fail("should have thrown SecurityException"); 85 } catch (final Exception exp) { 86 if (exp instanceof SecurityException) { 87 log("got " + exp + " as expected"); 88 } else { 89 fail(exp.getMessage()); 90 } 91 } 92 } 93 94 @Test 95 public void securityClassForNameTest() { 96 if (System.getSecurityManager() == null) { 97 // pass vacuously 98 return; 99 } 100 101 final ScriptEngineManager m = new ScriptEngineManager(); 102 final ScriptEngine e = m.getEngineByName("nashorn"); 103 try { 104 e.eval("var v = java.lang.Class.forName('sun.misc.Unsafe');"); 105 fail("should have thrown SecurityException"); 106 } catch (final Exception exp) { 107 if (exp instanceof SecurityException) { 108 log("got " + exp + " as expected"); 109 } else { 110 fail(exp.getMessage()); 111 } 112 } 113 } 114 115 @Test 116 public void securitySystemExit() { 117 if (System.getSecurityManager() == null) { 118 // pass vacuously 119 return; 120 } 121 122 final ScriptEngineManager m = new ScriptEngineManager(); 123 final ScriptEngine e = m.getEngineByName("nashorn"); 124 try { 125 e.eval("java.lang.System.exit(0);"); 126 fail("should have thrown SecurityException"); 127 } catch (final Exception exp) { 128 if (exp instanceof SecurityException) { 129 log("got " + exp + " as expected"); 130 } else { 131 fail(exp.getMessage()); 132 } 133 } 134 } 135 136 137 @Test 138 public void securitySystemExitFromFinalizerThread() throws ScriptException { 139 if (System.getSecurityManager() == null) { 140 // pass vacuously 141 return; 142 } 143 144 final ScriptEngineManager m = new ScriptEngineManager(); 145 final ScriptEngine e = m.getEngineByName("nashorn"); 146 e.eval("var o = Java.extend(Java.type('javax.imageio.spi.ServiceRegistry'), { deregisterAll: this.exit.bind(null, 1234)});\n" + 147 "new o(new java.util.ArrayList().iterator())"); 148 System.gc(); 149 System.runFinalization(); 150 // NOTE: this test just exits the VM if it fails. 151 } 152 153 @Test 154 public void securitySystemLoadLibrary() { 155 if (System.getSecurityManager() == null) { 156 // pass vacuously 157 return; 158 } 159 160 final ScriptEngineManager m = new ScriptEngineManager(); 161 final ScriptEngine e = m.getEngineByName("nashorn"); 162 try { 163 e.eval("java.lang.System.loadLibrary('foo');"); 164 fail("should have thrown SecurityException"); 165 } catch (final Exception exp) { 166 if (exp instanceof SecurityException) { 167 log("got " + exp + " as expected"); 168 } else { 169 fail(exp.getMessage()); 170 } 171 } 172 } 173 174 // @bug 8032948: Nashorn linkages awry 175 @SuppressWarnings("serial") 176 public static class FakeProxy extends Proxy { 177 public FakeProxy(final InvocationHandler ih) { 178 super(ih); 179 } 180 181 public static Class<?> makeProxyClass(final ClassLoader cl, final Class<?>... ifaces) { 182 return Proxy.getProxyClass(cl, ifaces); 183 } 184 } 185 186 @Test 187 public void fakeProxySubclassAccessCheckTest() { 188 if (System.getSecurityManager() == null) { 189 // pass vacuously 190 return; 191 } 192 193 final ScriptEngineManager m = new ScriptEngineManager(); 194 final ScriptEngine e = m.getEngineByName("nashorn"); 195 196 e.put("name", ScriptEngineSecurityTest.class.getName()); 197 e.put("cl", ScriptEngineSecurityTest.class.getClassLoader()); 198 e.put("intfs", new Class[] { Runnable.class }); 199 200 final String getClass = "Java.type(name + '$FakeProxy').getProxyClass(cl, intfs);"; 201 202 // Should not be able to call static methods of Proxy via fake subclass 203 try { 204 e.eval(getClass); 205 fail("should have thrown SecurityException"); 206 } catch (final Exception exp) { 207 if (! (exp instanceof SecurityException)) { 208 fail("SecurityException expected, got " + exp); 209 } 210 } 211 } 212 213 @Test 214 public void fakeProxySubclassAccessCheckTest2() { 215 if (System.getSecurityManager() == null) { 216 // pass vacuously 217 return; 218 } 219 220 final ScriptEngineManager m = new ScriptEngineManager(); 221 final ScriptEngine e = m.getEngineByName("nashorn"); 222 223 e.put("name", ScriptEngineSecurityTest.class.getName()); 224 e.put("cl", ScriptEngineSecurityTest.class.getClassLoader()); 225 e.put("intfs", new Class[] { Runnable.class }); 226 227 final String getClass = "Java.type(name + '$FakeProxy').makeProxyClass(cl, intfs);"; 228 229 // Should not be able to call static methods of Proxy via fake subclass 230 try { 231 e.eval(getClass); 232 fail("should have thrown SecurityException"); 233 } catch (final Exception exp) { 234 if (! (exp instanceof SecurityException)) { 235 fail("SecurityException expected, got " + exp); 236 } 237 } 238 } 239 240 @Test 241 public static void proxyStaticAccessCheckTest() { 242 if (System.getSecurityManager() == null) { 243 // pass vacuously 244 return; 245 } 246 247 final ScriptEngineManager m = new ScriptEngineManager(); 248 final ScriptEngine e = m.getEngineByName("nashorn"); 249 final Runnable r = (Runnable)Proxy.newProxyInstance( 250 ScriptEngineSecurityTest.class.getClassLoader(), 251 new Class[] { Runnable.class }, 252 new InvocationHandler() { 253 @Override 254 public Object invoke(final Object p, final Method mtd, final Object[] a) { 255 return null; 256 } 257 }); 258 259 e.put("rc", r.getClass()); 260 e.put("cl", ScriptEngineSecurityTest.class.getClassLoader()); 261 e.put("intfs", new Class[] { Runnable.class }); 262 263 // make sure static methods of Proxy is not accessible via subclass 264 try { 265 e.eval("rc.static.getProxyClass(cl, intfs)"); 266 fail("Should have thrown SecurityException"); 267 } catch (final Exception exp) { 268 if (! (exp instanceof SecurityException)) { 269 fail("SecurityException expected, got " + exp); 270 } 271 } 272 } 273 274 275 @Test 276 public void nashornConfigSecurityTest() { 277 if (System.getSecurityManager() == null) { 278 // pass vacuously 279 return; 280 } 281 282 final NashornScriptEngineFactory fac = new NashornScriptEngineFactory(); 283 try { 284 fac.getScriptEngine(new ClassFilter() { 285 @Override 286 public boolean exposeToScripts(final String name) { 287 return true; 288 } 289 }); 290 fail("SecurityException should have been thrown"); 291 } catch (final SecurityException e) { 292 //empty 293 } 294 } 295 296 @Test 297 public void nashornConfigSecurityTest2() { 298 if (System.getSecurityManager() == null) { 299 // pass vacuously 300 return; 301 } 302 303 final NashornScriptEngineFactory fac = new NashornScriptEngineFactory(); 304 try { 305 fac.getScriptEngine(new String[0], null, new ClassFilter() { 306 @Override 307 public boolean exposeToScripts(final String name) { 308 return true; 309 } 310 }); 311 fail("SecurityException should have been thrown"); 312 } catch (final SecurityException e) { 313 //empty 314 } 315 } 316 }