/************************************************************************** * Parts copyright (c) 2001 by Punch Telematix. All rights reserved. * * Parts copyright (c) 2009 by /k/ Embedded Java Solutions. * * All rights reserved. * * * * Redistribution and use in source and binary forms, with or without * * modification, are permitted provided that the following conditions * * are met: * * 1. Redistributions of source code must retain the above copyright * * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * * notice, this list of conditions and the following disclaimer in the * * documentation and/or other materials provided with the distribution. * * 3. Neither the name of Punch Telematix or of /k/ Embedded Java Solutions* * nor the names of other contributors may be used to endorse or promote* * products derived from this software without specific prior written * * permission. * * * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED * * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * * IN NO EVENT SHALL PUNCH TELEMATIX, /K/ EMBEDDED JAVA SOLUTIONS OR OTHER * * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * **************************************************************************/ package java.lang; import java.io.FileDescriptor; import java.io.FilePermission; import java.lang.reflect.Constructor; import java.net.InetAddress; import java.net.SocketPermission; import java.security.AccessControlContext; import java.security.Permission; import java.security.SecurityPermission; import java.util.PropertyPermission; /** The default SecurityManager for Mika. ** If USE_SECURITY_MANAGER is set in wonka.vm.SecurityConfiguration ** then this is a real security manager which uses the AccessController ** to implement all checks: otherwise it is a null security manager which ** allows everyone to do everything. */ public class SecurityManager { /** Field inCheck is set true iff a security check is in progress ** AND we call another method of SecurityManager (which might ** have been overridden). Otherwise we don't bother. ** Note that use of this variable is deprecated. */ protected boolean inCheck = false; /** ** Tnis boolean is set when permission to create a class loader is granted. ** Until then we can be sure that no classes created by such a class loader ** can be on the stack, and therefore we can skip some checks (and avoid ** some nasty recursion). */ private boolean haveUserDefinedClassLoaders; /** This is what one might call ``a workaround''. ** The problem is that we may not have an AWT, and in that case ** there will be no class java.awt.AWTPermission. So in our ** static initializer we try to load that class, and if the attempt ** fails then all calls to checkPrintJobAccess, checkSystemClipboardAccess, ** checkAwtEventQueueAccess, and checkTopLevelWindow will fail. */ static private Class awtPermission; /** The constructor of awtPermission which takes a single string as argument. */ static private Constructor awtpCon; static { try { awtPermission = Class.forName("java.awt.AWTPermission"); Class[] params = new Class[1]; params[0] = String.class; awtpCon = awtPermission.getConstructor(params); } catch (Exception e) { e.printStackTrace(); } } /** Default constructor, public in Java2. ** Performs a security check iff USE_ACCESS_CONTROLLER or USE_SECURITY_MANAGER ** is set in wonka.vm.SecurityConfiguration. */ public SecurityManager() throws SecurityException { if (wonka.vm.SecurityConfiguration.ENABLE_SECURITY_CHECKS) { java.security.AccessController.checkPermission(new RuntimePermission("createSecurityManager")); } } /** A wrapper for AccessController.checkPermission(perm), or a no-op if ** USE_SECURITY_MANAGER is not set in wonka.vm.SecurityConfiguration. */ public void checkPermission(Permission perm) { if (wonka.vm.SecurityConfiguration.ENABLE_SECURITY_CHECKS) { try { inCheck = true; java.security.AccessController.getContext().checkPermission(perm); } finally { inCheck = false; } } } /** A wrapper for AccessController.checkPermission(perm). */ public void checkPermission(Permission perm, Object context) { if (wonka.vm.SecurityConfiguration.ENABLE_SECURITY_CHECKS) { try { inCheck = true; java.security.AccessControlContext acc = (AccessControlContext)context; acc.checkPermission(perm); } catch (ClassCastException cce) { throw new SecurityException("Not an AccessControlContext: "+context); } finally { inCheck = false; } } } /** Get the security context (i.e., AccessControlContext) currently applicable. */ public Object getSecurityContext() { return java.security.AccessController.getContext(); } /** Get the thread group in which new threads should be instantiated. ** Used by the constructors of java.lang.Thread which do not specifiy the ThreadGroup. ** This implementation just returns the ThreadGroup of the current thread. ** Override this if you feel that new threads should be instantiated somewhere else (e.g. in a Realm ...). */ public ThreadGroup getThreadGroup() { return Thread.currentThread().getThreadGroup(); } /** The Class[] returned contains one element for every method on the stack, starting with the method which called getClassContext(). ** Provided for use by user-defined SecurityManager's, we don't use this internally. ** Looks at all frames, not just up to the most recent doPrivileged. ** Includes native methods, including invoke(). */ protected native Class[] getClassContext(); /** The Class[] returned contains one element for every method on the stack, starting with the method which called getClassContext(), up to the most recent privileged frame. ** Includes native methods, including invoke(). */ private native Class[] getNonPrivilegedClassContext(); /** Gets the stack depth of the most recent call to a method of the given class. ** (But does it include this call? Who cares...). ** Returns -1 if not found. ** Looks at all frames, not just up to the most recent doPrivileged. ** Deprecated. */ protected int classDepth(String name) { System.err.println("SecurityManager method classDepth() is deprecated!"); Class [] classes = getClassContext(); try { Class cl = Class.forName(name); for (int i = 0; i < classes.length; ++i) { if (classes[i] == cl) { return i; } } } catch (ClassNotFoundException cnfe) { // Fall through, return -1 } return -1; } /** Get the class loader of the topmost class on the stack that was not loaded by the system class loader or bootstrap class loader. ** Only looks at frames up to the most recent doPrivileged, but does include native methods, including invoke(). ** Always returns null if caller has AllPermission. ** Deprecated. */ protected ClassLoader currentClassLoader() { Class clc = currentLoadedClass(); return clc == null ? null : clc.loader; } /** Get the topmost class on the stack that was not loaded by the system class loader or bootstrap class loader. ** Only looks at frames up to the most recent doPrivileged, but does include native methods, including invoke(). ** Always returns null if caller has AllPermission. ** Deprecated. */ protected Class currentLoadedClass() { if (!haveUserDefinedClassLoaders) { return null; } try { checkPermission(new java.security.AllPermission()); return null; } catch (SecurityException se) { } Class [] classes = getNonPrivilegedClassContext(); for (int i = 0; i < classes.length; ++i) { ClassLoader cl = classes[i].loader; if (!ClassLoader.isSystemClassLoader(cl)) { return classes[i]; } } return null; } /** Get the depth on the stack of the topmost class that was not loaded by the system class loader or bootstrap class loader. ** Only looks at frames up to the most recent doPrivileged, but does include native methods, including invoke(). ** Always returns null if caller has AllPermission. ** Deprecated. */ protected int classLoaderDepth() { if (currentLoadedClass() == null) { return -1; } try { checkPermission(new java.security.AllPermission()); return -1; } catch (SecurityException se) { } Class [] classes = getNonPrivilegedClassContext(); for (int i = 0; i < classes.length; ++i) { ClassLoader cl = classes[i].loader; if (!ClassLoader.isSystemClassLoader(cl)) { return i; } } return -1; } /** See whether the given class is in the stack. ** Deprecated. */ protected boolean inClass(String name) { return classDepth(name) >= 0; } /** See whether any non-system class is in the stack. ** See currentClassLoader(). ** Deprecated. */ protected boolean inClassLoader() { return currentClassLoader() != null; } /** Get the value of the inCheck field. Deprecated. */ public synchronized boolean getInCheck() { return inCheck; } /** Checks whether the caller has permission to create a ClassLoader. ** If you override this, you should include a call to super.checkCreateClassLoader(). */ public void checkCreateClassLoader() throws SecurityException { if (haveUserDefinedClassLoaders) { checkPermission(new RuntimePermission("createClassLoader")); } // If we passed the check then user-defined class loaders may be created haveUserDefinedClassLoaders = true; } /** Checks whether the caller has permission to modify Thread t. ** The check is only applied if t belongs to the system ThreadGroup. ** If you override this, you should include a call to super.checkAccess(). ** (You should probably also allow access to any thread which has ** RuntimePermission("modifyThread"), so that system code can still create threads). */ public void checkAccess(Thread t) throws SecurityException { if (t.getThreadGroup().getParent() != null) { return; } if (haveUserDefinedClassLoaders) { checkPermission(new RuntimePermission("modifyThread")); } } /** Checks whether the caller has permission to modify ThreadGroup g. ** The check is only applied if t belongs to the system ThreadGroup. ** If you override this, you should include a call to super.checkAccess(). ** (You should probably also allow access to any thread which has ** RuntimePermission("modifyThreadGroup"), so that system code can still create threads). */ public void checkAccess(ThreadGroup g) throws SecurityException { if (g.getParent() != null) { return; } if (haveUserDefinedClassLoaders) { checkPermission(new RuntimePermission("modifyThreadGroup")); } } /** Checks whether the caller has access to the declared members of ``cl''. ** If you override this, you should include a call to super.checkMemberAccess(). */ public void checkMemberAccess(Class cl, int mtype) throws SecurityException { if (haveUserDefinedClassLoaders && mtype != java.lang.reflect.Member.PUBLIC && cl.loader != currentClassLoader()) { checkPermission(new RuntimePermission("accessDeclaredMembers."+cl.getName())); } } /** Checks whether the caller is allowed to exit the VM. ** If you override this, you should include a call to super.checkExit(). ** The `status' argument is not used. */ public void checkExit(int status) throws SecurityException { if (haveUserDefinedClassLoaders) { checkPermission(new RuntimePermission("exitVM")); } } /** Checks whether the caller is allowed to execute the specified command. ** If you override this, you should include a call to super.checkExecute(). ** Note the implicit assumption that all commands are the names of files. */ public void checkExec(String cmd) throws SecurityException { if (haveUserDefinedClassLoaders) { checkPermission(new FilePermission(cmd, "execute")); } } /** Checks whether the caller has permission to use IP Multicast. ** If you override this, you should include a call to super.checkMulticast(). */ public void checkMulticast(InetAddress addr) throws SecurityException { if (haveUserDefinedClassLoaders) { checkPermission(new SocketPermission(addr.getHostAddress(), "accept,connect")); } } /** Checks whether the caller has permission to use IP Multicast. ** If you override this, you should include a call to super.checkMulticast(). ** Note: parameter `ttl' is not used (what's it there for?) */ public void checkMulticast(InetAddress addr, byte ttl) throws SecurityException { if (haveUserDefinedClassLoaders) { checkPermission(new SocketPermission(addr.getHostAddress(), "accept,connect")); } } /** Checks whether the caller has permission to read the given system property. ** If you override this, you should include a call to super.checkPropertyAccess(). */ public void checkPropertyAccess(String propname) throws SecurityException { if (haveUserDefinedClassLoaders) { checkPermission(new PropertyPermission(propname, "read")); } } /** Checks whether the caller has permission to read or modify the system properties as a whole. ** If you override this, you should include a call to super.checkPropertiesAccess(). */ public void checkPropertiesAccess() throws SecurityException { if (haveUserDefinedClassLoaders) { checkPermission(new PropertyPermission("*", "read,write")); } } /** Checks whether the caller has the SecurityPermission called ``target''. ** If you override this, you should include a call to super.checkPropertiesAccess(). */ public void checkSecurityAccess(String target) throws SecurityException { if (haveUserDefinedClassLoaders) { checkPermission(new SecurityPermission(target)); } } /** Checks whether the caller has permission to load library ``libname''. ** If you override this, you should include a call to super.checkLink(). */ public void checkLink(String libname) throws SecurityException { if (haveUserDefinedClassLoaders) { checkPermission(new RuntimePermission("loadLibrary."+libname)); } } /** Checks whether the caller has permission to read the file descriptor `fd'. ** If you override this, you should include a call to super.checkRead(). ** Parameter `fd' is not used. */ public void checkRead(FileDescriptor fd) throws SecurityException { if (haveUserDefinedClassLoaders) { checkPermission(new RuntimePermission("readFileDescriptor")); } } /** Checks whether the caller has permission to read the file ``file''. ** If you override this, you should include a call to super.checkRead(). */ public void checkRead(String file) throws SecurityException { if (haveUserDefinedClassLoaders) { checkPermission(new FilePermission(file,"read")); } } /** Checks whether the given context has permission to read the file ``file''. */ public void checkRead(String file, Object context) throws SecurityException { if (haveUserDefinedClassLoaders) { checkPermission(new FilePermission(file,"read"), context); } } /** Checks whether the caller has permission to write to the file `fd'. ** If you override this, you should include a call to super.checkWrite(). ** Parameter `fd' is not used in the default version. */ public void checkWrite(FileDescriptor fd) throws SecurityException { if (haveUserDefinedClassLoaders) { checkPermission(new RuntimePermission("writeFileDescriptor")); } } /** Checks whether the caller has permission to write to the file ``file''. ** If you override this, you should include a call to super.checkWrite(). */ public void checkWrite(String file) throws SecurityException { if (haveUserDefinedClassLoaders) { checkPermission(new FilePermission(file,"write")); } } public void checkDelete(String file) throws SecurityException { if (haveUserDefinedClassLoaders) { checkPermission(new FilePermission(file,"delete")); } } /** Checks whether the caller has permission to connect to the given port. ** If you override this, you should include a call to super.checkConnect(). */ public void checkConnect(String host, int port) throws SecurityException { if (haveUserDefinedClassLoaders) { if (port == -1) { checkPermission(new SocketPermission(host,"resolve")); } else { checkPermission(new SocketPermission(host+":"+port,"connect")); } } } /** Checks whether the given context has permission to connect to the given port. ** If you override this, you should include a call to super.checkConnect(). */ public void checkConnect(String host, int port, Object context) throws SecurityException { if (haveUserDefinedClassLoaders) { if (port == -1) { checkPermission(new SocketPermission(host,"resolve"), context); } else { checkPermission(new SocketPermission(host+":"+port,"connect"), context); } } } /** Checks whether the caller has permission to listen to the given port. ** If you override this, you should include a call to super.checkListen(). */ public void checkListen(int port) throws SecurityException { if (haveUserDefinedClassLoaders) { if (port == 0) { checkPermission(new SocketPermission("localhost:1024-","listen")); } else { checkPermission(new SocketPermission("localhost:"+port,"listen")); } } } /** Checks whether the caller has permission to accept incoming connections. ** If you override this, you should include a call to super.checkAccept(). */ public void checkAccept(String host, int port) throws SecurityException { if (haveUserDefinedClassLoaders) { checkPermission(new SocketPermission(host+":"+port,"accept")); } } /** Checks whether the caller has permission to initiate a print job. ** If you override this, you should include a call to super.checkPrintJobAccess(). */ public void checkPrintJobAccess() throws SecurityException { if (awtPermission != null) { Object[] params = new Object[1]; params[0] = new String("queuePrintJob"); Permission perm; try { perm = (Permission)awtpCon.newInstance(params); } catch (Exception e) { e.printStackTrace(); throw new SecurityException("Failed to create an AWTPermission? "+e); } checkPermission(perm); } else { throw new SecurityException("No AWT present?"); } } /** Checks whether the caller has permission to access the AWT system clipboard. ** If you override this, you should include a call to super.checkSystemClipboardAccess(). */ public void checkSystemClipboardAccess() throws SecurityException { if (awtPermission != null) { Object[] params = new Object[1]; params[0] = new String("accessClipboard"); Permission perm; try { perm = (Permission)awtpCon.newInstance(params); } catch (Exception e) { e.printStackTrace(); throw new SecurityException("Failed to create an AWTPermission? "+e); } checkPermission(perm); } else { throw new SecurityException("No AWT present?"); } } /** Checks whether the caller has permission to access the AWT event queue. ** If you override this, you should include a call to super.checkAwtEventQueueAccess(). */ public void checkAwtEventQueueAccess() throws SecurityException { if (awtPermission != null) { Object[] params = new Object[1]; params[0] = new String("accessEventQueue"); Permission perm; try { perm = (Permission)awtpCon.newInstance(params); } catch (Exception e) { e.printStackTrace(); throw new SecurityException("Failed to create an AWTPermission? "+e); } checkPermission(perm); } else { throw new SecurityException("No AWT present?"); } } /** Checks whether the caller has permission to set the socket factories used by the java.net code. ** If you override this, you should include a call to super.checkSetFactory(). */ public void checkSetFactory() throws SecurityException { if (haveUserDefinedClassLoaders) { checkPermission(new RuntimePermission("setFactory")); } } /** Checks whether the caller is trusted to bring up the specified window. ** If you override this, you should include a call to super.checkTopLevelWindow(). ** Note that this method anomolously returns `true' if the caller is ** trusted, `false' otherwise. The parameter (`window') is not used. */ public boolean checkTopLevelWindow(Object window) throws SecurityException { if (awtPermission != null) { Object[] params = new Object[1]; params[0] = new String("topLevelWindowPermission"); Permission perm; try { perm = (Permission)awtpCon.newInstance(params); } catch (Exception e) { e.printStackTrace(); return false; } try { checkPermission(perm); return true; } catch (SecurityException se) { return false; } } else { return false; } } /** Checks whether the caller has access to the given package. ** If you override this, you should include a call to super.checkPackageAccess(). */ public void checkPackageAccess(String packageName) throws SecurityException { String restricteds = java.security.Security.getProperty("package.access"); if (restricteds == null) { restricteds = "wonka,com.acunia.wonka"; } int comma = restricteds.indexOf(','); String arestricted; while (comma >= 0) { arestricted = restricteds.substring(0,comma); if (packageName.equals(arestricted) || packageName.startsWith(arestricted) && packageName.charAt(arestricted.length()) == '.') { checkPermission(new RuntimePermission("accessClassInPackage."+packageName)); } restricteds = restricteds.substring(comma+1); comma = restricteds.indexOf(','); } arestricted = restricteds; if (packageName.equals(arestricted) || packageName.startsWith(arestricted) && packageName.charAt(arestricted.length()) == '.') { checkPermission(new RuntimePermission("accessClassInPackage."+packageName)); } } /** Checks whether the caller has permission to define classes in the given package. ** If you override this, you should include a call to super.checkPackageDefinition(). */ public void checkPackageDefinition(String packageName) throws SecurityException { String restricteds = java.security.Security.getProperty("package.definition"); if (restricteds == null) { restricteds = "java,wonka,com.acunia.wonka"; } int comma = restricteds.indexOf(','); String arestricted; while (comma >= 0) { arestricted = restricteds.substring(0,comma); if (packageName.equals(arestricted) || packageName.startsWith(arestricted) && packageName.charAt(arestricted.length()) == '.') { checkPermission(new RuntimePermission("defineClassInPackage."+packageName)); } restricteds = restricteds.substring(comma+1); comma = restricteds.indexOf(','); } arestricted = restricteds; if (packageName.equals(arestricted) || packageName.startsWith(arestricted) && packageName.charAt(arestricted.length()) == '.') { checkPermission(new RuntimePermission("defineClassInPackage."+packageName)); } } }