diff options
author | Eric Blake <ebb9@byu.net> | 2002-03-06 19:44:44 +0000 |
---|---|---|
committer | Eric Blake <ebb9@byu.net> | 2002-03-06 19:44:44 +0000 |
commit | 17c3f9b21a1503325cafd893332decf6c003a916 (patch) | |
tree | b76fe7e6ed37726c5687bb3d2eacd444561c61e5 /java | |
parent | e2c44b08d79dbbbb6ddd4d1544a90d4d1cc5f8d2 (diff) | |
download | classpath-17c3f9b21a1503325cafd893332decf6c003a916.tar.gz |
2002-03-06 Eric Blake <ebb9@email.byu.edu>
* java/lang/RuntimePermission.java: Improve Javadoc.
* java/lang/SecurityManager.java: Improve Javadoc and formatting.
* java/lang/System.java (setIn, setOut, setErr): Add required
security check.
(defaultProperties): Add a default, to allow clean resetting of
properties back to the VM startup state.
(setProperties): Correctly reset properties to default state.
* native/jni/java-lang/java_lang_System.c: Update method
signatures for changing I/O.
* include/java_lang_System.h: Ditto.
* vm/reference/java/lang/Runtime.java: Add shutdown hook
capability, as well as updating the exec calls.
* vm/reference/java/lang/VMSecurityManager.java: Improve Javadoc.
* java/util/PropertyPermission.java: Fix implication bugs.
* java/util/PropertyPermissionCollection.java: Ditto.
Diffstat (limited to 'java')
-rw-r--r-- | java/lang/RuntimePermission.java | 156 | ||||
-rw-r--r-- | java/lang/SecurityManager.java | 1703 | ||||
-rw-r--r-- | java/lang/System.java | 332 | ||||
-rw-r--r-- | java/util/PropertyPermission.java | 24 | ||||
-rw-r--r-- | java/util/PropertyPermissionCollection.java | 25 |
5 files changed, 1305 insertions, 935 deletions
diff --git a/java/lang/RuntimePermission.java b/java/lang/RuntimePermission.java index 81bc44c1e..0b5b5f878 100644 --- a/java/lang/RuntimePermission.java +++ b/java/lang/RuntimePermission.java @@ -1,5 +1,5 @@ -/* RuntimePermission.java - Copyright (C) 1998, 2000 Free Software Foundation, Inc. +/* RuntimePermission.java -- permission for a secure runtime action + Copyright (C) 1998, 2000, 2002 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -7,7 +7,7 @@ GNU Classpath is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. - + GNU Classpath is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU @@ -38,14 +38,14 @@ exception statement from your version. */ package java.lang; -import java.security.*; +import java.security.BasicPermission; /** * A <code>RuntimePermission</code> contains a permission name, but no * actions list. This means you either have the permission or you don't. * * Permission names have the follow the hierarchial property naming - * convention. In addition, an asterisk may appear at the end of a + * convention. In addition, an asterisk may appear at the end of a * name if following a period or by itself. * * <table border=1> @@ -53,112 +53,156 @@ import java.security.*; * <tr><td>"accessClassInPackage.*","*"</td> * <td>"**", "*x", "*.a"</td></tr> * </table> - * <br> - * - * The following table provides a list of all the possible RuntimePermission - * permission names with a description of what that permission allows. * <br> + * + * The following table provides a list of all the possible RuntimePermission + * permission names with a description of what that permission allows.<br> * <table border=1> - * <tr><th>Permission Name</th><th>Permission Allows</th></tr> + * <tr><th>Permission Name</th><th>Permission Allows</th><th>Risks</th</tr> * <tr> * <td><code>createClassLoader</code></td> - * <td>creation of a class loader</td></tr> + * <td>creation of a class loader</td> + * <td>a class loader can load rogue classes which bypass all security + * permissions</td></tr> * <tr> * <td><code>getClassLoader</code></td> - * <td>retrieval of the class loader for the calling class</td></tr> + * <td>retrieval of the class loader for the calling class</td> + * <td>rogue code could load classes not otherwise available</td></tr> * <tr> * <td><code>setContextClassLoader</code></td> - * <td>allows the setting of the context class loader used by a - * thread including system threads</td></tr> + * <td>allows the setting of the context class loader used by a thread</td> + * <td>rogue code could change the context class loader needed by system + * threads</td></tr> * <tr> * <td><code>setSecurityManager</code></td> - * <td>allows the application to replace the security manager with - * another, possibly less restrictive one.</td></tr> + * <td>allows the application to replace the security manager</td> + * <td>the new manager may be less restrictive, so that rogue code can + * bypass existing security checks</td></tr> * <tr> * <td><code>createSecurityManager</code></td> - * <td>allows the application to create a new security manager</td></tr> + * <td>allows the application to create a new security manager</td> + * <td>rogue code can use the new security manager to discover information + * about the execution stack</td></tr> * <tr> * <td><code>exitVM</code></td> - * <td>allows the application to halt the virtual machine</td></tr> + * <td>allows the application to halt the virtual machine</td> + * <td>rogue code can mount a denial-of-service attack by killing the + * virtual machine</td></tr> + * <tr> + * <td><code>shutdownHooks</code></td> + * <td>allows registration and modification of shutdown hooks</td> + * <td>rogue code can add a hook that interferes with clean + * virtual machine shutdown</td></tr> * <tr> * <td><code>setFactory</code></td> - * <td>allows the application to set the socket factory for socket, - * server socket, stream handler, or RMI socket factory.</td></tr> + * <td>allows the application to set the socket factory for socket, + * server socket, stream handler, or RMI socket factory.</td> + * <td>rogue code can create a rogue network object which mangles or + * intercepts data</td></tr> * <tr> * <td><code>setIO</code></td> - * <td>allows the application to set System.out, System.in, and - * System.err</td></tr> + * <td>allows the application to set System.out, System.in, and + * System.err</td> + * <td>rogue code could sniff user input and intercept or mangle + * output</td></tr> * <tr> * <td><code>modifyThread</code></td> * <td>allows the application to modify any thread in the virtual machine * using any of the methods <code>stop</code>, <code>resume</code>, - * <code>suspend</code>, <code>setPriority</code>, and - * <code>setName</code> of classs <code>Thread</code></td></tr> + * <code>suspend</code>, <code>setPriority</code>, and + * <code>setName</code> of classs <code>Thread</code></td> + * <td>rogue code could adversely modify system or user threads</td></tr> * <tr> * <td><code>stopThread</code></td> * <td>allows the application to <code>stop</code> any thread it has - * access to in the system</td></tr> + * access to in the system</td> + * <td>rogue code can stop arbitrary threads</td></tr> * <tr> * <td><code>modifyThreadGroup</td> * <td>allows the application to modify thread groups using any of the - * methods <code>destroy</code>, <code>resume</code>, - * <code>setDaemon</code>, <code>setMaxPriority</code>, + * methods <code>destroy</code>, <code>resume</code>, + * <code>setDaemon</code>, <code>setMaxPriority</code>, * <code>stop</code>, and <code>suspend</code> of the class - * <code>ThreadGroup</code></td></tr> + * <code>ThreadGroup</code></td> + * <td>rogue code can mount a denial-of-service attack by changing run + * priorities</td></tr> * <tr> * <td><code>getProtectionDomain</code></td> - * <td></td></tr> + * <td>retrieve a class's ProtectionDomain</td> + * <td>rogue code can gain information about the security policy, to + * prepare a better attack</td></tr> * <tr> * <td><code>readFileDescriptor</code></td> - * <td></td></tr> + * <td>read a file descriptor</td> + * <td>rogue code can read sensitive information</td></tr> * <tr> - * <td><code>writeFileDescriptor</code</td> - * <td></td></tr> + * <td><code>writeFileDescriptor</code></td> + * <td>write a file descriptor</td> + * <td>rogue code can write files, including viruses, and can modify the + * virtual machine binary; if not just fill up the disk</td></tr> * <tr> - * <td><code>loadLibrary.{library name}</code></td> - * <td></td></tr> + * <td><code>loadLibrary.<code><em>library name</em></td> + * <td>dynamic linking of the named library</td> + * <td>native code can bypass many security checks of pure Java</td></tr> * <tr> - * <td><code>accessClassInPackage.{package name}</code></td> - * <td></td></tr> + * <td><code>accessClassInPackage.</code><em>package name</em></td> + * <td>access to a package via a ClassLoader</td> + * <td>rogue code can access classes not normally available</td></tr> * <tr> - * <td><code>defineClassInPackage.{package name}</code></td> - * <td></td></tr> + * <td><code>defineClassInPackage.</code><em>package name</em></td> + * <td>define a class inside a given package</td> + * <td>rogue code can install rogue classes, including in trusted packages + * like java.security or java.lang</td></tr> * <tr> * <td><code>accessDeclaredMembers</code></td> - * <td></td></tr> + * <td>access declared class members via reflection</td> + * <td>rogue code can discover information, invoke methods, or modify fields + * that are not otherwise available</td></tr> * <tr> * <td><code>queuePrintJob</code></td> - * <td></td></tr> + * <td>initiate a print job</td> + * <td>rogue code could make a hard copy of sensitive information, or + * simply waste paper</td></tr> * </table> - * - * @since JDK 1.2 - * + * * @author Brian Jones + * @author Eric Blake <ebb9@email.byu.edu> + * @see BasicPermission + * @see Permission + * @see SecurityManager + * @since 1.2 + * @status updated to 1.4 */ -public final class RuntimePermission extends java.security.BasicPermission +public final class RuntimePermission extends BasicPermission { /** - * + * Compatible with JDK 1.2+. + */ + private static final long serialVersionUID = 7399184964622342223L; + + /** + * Create a new permission with the specified name. + * * @param permissionName the name of the granted permission - * - * @throws IllegalArgumentException thrown if the name contains an invalid - * wildcard character + * @throws NullPointerException if name is null + * @throws IllegalArgumentException thrown if name is empty or invalid */ public RuntimePermission(String permissionName) { - this(permissionName, null); + super(permissionName); } /** + * Create a new permission with the specified name. The actions argument + * is ignored, as runtime permissions have no actions. * * @param permissionName the name of the granted permission - * @param actions this should always be null - * - * @throws IllegalArgumentException throw if the name contains an invalid - * wildcard character + * @param actions ignored + * @throws NullPointerException if name is null + * @throws IllegalArgumentException thrown if name is empty or invalid */ public RuntimePermission(String permissionName, String actions) - { - super(permissionName, actions); - } + { + super(permissionName); + } } diff --git a/java/lang/SecurityManager.java b/java/lang/SecurityManager.java index 3ae049c40..1f73fdd3d 100644 --- a/java/lang/SecurityManager.java +++ b/java/lang/SecurityManager.java @@ -1,5 +1,5 @@ -/* java.lang.SecurityManager - Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc. +/* SecurityManager.java -- security checks for privileged actions + Copyright (C) 1998, 1999, 2001, 2002 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -7,7 +7,7 @@ GNU Classpath is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. - + GNU Classpath is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU @@ -38,736 +38,977 @@ exception statement from your version. */ package java.lang; -import java.net.*; -import java.util.*; -import java.io.*; +import java.io.FileDescriptor; +import java.net.InetAddress; +import java.security.Permission; +import java.security.SecurityPermission; /** - ** SecurityManager is a class you can extend to create - ** your own Java security policy. By default, there is - ** no SecurityManager installed in 1.1, which means that - ** all things are permitted to all people.<P> - ** - ** The default methods in this class deny all - ** things to all people. - ** - ** @author John Keiser - ** @version 1.1.0, 31 May 1998 - ** @since JDK1.0 - **/ -public class SecurityManager { - /** Tells whether or not the SecurityManager is currently - ** performing a security check. - **/ - protected boolean inCheck; - - /** Tells whether or not the SecurityManager is currently - ** performing a security check. - ** - ** @return whether or not the SecurityManager is - ** currently performing a security check. - **/ - public boolean getInCheck() { - return inCheck; - } - - /** Get a list of all the classes currently executing - ** methods on the Java stack. getClassContext()[0] is - ** the currently executing method - ** <STRONG>Spec Note:</STRONG> does not say whether - ** the stack will include the getClassContext() call or - ** the one just before it. - ** - ** @return an array containing all the methods on classes - ** on the Java execution stack. - **/ - protected Class[] getClassContext() { - return VMSecurityManager.getClassContext(); - } - - /** Find the ClassLoader for the most recent class on the - ** stack that was loaded by an explicit ClassLoader. If - ** everything on the stack was loaded by the system - ** classloader, null is returned. - ** - ** @return the most recent ClassLoader on the execution - ** stack. - **/ - protected ClassLoader currentClassLoader() { - return VMSecurityManager.currentClassLoader(); - } - - /** Find the most recent class on the stack that was - ** loaded by an explicit ClassLoader. If everything on - ** the stack was loaded by the system classloader, null - ** is returned. - ** - ** @return the most recent loaded Class on the execution - ** stack. - **/ - protected Class currentLoadedClass() { - Class[] c = getClassContext(); - for(int i=0;i<c.length;i++) { - if(c[i].getClassLoader() != null) { - return c[i]; - } - } - return null; - } - - /** Get the depth on the execution stack of the most - ** recent class that was loaded by an explicit - ** ClassLoader. This can be used as an index into - ** getClassContext(). - ** - ** @return the index of the most recent loaded Class on - ** the execution stack. - **/ - protected int classLoaderDepth() { - Class[] c = getClassContext(); - for(int i=0;i<c.length;i++) { - if(c[i].getClassLoader() != null) { - return i; - } - } - return -1; - } - - /** Tell whether there is a class loaded with an explicit - ** ClassLoader on the stack. - ** - ** @return whether there is a class loaded with an - ** explicit ClassLoader on the stack. - **/ - protected boolean inClassLoader() { - return classLoaderDepth() != -1; - } - - - /** Get the depth of a particular class on the execution - ** stack. - ** - ** @param className the fully-qualified name of the class - ** to search for on the stack. - ** @return the index of the class on the stack, or -1 if - ** the class is not on the stack. - **/ - protected int classDepth(String className) { - Class[] c = getClassContext(); - for(int i=0;i<c.length;i++) { - if(className.equals(c[i].getName())) { - return i; - } - } - return -1; - } - - /** Tell whether the specified class is on the execution - ** stack. - ** - ** @param className the fully-qualified name of the class - ** to search for on the stack. - ** @return whether the specified class is on the - ** execution stack. - **/ - protected boolean inClass(String className) { - return classDepth(className) != -1; - } - - /** Get an implementation-dependent Object that contains - ** enough information about the current environment to be - ** able to perform standard security checks later. This - ** is used by trusted methods that need to verify that - ** their callers have sufficient access to perform - ** certain operations.<P> - ** - ** Currently the only methods that use this are checkRead() - ** and checkConnect(). - ** - ** @see checkConnect(java.lang.String,int,java.lang.Object) - ** @see checkRead(java.lang.String,java.lang.Object) - **/ - public Object getSecurityContext() { - return new SecurityContext(getClassContext()); - } - - /** Check if the current thread is allowed to create a - ** ClassLoader.<P> - ** - ** This method is called from ClassLoader.ClassLoader(), - ** in other words, whenever a ClassLoader is created.<P> - ** - ** SecurityManager's implementation always denies access. - ** - ** @exception SecurityException if the operation is not - ** permitted. - ** @see java.lang.ClassLoader#ClassLoader() - **/ - public void checkCreateClassLoader() { - throw new SecurityException("Cannot create new ClassLoaders."); - } - - /** Check if the current thread is allowed to modify this - ** other Thread.<P> - ** - ** Called by Thread.stop(), suspend(), resume(), and - ** interrupt(), destroy(), setPriority(), setName() and - ** setDaemon().<P> - ** - ** SecurityManager's implementation always denies access. - ** - ** @param g the Thread to check against - ** @exception SecurityException if the operation is not - ** permitted. - ** @see java.lang.Thread#stop() - ** @see java.lang.Thread#suspend() - ** @see java.lang.Thread#resume() - ** @see java.lang.Thread#interrupt() - ** @see java.lang.Thread#destroy() - ** @see java.lang.Thread#setPriority(int) - ** @see java.lang.Thread#setName(java.lang.String) - ** @see java.lang.Thread#setDaemon(boolean) - **/ - public void checkAccess(Thread t) { - throw new SecurityException("Cannot modify Threads."); - } - - /** Check if the current thread is allowed to modify this - ** ThreadGroup.<P> - ** - ** Called by Thread.Thread() (to add a thread to the - ** ThreadGroup), ThreadGroup.ThreadGroup() (to add this - ** ThreadGroup to a parent), ThreadGroup.stop(), - ** suspend(), resume(), interrupt(), destroy(), - ** setDaemon(), and setMaxPriority().<P> - ** - ** SecurityManager's implementation always denies access. - ** - ** @param g the ThreadGroup to check against - ** @exception SecurityException if the operation is not - ** permitted. - ** @see java.lang.Thread#Thread() - ** @see java.lang.ThreadGroup#ThreadGroup() - ** @see java.lang.ThreadGroup#stop() - ** @see java.lang.ThreadGroup#suspend() - ** @see java.lang.ThreadGroup#resume() - ** @see java.lang.ThreadGroup#interrupt() - ** @see java.lang.ThreadGroup#setDaemon(boolean) - ** @see java.lang.ThreadGroup#setMaxPriority(int) - **/ - public void checkAccess(ThreadGroup g) { - throw new SecurityException("Cannot modify ThreadGroups."); - } - - /** Check if the current thread is allowed to exit the - ** JVM with the given status.<P> - ** - ** This method is called from Runtime.exit().<P> - ** - ** SecurityManager's implementation always denies access. - ** - ** @param status the status to exit with - ** @exception SecurityException if the operation is not - ** permitted. - ** @see java.lang.Runtime#exit() - ** @see java.lang.Runtime#exit(int) - **/ - public void checkExit(int status) { - throw new SecurityException("Cannot exit JVM."); - } - - /** Check if the current thread is allowed to execute the - ** given program.<P> - ** - ** This method is called from Runtime.exec().<P> - ** - ** SecurityManager's implementation always denies access. - ** - ** @param program the name of the program to exec - ** @exception SecurityException if the operation is not - ** permitted. - ** @see java.lang.Runtime#exec(java.lang.String[],java.lang.String[]) - **/ - public void checkExec(String program) { - throw new SecurityException("Cannot execute programs."); - } - - /** Check if the current thread is allowed to link in the - ** given native library.<P> - ** - ** This method is called from Runtime.load() (and hence, - ** by loadLibrary() as well).<P> - ** - ** SecurityManager's implementation always denies access. - ** - ** @param filename the full name of the library to load - ** @exception SecurityException if the operation is not - ** permitted. - ** @see java.lang.Runtime#load(java.lang.String) - **/ - public void checkLink(String filename) { - throw new SecurityException("Cannot link native libraries."); - } - - /** Check if the current thread is allowed to read the - ** given file using the FileDescriptor.<P> - ** - ** This method is called from - ** FileInputStream.FileInputStream().<P> - ** - ** SecurityManager's implementation always denies access. - ** - ** @param desc the FileDescriptor representing the file - ** to access - ** @exception SecurityException if the operation is not - ** permitted. - ** @see java.io.FileInputStream#FileInputStream(java.io.FileDescriptor) - **/ - public void checkRead(FileDescriptor desc) { - throw new SecurityException("Cannot read files via file descriptors."); - } - - /** Check if the current thread is allowed to read the - ** given file.<P> - ** - ** This method is called from - ** FileInputStream.FileInputStream(), - ** RandomAccessFile.RandomAccessFile(), File.exists(), - ** canRead(), isFile(), isDirectory(), lastModified(), - ** length() and list().<P> - ** - ** SecurityManager's implementation always denies access. - ** - ** @param filename the full name of the file to access - ** @exception SecurityException if the operation is not - ** permitted. - ** @see java.io.File - ** @see java.io.FileInputStream#FileInputStream(java.lang.String) - ** @see java.io.RandomAccessFile#RandomAccessFile(java.lang.String) - **/ - public void checkRead(String filename) { - throw new SecurityException("Cannot read files via file names."); - } - - /** Check if the current thread is allowed to read the - ** given file. using the given SecurityContext.<P> - ** - ** I know of no core class that calls this method.<P> - ** - ** SecurityManager's implementation always denies access. - ** - ** @param filename the full name of the file to access - ** @param securityContext the Security Context to - ** determine access for. - ** @exception SecurityException if the operation is not - ** permitted. - **/ - public void checkRead(String filename, Object securityContext) { - throw new SecurityException("Cannot read files via file names."); - } - - /** Check if the current thread is allowed to write to the - ** given file using the FileDescriptor.<P> - ** - ** This method is called from - ** FileOutputStream.FileOutputStream().<P> - ** - ** SecurityManager's implementation always denies access. - ** - ** @param desc the FileDescriptor representing the file - ** to access - ** @exception SecurityException if the operation is not - ** permitted. - ** @see java.io.FileOutputStream#FileOutputStream(java.io.FileDescriptor) - **/ - public void checkWrite(FileDescriptor desc) { - throw new SecurityException("Cannot write files via file descriptors."); - } - - /** Check if the current thread is allowed to write to the - ** given file.<P> - ** - ** This method is called from - ** FileOutputStream.FileOutputStream(), - ** RandomAccessFile.RandomAccessFile(), - ** File.canWrite(), mkdir(), and renameTo().<P> - ** - ** SecurityManager's implementation always denies access. - ** - ** @param filename the full name of the file to access - ** @exception SecurityException if the operation is not - ** permitted. - ** @see java.io.File#canWrite() - ** @see java.io.File#mkdir() - ** @see java.io.File#renameTo() - ** @see java.io.FileOutputStream#FileOutputStream(java.lang.String) - ** @see java.io.RandomAccessFile#RandomAccessFile(java.lang.String) - **/ - public void checkWrite(String filename) { - throw new SecurityException("Cannot write files via file names."); - } - - /** Check if the current thread is allowed to delete the - ** given file.<P> - ** - ** This method is called from File.delete().<P> - ** - ** SecurityManager's implementation always denies access. - ** - ** @param filename the full name of the file to delete - ** @exception SecurityException if th operation is not - ** permitted. - ** @see java.io.File#delete() - **/ - public void checkDelete(String filename) { - throw new SecurityException("Cannot delete files."); - } - - /** Check if the current thread is allowed to connect to a - ** given host on a given port.<P> - ** - ** This method is called from Socket.Socket(). - ** - ** SecurityManager's implementation always denies access. - ** - ** @param host the host to connect to - ** @param port the port to connect on - ** @exception SecurityException if the operation is not - ** permitted - ** @see java.net.Socket#Socket() - **/ - public void checkConnect(String host, int port) { - throw new SecurityException("Cannot make network connections."); - } - - /** Check if the current thread is allowed to connect to a - ** given host on a given port using a specific security - ** context to determine access.<P> - ** - ** This method is not called in the 1.1 core classes.<P> - ** - ** SecurityManager's implementation always denies access. - ** - ** @param host the host to connect to - ** @param port the port to connect on - ** @param securityContext the security context to - ** determine access with - ** @exception SecurityException if the operation is not - ** permitted - **/ - public void checkConnect(String host, int port, Object securityContext) { - throw new SecurityException("Cannot make network connections."); - } - - /** Check if the current thread is allowed to listen to a - ** specific port for data.<P> - ** - ** This method is called by ServerSocket.ServerSocket().<P> - ** - ** SecurityManager's implementation always denies access. - ** - ** @param port the port to listen on - ** @exception SecurityException if the operation is not - ** permitted - ** @see java.net.ServerSocket#ServerSocket(int) - **/ - public void checkListen(int port) { - throw new SecurityException("Cannot listen for connections."); - } - - /** Check if the current thread is allowed to accept a - ** connection from a particular host on a particular - ** port.<P> - ** - ** This method is called by ServerSocket.implAccept().<P> - ** - ** SecurityManager's implementation always denies access. - ** - ** @param host the host which wishes to connect - ** @param port the port the connection will be on - ** @exception SecurityException if the operation is not - ** permitted - ** @see java.net.ServerSocket#accept() - **/ - public void checkAccept(String host, int port) { - throw new SecurityException("Cannot accept connections."); - } - - /** Check if the current thread is allowed to read and - ** write multicast to a particular address.<P> - ** - ** SecurityManager's implementation always denies access. - ** - ** @XXX where is it called? - ** - ** @param addr the address to multicast to. - ** @exception SecurityException if the operation is not - ** permitted. - **/ - public void checkMulticast(InetAddress addr) { - throw new SecurityException("Cannot read or write multicast."); - } - - /** Check if the current thread is allowed to read and - ** write multicast to a particular address with a - ** particular ttl value.<P> - ** - ** SecurityManager's implementation always denies access.<P> - ** - ** @XXX where is it called? - ** - ** @XXX what the hell is ttl? Expand abbreviation. - ** - ** @param addr the address to multicast to. - ** @param ttl the ttl value to use - ** @exception SecurityException if the operation is not - ** permitted. - **/ - public void checkMulticast(InetAddress addr, byte ttl) { - throw new SecurityException("Cannot read or write multicast."); - } - - /** - ** Check if the current thread is allowed to perform an - ** operation that requires the specified <code>Permission</code>. - ** - ** @param perm The <code>Permission</code> required. - ** @exception SecurityException If the operation is not allowed. - **/ - public void checkPermission(java.security.Permission perm) { - throw new SecurityException("Operation not allowed"); - } - - /** - ** Check if the current thread is allowed to perform an - ** operation that requires the specified <code>Permission</code>. - ** - ** @param perm The <code>Permission</code> required. - ** @param context A security context - ** @exception SecurityException If the operation is not allowed. - ** @since 1.2 - **/ - public void checkPermission(java.security.Permission perm, - Object context) { - throw new SecurityException("Operation not allowed"); - } - - /** Check if the current thread is allowed to read or - ** write all the system properties at once.<P> - ** - ** This method is called by System.getProperties() - ** and setProperties().<P> - ** - ** SecurityManager's implementation always denies access. - ** - ** @exception SecurityException if the operation is not - ** permitted. - ** @see java.lang.System#getProperties() - ** @see java.lang.System#setProperties(java.util.Properties) - **/ - public void checkPropertiesAccess() { - throw new SecurityException("Cannot access all system properties at once."); - } - - /** Check if the current thread is allowed to read or - ** write a particular system property.<P> - ** - ** This method is called by System.getProperty() and - ** setProperty().<P> - ** - ** SecurityManager's implementation always denies access. - ** - ** @exception SecurityException is the operation is not - ** permitted. - ** @see java.lang.System#getProperty(java.lang.String) - ** @see java.lang.System#setProperty(java.lang.String,java.lang.String) - **/ - public void checkPropertyAccess(String name) { - throw new SecurityException("Cannot access individual system properties."); - } - - /** Check if the current thread is allowed to create a - ** top-level window. If it is not, the operation should - ** still go through, but some sort of nonremovable - ** warning should be placed on the window to show that it - ** is untrusted.<P> - ** - ** This method is called by Window.Window().<P> - ** - ** SecurityManager's implementation always denies access. - ** - ** @param window the window to create - ** @see java.awt.Window#Window(java.awt.Frame) - **/ - public boolean checkTopLevelWindow(Object window) { - return false; - } - - /** Check if the current thread is allowed to create a - ** print job.<P> - ** - ** This method is called by Toolkit.getPrintJob(). (I - ** assume so, at least, it just don't say nothing about - ** it in the spec.)<P> - ** - ** SecurityManager's implementation always denies access. - ** - ** @exception SecurityException if the operation is not - ** permitted. - ** @see java.awt.Toolkit.getPrintJob(java.awt.Frame,java.lang.String,java.util.Properties) - **/ - public void checkPrintJobAccess() { - throw new SecurityException("Cannot create print jobs."); - } - - /** Check if the current thread is allowed to use the - ** system clipboard.<P> - ** - ** This method is called by Toolkit.getSystemClipboard(). - ** (I assume.)<P> - ** - ** SecurityManager's implementation always denies access. - ** - ** @exception SecurityException if the operation is not - ** permitted. - ** @see java.awt.Toolkit#getSystemClipboard() - **/ - public void checkSystemClipboardAccess() { - throw new SecurityException("Cannot access the system clipboard."); - } - - /** Check if the current thread is allowed to use the AWT - ** event queue.<P> - ** - ** This method is called by Toolkit.getSystemEventQueue().<P> - ** - ** SecurityManager's implementation always denies access. - ** - ** @exception SecurityException if the operation is not - ** permitted. - ** @see java.awt.Toolkit#getSystemEventQueue() - **/ - public void checkAwtEventQueueAccess() { - throw new SecurityException("Cannot access the AWT event queue."); - } - - /** Check if the current thread is allowed to access the - ** specified package at all.<P> - ** - ** This method is called by ClassLoader.loadClass() in - ** user-created ClassLoaders.<P> - ** - ** SecurityManager's implementation always denies access. - ** - ** @param packageName the package name to check access to - ** @exception SecurityException if the operation is not - ** permitted. - ** @see java.lang.ClassLoader#loadClass(java.lang.String,boolean) - **/ - public void checkPackageAccess(String packageName) { - throw new SecurityException("Cannot access packages via the ClassLoader."); - } - - /** Check if the current thread is allowed to define - ** classes the specified package. If the class already - ** created, though, ClassLoader.loadClass() can still - ** return the Class if checkPackageAccess() checks out.<P> - ** - ** This method is called by ClassLoader.loadClass() in - ** user-created ClassLoaders.<P> - ** - ** SecurityManager's implementation always denies access. - ** - ** @param packageName the package name to check access to - ** @exception SecurityException if the operation is not - ** permitted. - ** @see java.lang.ClassLoader#loadClass(java.lang.String,boolean) - **/ - public void checkPackageDefinition(String packageName) { - throw new SecurityException("Cannot load classes into any packages via the ClassLoader."); - } - - /** Check if the current thread is allowed to set the - ** current socket factory.<P> - ** - ** This method is called by Socket.setSocketImplFactory(), - ** ServerSocket.setSocketFactory(), and - ** URL.setURLStreamHandlerFactory().<P> - ** - ** SecurityManager's implementation always denies access. - ** - ** @exception SecurityException if the operation is not - ** permitted. - ** @see java.net.Socket#setSocketImplFactory(java.net.SocketImplFactory) - ** @see java.net.ServerSocket#setSocketFactory(java.net.SocketImplFactory) - ** @see java.net.URL#setURLStreamHandlerFactory(java.net.URLStreamHandlerFactory) - **/ - public void checkSetFactory() { - throw new SecurityException("Cannot set the socket factory."); - } - - /** Check if the current thread is allowed to get certain - ** types of Methods, Fields and Constructors from a Class - ** object.<P> - ** - ** This method is called by Class.getMethod[s](), - ** Class.getField[s](), Class.getConstructor[s], - ** Class.getDeclaredMethod[s](), - ** Class.getDeclaredField[s](), and - ** Class.getDeclaredConstructor[s]().<P> - ** - ** SecurityManager's implementation always denies access. - ** - ** @param c the Class to check - ** @param memberType the type of members to check - ** against, either Member.DECLARED or - ** Member.PUBLIC. - ** @exception SecurityException if the operation is not - ** permitted. - ** @see java.lang.Class - ** @see java.lang.reflect.Member#DECLARED - ** @see java.lang.reflect.Member#PUBLIC - **/ - public void checkMemberAccess(Class c, int memberType) { - throw new SecurityException("Cannot access members of classes."); - } - - /** Test whether a particular security action may be - ** taken. - ** @param action the desired action to take - ** @exception SecurityException if the action is denied. - ** @XXX I have no idea what actions must be tested - ** or where. - **/ - public void checkSecurityAccess(String action) { - checkPermission (new java.security.SecurityPermission (action)); - } - - /** Get the ThreadGroup that a new Thread should belong - ** to by default.<P> - ** - ** Called by Thread.Thread().<P> - ** - ** SecurityManager's implementation just uses the - ** ThreadGroup of the current Thread.<P> - ** - ** <STRONG>Spec Note:</STRONG> it is not clear whether - ** the new Thread is guaranteed to pass the - ** checkAccessThreadGroup() test when using this - ** ThreadGroup. I presume so. - ** - ** @return the ThreadGroup to put the new Thread into. - **/ - public ThreadGroup getThreadGroup() { - return Thread.currentThread().getThreadGroup(); - } - - public SecurityManager () { - if (System.getSecurityManager () != null) - throw new SecurityException (); - } -} - + * SecurityManager is a class you can extend to create your own Java + * security policy. By default, there is no SecurityManager installed in + * 1.1, which means that all things are permitted to all people. The security + * manager, if set, is consulted before doing anything with potentially + * dangerous results, and throws a <code>SecurityException</code> if the + * action is forbidden. + * + * <p>A typical check is as follows, just before the dangerous operation:<br> + * <pre> + * SecurityManager sm = System.getSecurityManager(); + * if (sm != null) + * sm.checkXXX(<em>argument</em>, ...); + * </pre> + * Note that this is thread-safe, by caching the security manager in a local + * variable rather than risking a NullPointerException if the mangager is + * changed between the check for null and before the permission check. + * + * <p>The special method <code>checkPermission</code> is a catchall, and + * the default implementation calls + * <code>AccessController.checkPermission</code>. In fact, all the other + * methods default to calling checkPermission. + * + * <p>Sometimes, the security check needs to happen from a different context, + * such as when called from a worker thread. In such cases, use + * <code>getSecurityContext</code> to take a snapshot that can be passed + * to the worker thread:<br> + * <pre> + * Object context = null; + * SecurityManager sm = System.getSecurityManager(); + * if (sm != null) + * context = sm.getSecurityContext(); // defaults to an AccessControlContext + * // now, in worker thread + * if (sm != null) + * sm.checkPermission(permission, context); + * <pre> + * + * <p>Permissions fall into these categories: File, Socket, Net, Security, + * Runtime, Property, AWT, Reflect, and Serializable. Each of these + * permissions have a property naming convention, that follows a hierarchical + * naming convention, to make it easy to grant or deny several permissions + * at once. Some permissions also take a list of permitted actions, such + * as "read" or "write", to fine-tune control even more. The permission + * <code>java.security.AllPermission</code> grants all permissions. + * + * <p>The default methods in this class deny all things to all people. You + * must explicitly grant permission for anything you want to be legal when + * subclassing this class. + * + * @author John Keiser + * @author Eric Blake <ebb9@email.byu.edu> + * @see ClassLoader + * @see SecurityException + * @see #checkTopLevelWindow(Object) + * @see System#getSecurityManager() + * @see System#setSecurityManager(SecurityManager) + * @see AccessController + * @see AccessControlContext + * @see AccessControlException + * @see Permission + * @see BasicPermission + * @see java.io.FilePermission + * @see java.net.SocketPermission + * @see java.util.PropertyPermission + * @see RuntimePermission + * @see java.awt.AWTPermission + * @see Policy + * @see SecurityPermission + * @see ProtectionDomain + * @since 1.0 + * @status still missing 1.4 functionality + */ +public class SecurityManager +{ + /** + * Tells whether or not the SecurityManager is currently performing a + * security check. + * @deprecated Use {@link #checkPermission(Permission)} instead. + */ + protected boolean inCheck; + + /** + * Construct a new security manager. There may be a security check, of + * <code>RuntimePermission("createSecurityManager")</code>. + * + * @throws SecurityException if permission is denied + */ + public SecurityManager() + { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) + sm.checkPermission(new RuntimePermission("createSecurityManager")); + } + + /** + * Tells whether or not the SecurityManager is currently performing a + * security check. + * + * @return true if the SecurityManager is in a security check + * @see #inCheck + * @deprecated use {@link #checkPermission(Permission)} instead + */ + public boolean getInCheck() + { + return inCheck; + } + + /** + * Get a list of all the classes currently executing methods on the Java + * stack. getClassContext()[0] is the currently executing method (ie. the + * class that CALLED getClassContext, not SecurityManager). + * + * @return an array of classes on the Java execution stack + */ + protected Class[] getClassContext() + { + return VMSecurityManager.getClassContext(); + } + + /** + * Find the ClassLoader of the first non-system class on the execution + * stack. A non-system class is one whose ClassLoader is not equal to + * {@link ClassLoader#getSystemClassLoader()} or its ancestors. This + * will return null in three cases:<br><nl> + * <li>All methods on the stack are from system classes</li> + * <li>All methods on the stack up to the first "privileged" caller, as + * created by {@link AccessController.doPrivileged(PrivilegedAction)}, + * are from system classes</li> + * <li>A check of <code>java.security.AllPermission</code> succeeds.</li> + * </nl> + * + * @return the most recent non-system ClassLoader on the execution stack + * @deprecated use {@link #checkPermission(Permission)} instead + */ + protected ClassLoader currentClassLoader() + { + // XXX should be: + // Class c = currentLoadedClass(); + // return c != null ? c.getClassLoader() : null; + return VMSecurityManager.currentClassLoader(); + } + + /** + * Find the first non-system class on the execution stack. A non-system + * class is one whose ClassLoader is not equal to + * {@link ClassLoader#getSystemClassLoader()} or its ancestors. This + * will return null in three cases:<br><nl> + * <li>All methods on the stack are from system classes</li> + * <li>All methods on the stack up to the first "privileged" caller, as + * created by {@link AccessController.doPrivileged(PrivilegedAction)}, + * are from system classes</li> + * <li>A check of <code>java.security.AllPermission</code> succeeds.</li> + * </nl> + * + * @return the most recent non-system Class on the execution stack + * @deprecated use {@link #checkPermission(Permission)} instead + */ + protected Class currentLoadedClass() + { + // XXX Should be: + // int i = classLoaderDepth(); + // return i >= 0 ? getClassContext(i) : null; + Class[] c = getClassContext(); + for (int i = 0; i < c.length; i++) + if (c[i].getClassLoader() != null) + return c[i]; + return null; + } + + /** + * Get the depth of a particular class on the execution stack. + * + * @param className the fully-qualified name to search for + * @return the index of the class on the stack, or -1 + * @deprecated use {@link #checkPermission(Permission)} instead + */ + protected int classDepth(String className) + { + Class[] c = getClassContext(); + for (int i = 0; i < c.length; i++) + if (className.equals(c[i].getName())) + return i; + return -1; + } + + /** + * Get the depth on the execution stack of the most recent non-system class. + * A non-system class is one whose ClassLoader is not equal to + * {@link ClassLoader#getSystemClassLoader()} or its ancestors. This + * will return -1 in three cases:<br><nl> + * <li>All methods on the stack are from system classes</li> + * <li>All methods on the stack up to the first "privileged" caller, as + * created by {@link AccessController.doPrivileged(PrivilegedAction)}, + * are from system classes</li> + * <li>A check of <code>java.security.AllPermission</code> succeeds.</li> + * </nl> + * + * @return the index of the most recent non-system Class on the stack + * @deprecated use {@link #checkPermission(Permission)} instead + */ + protected int classLoaderDepth() + { + // XXX Check AllPermission first. + Class[] c = getClassContext(); + for (int i = 0; i <c.length; i++) + if (c[i].getClassLoader() != null) + // XXX Check if c[i] is AccessController, or a system class. + return i; + return -1; + } + + /** + * Tell whether the specified class is on the execution stack. + * + * @param className the fully-qualified name of the class to find + * @return whether the specified class is on the execution stack + * @deprecated use {@link #checkPermission(Permission)} instead + */ + protected boolean inClass(String className) + { + return classDepth(className) != -1; + } + + /** + * Tell whether there is a class loaded with an explicit ClassLoader on + * the stack. + * + * @return whether a class with an explicit ClassLoader is on the stack + * @deprecated use {@link #checkPermission(Permission)} instead + */ + protected boolean inClassLoader() + { + return classLoaderDepth() != -1; + } + + /** + * Get an implementation-dependent Object that contains enough information + * about the current environment to be able to perform standard security + * checks later. This is used by trusted methods that need to verify that + * their callers have sufficient access to perform certain operations. + * + * <p>Currently the only methods that use this are checkRead() and + * checkConnect(). The default implementation returns an + * <code>AccessControlContext</code>. + * + * @return a security context + * @see #checkConnect(String, int, Object) + * @see #checkRead(String, Object) + * @see AccessControlContext + * @see AccessController#getContext() + */ + public Object getSecurityContext() + { + // XXX Should be: return AccessController.getContext(); + return new SecurityContext(getClassContext()); + } + + /** + * Check if the current thread is allowed to perform an operation that + * requires the specified <code>Permission</code>. This defaults to + * <code>AccessController.checkPermission</code>. + * + * @param perm the <code>Permission</code> required + * @throws SecurityException if permission is denied + * @throws NullPointerException if perm is null + * @since 1.2 + */ + public void checkPermission(Permission perm) + { + // XXX Should be: AccessController.checkPermission(perm); + throw new SecurityException("Operation not allowed"); + } + + /** + * Check if the current thread is allowed to perform an operation that + * requires the specified <code>Permission</code>. This is done in a + * context previously returned by <code>getSecurityContext()</code>. The + * default implementation expects context to be an AccessControlContext, + * and it calls <code>AccessControlContext.checkPermission(perm)</code>. + * + * @param perm the <code>Permission</code> required + * @param context a security context + * @throws SecurityException if permission is denied, or if context is + * not an AccessControlContext + * @throws NullPointerException if perm is null + * @see #getSecurityContext() + * @see AccessControlContext#checkPermission(Permission) + * @since 1.2 + */ + public void checkPermission(Permission perm, Object context) + { + // XXX Should be: + // if (! (context instanceof AccessControlContext)) + // throw new SecurityException("Missing context"); + // ((AccessControlContext) context).checkPermission(perm); + + throw new SecurityException("Operation not allowed"); + } + + /** + * Check if the current thread is allowed to create a ClassLoader. This + * method is called from ClassLoader.ClassLoader(), and checks + * <code>RuntimePermission("createClassLoader")</code>. If you override + * this, you should call <code>super.checkCreateClassLoader()</code> rather + * than throwing an exception. + * + * @throws SecurityException if permission is denied + * @see ClassLoader#ClassLoader() + */ + public void checkCreateClassLoader() + { + // XXX Should be: + // checkPermission(new RuntimePermission("createClassLoader")); + throw new SecurityException("Cannot create new ClassLoaders."); + } + + /** + * Check if the current thread is allowed to modify another Thread. This is + * called by Thread.stop(), suspend(), resume(), interrupt(), destroy(), + * setPriority(), setName(), and setDaemon(). The default implementation + * checks <code>RuntimePermission("modifyThread") on system threads (ie. + * threads in ThreadGroup with a null parent), and returns silently on + * other threads. + * + * <p>If you override this, you must do two things. First, call + * <code>super.checkAccess(t)</code>, to make sure you are not relaxing + * requirements. Second, if the calling thread has + * <code>RuntimePermission("modifyThread")</code>, return silently, so that + * core classes (the Classpath library!) can modify any thread. + * + * @param t the other Thread to check + * @throws SecurityException if permission is denied + * @throws NullPointerException if t is null + * @see Thread#stop() + * @see Thread#suspend() + * @see Thread#resume() + * @see Thread#setPriority(int) + * @see Thread#setName(String) + * @see Thread#setDaemon(boolean) + */ + public void checkAccess(Thread t) + { + // XXX Implement this correctly. + throw new SecurityException("Cannot modify Threads."); + } + + /** + * Check if the current thread is allowed to modify a ThreadGroup. This is + * called by Thread.Thread() (to add a thread to the ThreadGroup), + * ThreadGroup.ThreadGroup() (to add this ThreadGroup to a parent), + * ThreadGroup.stop(), suspend(), resume(), interrupt(), destroy(), + * setDaemon(), and setMaxPriority(). The default implementation + * checks <code>RuntimePermission("modifyThread") on the system group (ie. + * the one with a null parent), and returns silently on other groups. + * + * <p>If you override this, you must do two things. First, call + * <code>super.checkAccess(t)</code>, to make sure you are not relaxing + * requirements. Second, if the calling thread has + * <code>RuntimePermission("modifyThreadGroup")</code>, return silently, + * so that core classes (the Classpath library!) can modify any thread. + * + * @param t the other Thread to check + * @throws SecurityException if permission is denied + * @throws NullPointerException if t is null + * @see Thread#Thread() + * @see ThreadGroup#ThreadGroup() + * @see ThreadGroup#stop() + * @see ThreadGroup#suspend() + * @see ThreadGroup#resume() + * @see ThreadGroup#interrupt() + * @see ThreadGroup#setDaemon(boolean) + * @see ThreadGroup#setMaxPriority(int) + */ + public void checkAccess(ThreadGroup g) + { + // XXX Implement this correctly. + throw new SecurityException("Cannot modify ThreadGroups."); + } + + /** + * Check if the current thread is allowed to exit the JVM with the given + * status. This method is called from Runtime.exit() and Runtime.halt(). + * The default implementation checks + * <code>RuntimePermission("exitVM")</code>. If you override this, call + * <code>super.checkExit</code> rather than throwing an exception. + * + * @param status the status to exit with + * @throws SecurityException if permission is denied + * @see Runtime#exit(int) + * @see Runtime#halt(int) + */ + public void checkExit(int status) + { + // XXX Should be: checkPermission(new RuntimePermission("exitVM")); + throw new SecurityException("Cannot exit JVM."); + } + + /** + * Check if the current thread is allowed to execute the given program. This + * method is called from Runtime.exec(). If the name is an absolute path, + * the default implementation checks + * <code>FilePermission(program, "execute")</code>, otherwise it checks + * <code>FilePermission("<<ALL FILES>>", "execute")</code>. If + * you override this, call <code>super.checkExec</code> rather than + * throwing an exception. + * + * @param program the name of the program to exec + * @throws SecurityException if permission is denied + * @throws NullPointerException if program is null + * @see Runtime#exec(String[], String[], File) + */ + public void checkExec(String program) + { + // XXX Implement this correctly. + throw new SecurityException("Cannot execute programs."); + } + + /** + * Check if the current thread is allowed to link in the given native + * library. This method is called from Runtime.load() (and hence, by + * loadLibrary() as well). The default implementation checks + * <code>RuntimePermission("loadLibrary." + filename)</code>. If you + * override this, call <code>super.checkLink</code> rather than throwing + * an exception. + * + * @param filename the full name of the library to load + * @throws SecurityException if permission is denied + * @throws NullPointerException if filename is null + * @see Runtime#load(String) + */ + public void checkLink(String filename) + { + // Use the toString() hack to do the null check. + // XXX Should be: + // checkPermission(new RuntimePermission("loadLibrary." + // + filename.toString())); + throw new SecurityException("Cannot link native libraries."); + } + + /** + * Check if the current thread is allowed to read the given file using the + * FileDescriptor. This method is called from + * FileInputStream.FileInputStream(). The default implementation checks + * <code>RuntimePermission("readFileDescriptor")</code>. If you override + * this, call <code>super.checkRead</code> rather than throwing an + * exception. + * + * @param desc the FileDescriptor representing the file to access + * @throws SecurityException if permission is denied + * @throws NullPointerException if desc is null + * @see FileInputStream#FileInputStream(FileDescriptor) + */ + public void checkRead(FileDescriptor desc) + { + // XXX Should be: + // checkPermission(new RuntimePermission("readFileDescriptor")); + throw new SecurityException("Cannot read files via file descriptors."); + } + + /** + * Check if the current thread is allowed to read the given file. This + * method is called from FileInputStream.FileInputStream(), + * RandomAccessFile.RandomAccessFile(), File.exists(), canRead(), isFile(), + * isDirectory(), lastModified(), length() and list(). The default + * implementation checks <code>FilePermission(filename, "read")</code>. If + * you override this, call <code>super.checkRead</code> rather than + * throwing an exception. + * + * @param filename the full name of the file to access + * @throws SecurityException if permission is denied + * @throws NullPointerException if filename is null + * @see File + * @see FileInputStream#FileInputStream(String) + * @see RandomAccessFile#RandomAccessFile(String) + */ + public void checkRead(String filename) + { + // XXX Should be: checkPermission(new FilePermission(filename, "read")); + throw new SecurityException("Cannot read files via file names."); + } + + /** + * Check if the current thread is allowed to read the given file. using the + * given security context. The context must be a result of a previous call + * to <code>getSecurityContext()</code>. The default implementation checks + * <code>AccessControlContext.checkPermission(new FilePermission(filename, + * "read"))</code>. If you override this, call <code>super.checkRead</code> + * rather than throwing an exception. + * + * @param filename the full name of the file to access + * @param context the context to determine access for + * @throws SecurityException if permission is denied, or if context is + * not an AccessControlContext + * @throws NullPointerException if filename is null + * @see #getSecurityContext() + * @see AccessControlContext#checkPermission(Permission) + */ + public void checkRead(String filename, Object context) + { + // XXX Should be: + // if (! (context instanceof AccessControlContext)) + // throw new SecurityException("Missing context"); + // AccessControlContext ac = (AccessControlContext) context; + // ac.checkPermission(new FilePermission(filename, "read")); + throw new SecurityException("Cannot read files via file names."); + } + + /** + * Check if the current thread is allowed to write the given file using the + * FileDescriptor. This method is called from + * FileOutputStream.FileOutputStream(). The default implementation checks + * <code>RuntimePermission("writeFileDescriptor")</code>. If you override + * this, call <code>super.checkWrite</code> rather than throwing an + * exception. + * + * @param desc the FileDescriptor representing the file to access + * @throws SecurityException if permission is denied + * @throws NullPointerException if desc is null + * @see FileOutputStream#FileOutputStream(FileDescriptor) + */ + public void checkWrite(FileDescriptor desc) + { + // XXX Should be: + // checkPermission(new RuntimePermission("writeFileDescriptor")); + throw new SecurityException("Cannot write files via file descriptors."); + } + + /** + * Check if the current thread is allowed to write the given file. This + * method is called from FileOutputStream.FileOutputStream(), + * RandomAccessFile.RandomAccessFile(), File.canWrite(), mkdir(), and + * renameTo(). The default implementation checks + * <code>FilePermission(filename, "write")</code>. If you override this, + * call <code>super.checkWrite</code> rather than throwing an exception. + * + * @param filename the full name of the file to access + * @throws SecurityException if permission is denied + * @throws NullPointerException if filename is null + * @see File + * @see File#canWrite() + * @see File#mkdir() + * @see File#renameTo() + * @see FileOutputStream#FileOutputStream(String) + * @see RandomAccessFile#RandomAccessFile(String) + */ + public void checkWrite(String filename) + { + // XXX Should be: checkPermission(new FilePermission(filename, "write")); + throw new SecurityException("Cannot write files via file names."); + } + + /** + * Check if the current thread is allowed to delete the given file. This + * method is called from File.delete(). The default implementation checks + * <code>FilePermission(filename, "delete")</code>. If you override this, + * call <code>super.checkDelete</code> rather than throwing an exception. + * + * @param filename the full name of the file to delete + * @throws SecurityException if permission is denied + * @throws NullPointerException if filename is null + * @see File#delete() + */ + public void checkDelete(String filename) + { + // XXX Should be: checkPermission(new FilePermission(filename, "delete")); + throw new SecurityException("Cannot delete files."); + } + + /** + * Check if the current thread is allowed to connect to a given host on a + * given port. This method is called from Socket.Socket(). A port number + * of -1 indicates the caller is attempting to determine an IP address, so + * the default implementation checks + * <code>SocketPermission(host, "resolve")</code>. Otherwise, the default + * implementation checks + * <code>SocketPermission(host + ":" + port, "connect")</code>. If you + * override this, call <code>super.checkConnect</code> rather than throwing + * an exception. + * + * @param host the host to connect to + * @param port the port to connect on + * @throws SecurityException if permission is denied + * @throws NullPointerException if host is null + * @see Socket#Socket() + */ + public void checkConnect(String host, int port) + { + // XXX Should be: + // if (port == -1) + // checkPermission(new SocketPermission(host, "resolve")); + // else + // checkPermission(new SocketPermission(host + ":" + port, "connect")); + throw new SecurityException("Cannot make network connections."); + } + + /** + * Check if the current thread is allowed to connect to a given host on a + * given port, using the given security context. The context must be a + * result of a previous call to <code>getSecurityContext</code>. A port + * number of -1 indicates the caller is attempting to determine an IP + * address, so the default implementation checks + * <code>AccessControlContext.checkPermission(new SocketPermission(host, + * "resolve"))</code>. Otherwise, the default implementation checks + * <code>AccessControlContext.checkPermission(new SocketPermission(host + * + ":" + port, "connect"))</code>. If you override this, call + * <code>super.checkConnect</code> rather than throwing an exception. + * + * @param host the host to connect to + * @param port the port to connect on + * @param context the context to determine access for + * @throws SecurityException if permission is denied, or if context is + * not an AccessControlContext + * @throws NullPointerException if host is null + * @see #getSecurityContext() + * @see AccessControlContext#checkPermission(Permission) + */ + public void checkConnect(String host, int port, Object securityContext) + { + // XXX Should be: + // if (! (context instanceof AccessControlContext)) + // throw new SecurityException("Missing context"); + // AccessControlContext ac = (AccessControlContext) context; + // if (port == -1) + // ac.checkPermission(new SocketPermission(host, "resolve")); + // else + // ac.checkPermission(new SocketPermission(host + ":" +port, "connect")); + throw new SecurityException("Cannot make network connections."); + } + + /** + * Check if the current thread is allowed to listen to a specific port for + * data. This method is called by ServerSocket.ServerSocket(). The default + * implementation checks + * <code>SocketPermission("localhost:" + (port == 0 ? "1024-" : "" + port), + * "listen")</code>. If you override this, call + * <code>super.checkListen</code> rather than throwing an exception. + * + * @param port the port to listen on + * @throws SecurityException if permission is denied + * @see ServerSocket#ServerSocket(int) + */ + public void checkListen(int port) + { + // XXX Should be: + // checkPermission(new SocketPermission("localhost:" + // + (port == 0 ? "1024-" : "" +port), + // "listen")); + throw new SecurityException("Cannot listen for connections."); + } + + /** + * Check if the current thread is allowed to accept a connection from a + * particular host on a particular port. This method is called by + * ServerSocket.implAccept(). The default implementation checks + * <code>SocketPermission(host + ":" + port, "accept")</code>. If you + * override this, call <code>super.checkAccept</code> rather than throwing + * an exception. + * + * @param host the host which wishes to connect + * @param port the port the connection will be on + * @throws SecurityException if permission is denied + * @throws NullPointerException if host is null + * @see ServerSocket#accept() + */ + public void checkAccept(String host, int port) + { + // Use the toString() hack to do the null check. + // XXX Should be: + // checkPermission(new SocketPermission(host.toString() + ":" + port, + // "accept")); + throw new SecurityException("Cannot accept connections."); + } + + /** + * Check if the current thread is allowed to read and write multicast to + * a particular address. The default implementation checks + * <code>SocketPermission(addr.getHostAddress(), "accept,connect")</code>. + * If you override this, call <code>super.checkMulticast</code> rather than + * throwing an exception. + * + * @param addr the address to multicast to + * @throws SecurityException if permission is denied + * @throws NullPointerException if host is null + * @since 1.1 + */ + public void checkMulticast(InetAddress addr) + { + // XXX Should be: + // checkPermission(new SocketPermission(addr.getHostAddress(), + // "accept,connect")); + throw new SecurityException("Cannot read or write multicast."); + } + + /** + *Check if the current thread is allowed to read and write multicast to + * a particular address with a particular ttl (time-to-live) value. The + * default implementation ignores ttl, and checks + * <code>SocketPermission(addr.getHostAddress(), "accept,connect")</code>. + * If you override this, call <code>super.checkMulticast</code> rather than + * throwing an exception. + * + * @param addr the address to multicast to + * @param ttl value in use for multicast send + * @throws SecurityException if permission is denied + * @throws NullPointerException if host is null + * @since 1.1 + * @deprecated use {@link #checkPermission(Permission)} instead + */ + public void checkMulticast(InetAddress addr, byte ttl) + { + // XXX Should be: + // checkPermission(new SocketPermission(addr.getHostAddress(), + // "accept,connect")); + throw new SecurityException("Cannot read or write multicast."); + } + + /** + * Check if the current thread is allowed to read or write all the system + * properties at once. This method is called by System.getProperties() + * and setProperties(). The default implementation checks + * <code>PropertyPermission("*", "read,write")</code>. If you override + * this, call <code>super.checkPropertiesAccess</code> rather than + * throwing an exception. + * + * @throws SecurityException if permission is denied + * @see System#getProperties() + * @see System#setProperties(Properties) + */ + public void checkPropertiesAccess() + { + // XXX Should be: + // checkPermission(new PropertyPermission("*", "read,write")); + throw new SecurityException("Cannot access all system properties at once."); + } + + /** + * Check if the current thread is allowed to read a particular system + * property (writes are checked directly via checkPermission). This method + * is called by System.getProperty() and setProperty(). The default + * implementation checks <code>PropertyPermission(key, "read")</code>. If + * you override this, call <code>super.checkPropertyAccess</code> rather + * than throwing an exception. + * + * @throws SecurityException if permission is denied + * @throws NullPointerException if key is null + * @throws IllegalArgumentException if key is "" + * @see System#getProperty(String) + */ + public void checkPropertyAccess(String key) + { + // XXX Should be: checkPermission(new PropertyPermission(key, "read")); + throw new SecurityException("Cannot access individual system properties."); + } + + /** + * Check if the current thread is allowed to create a top-level window. If + * it is not, the operation should still go through, but some sort of + * nonremovable warning should be placed on the window to show that it + * is untrusted. This method is called by Window.Window(). The default + * implementation checks + * <code>AWTPermission("showWindowWithoutWarningBanner")</code>, and returns + * true if no exception was thrown. If you override this, use + * <code>return super.checkTopLevelWindow</code> rather than returning + * false. + * + * @param window the window to create + * @return true if there is permission to show the window without warning + * @throws NullPointerException if window is null + * @see Window#Window(Frame) + */ + public boolean checkTopLevelWindow(Object window) + { + // Should be: + // if (window == null) + // throw new NullPointerException(); + // try + // { + // checkPermission(new AWTPermission("showWindowWithoutWarningBanner")); + // return true; + // } + // catch (SecurityException e) + // { + // return false; + // } + return false; + } + + /** + * Check if the current thread is allowed to create a print job. This + * method is called by Toolkit.getPrintJob(). The default implementation + * checks <code>RuntimePermission("queuePrintJob")</code>. If you override + * this, call <code>super.checkPrintJobAccess</code> rather than throwing + * an exception. + * + * @throws SecurityException if permission is denied + * @see Toolkit#getPrintJob(Frame, String, Properties) + * @since 1.1 + */ + public void checkPrintJobAccess() + { + // XXX Should be: checkPermission(new RuntimePermission("queuePrintJob")); + throw new SecurityException("Cannot create print jobs."); + } + + /** + * Check if the current thread is allowed to use the system clipboard. This + * method is called by Toolkit.getSystemClipboard(). The default + * implementation checks <code>AWTPermission("accessClipboard")</code>. If + * you override this, call <code>super.checkSystemClipboardAccess</code> + * rather than throwing an exception. + * + * @throws SecurityException if permission is denied + * @see Toolkit#getSystemClipboard() + * @since 1.1 + */ + public void checkSystemClipboardAccess() + { + // XXX Should be: checkPermission(new AWTPermission("accessClipboard")); + throw new SecurityException("Cannot access the system clipboard."); + } + + /** + * Check if the current thread is allowed to use the AWT event queue. This + * method is called by Toolkit.getSystemEventQueue(). The default + * implementation checks <code>AWTPermission("accessEventQueue")</code>. + * you override this, call <code>super.checkAwtEventQueueAccess</code> + * rather than throwing an exception. + * + * @throws SecurityException if permission is denied + * @see Toolkit#getSystemEventQueue() + * @since 1.1 + */ + public void checkAwtEventQueueAccess() + { + // Should be: checkPermission(new AWTPermission("accessEventQueue")); + throw new SecurityException("Cannot access the AWT event queue."); + } + + /** + * Check if the current thread is allowed to access the specified package + * at all. This method is called by ClassLoader.loadClass() in user-created + * ClassLoaders. The default implementation gets a list of all restricted + * packages, via <code>Security.getProperty("package.access")</code>. Then, + * if packageName starts with or equals any restricted package, it checks + * <code>RuntimePermission("accessClassInPackage." + packageName)</code>. + * If you override this, you should call + * <code>super.checkPackageAccess</code> before doing anything else. + * + * @param packageName the package name to check access to + * @throws SecurityException if permission is denied + * @throws NullPointerException if packageName is null + * @see ClassLoader#loadClass(String, boolean) + * @see Security#getProperty(String) + */ + public void checkPackageAccess(String packageName) + { + // XXX Implement this. + throw new SecurityException("Cannot access packages via the ClassLoader."); + } + + /** + * Check if the current thread is allowed to define a class into the + * specified package. This method is called by ClassLoader.loadClass() in + * user-created ClassLoaders. The default implementation gets a list of all + * restricted packages, via + * <code>Security.getProperty("package.definition")</code>. Then, if + * packageName starts with or equals any restricted package, it checks + * <code>RuntimePermission("defineClassInPackage." + packageName)</code>. + * If you override this, you should call + * <code>super.checkPackageDefinition</code> before doing anything else. + * + * @param packageName the package name to check access to + * @throws SecurityException if permission is denied + * @throws NullPointerException if packageName is null + * @see ClassLoader#loadClass(String, boolean) + * @see Security#getProperty(String) + */ + public void checkPackageDefinition(String packageName) + { + // XXX Implement this. + throw new SecurityException("Cannot load classes into any packages via the ClassLoader."); + } + + /** + * Check if the current thread is allowed to set the current socket factory. + * This method is called by Socket.setSocketImplFactory(), + * ServerSocket.setSocketFactory(), and URL.setURLStreamHandlerFactory(). + * The default implementation checks + * <code>RuntimePermission("setFactory")</code>. If you override this, call + * <code>super.checkSetFactory</code> rather than throwing an exception. + * + * @throws SecurityException if permission is denied + * @see Socket#setSocketImplFactory(SocketImplFactory) + * @see ServerSocket#setSocketFactory(SocketImplFactory) + * @see URL#setURLStreamHandlerFactory(URLStreamHandlerFactory) + */ + public void checkSetFactory() + { + // XXX Should be: checkPermission(new RuntimePermission("setFactory")); + throw new SecurityException("Cannot set the socket factory."); + } + + /** + * Check if the current thread is allowed to get certain types of Methods, + * Fields and Constructors from a Class object. This method is called by + * Class.getMethod[s](), Class.getField[s](), Class.getConstructor[s], + * Class.getDeclaredMethod[s](), Class.getDeclaredField[s](), and + * Class.getDeclaredConstructor[s](). The default implementation allows + * PUBLIC access, and access to classes defined by the same classloader as + * the code performing the reflection. Otherwise, it checks + * <code>RuntimePermission("accessDeclaredMembers")</code>. If you override + * this, do not call <code>super.checkMemberAccess</code>, as this would + * mess up the stack depth check that determines the ClassLoader requesting + * the access. + * + * @param c the Class to check + * @param memberType either DECLARED or PUBLIC + * @throws SecurityException if permission is denied, including when + * memberType is not DECLARED or PUBLIC + * @throws NullPointerException if c is null + * @see Class + * @see Member#DECLARED + * @see Member#PUBLIC + * @since 1.1 + */ + public void checkMemberAccess(Class c, int memberType) + { + // XXX Implement this. + throw new SecurityException("Cannot access members of classes."); + } + + /** + * Test whether a particular security action may be taken. The default + * implementation checks <code>SecurityPermission(action)</code>. If you + * override this, call <code>super.checkSecurityAccess</code> rather than + * throwing an exception. + * + * @param action the desired action to take + * @throws SecurityException if permission is denied + * @throws NullPointerException if action is null + * @throws IllegalArgumentException if action is "" + * @since 1.1 + */ + public void checkSecurityAccess(String action) + { + checkPermission(new SecurityPermission(action)); + } + + /** + * Get the ThreadGroup that a new Thread should belong to by default. Called + * by Thread.Thread(). The default implementation returns the current + * ThreadGroup of the current Thread. <STRONG>Spec Note:</STRONG> it is not + * clear whether the new Thread is guaranteed to pass the + * checkAccessThreadGroup() test when using this ThreadGroup, but I presume + * so. + * + * @return the ThreadGroup to put the new Thread into + * @since 1.1 + */ + public ThreadGroup getThreadGroup() + { + return Thread.currentThread().getThreadGroup(); + } +} // class SecurityManager + +// XXX This class is unnecessary. class SecurityContext { Class[] classes; SecurityContext(Class[] classes) { diff --git a/java/lang/System.java b/java/lang/System.java index 9f6283bbe..a1b009467 100644 --- a/java/lang/System.java +++ b/java/lang/System.java @@ -38,8 +38,13 @@ exception statement from your version. */ package java.lang; -import java.io.*; -import java.util.*; +import java.io.FileInputStream; +import java.io.FileDescriptor; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.io.PrintStream; +import java.util.Properties; +import java.util.PropertyPermission; import gnu.classpath.Configuration; /** @@ -72,9 +77,128 @@ public class System } /** - * Stores the system properties. + * The default properties. Read them in once, then stuff them as defaults + * into future properties to save time when recreating properties via + * <code>setProperties(null)</code>. This should not be modified. */ - private static Properties properties; + private static final Properties defaultProperties = new Properties(); + static + { + VMSystem.insertSystemProperties(defaultProperties); + defaultProperties.put("gnu.cpu.endian", + isWordsBigEndian() ? "big" : "little"); + + // Common encoding aliases. See gnu.java.io.EncodingManager. + defaultProperties.put("gnu.java.io.encoding_scheme_alias.ISO-8859-1", + "8859_1"); + defaultProperties.put("gnu.java.io.encoding_scheme_alias.ISO-8859-2", + "8859_2"); + defaultProperties.put("gnu.java.io.encoding_scheme_alias.ISO-8859-3", + "8859_3"); + defaultProperties.put("gnu.java.io.encoding_scheme_alias.ISO-8859-4", + "8859_4"); + defaultProperties.put("gnu.java.io.encoding_scheme_alias.ISO-8859-5", + "8859_5"); + defaultProperties.put("gnu.java.io.encoding_scheme_alias.ISO-8859-6", + "8859_6"); + defaultProperties.put("gnu.java.io.encoding_scheme_alias.ISO-8859-7", + "8859_7"); + defaultProperties.put("gnu.java.io.encoding_scheme_alias.ISO-8859-8", + "8859_8"); + defaultProperties.put("gnu.java.io.encoding_scheme_alias.ISO-8859-9", + "8859_9"); + + defaultProperties.put("gnu.java.io.encoding_scheme_alias.iso-8859-1", + "8859_1"); + defaultProperties.put("gnu.java.io.encoding_scheme_alias.iso-8859-2", + "8859_2"); + defaultProperties.put("gnu.java.io.encoding_scheme_alias.iso-8859-3", + "8859_3"); + defaultProperties.put("gnu.java.io.encoding_scheme_alias.iso-8859-4", + "8859_4"); + defaultProperties.put("gnu.java.io.encoding_scheme_alias.iso-8859-5", + "8859_5"); + defaultProperties.put("gnu.java.io.encoding_scheme_alias.iso-8859-6", + "8859_6"); + defaultProperties.put("gnu.java.io.encoding_scheme_alias.iso-8859-7", + "8859_7"); + defaultProperties.put("gnu.java.io.encoding_scheme_alias.iso-8859-8", + "8859_8"); + defaultProperties.put("gnu.java.io.encoding_scheme_alias.iso-8859-9", + "8859_9"); + + defaultProperties.put("gnu.java.io.encoding_scheme_alias.iso8859_1", + "8859_1"); + defaultProperties.put("gnu.java.io.encoding_scheme_alias.iso8859_2", + "8859_2"); + defaultProperties.put("gnu.java.io.encoding_scheme_alias.iso8859_3", + "8859_3"); + defaultProperties.put("gnu.java.io.encoding_scheme_alias.iso8859_4", + "8859_4"); + defaultProperties.put("gnu.java.io.encoding_scheme_alias.iso8859_5", + "8859_5"); + defaultProperties.put("gnu.java.io.encoding_scheme_alias.iso8859_6", + "8859_6"); + defaultProperties.put("gnu.java.io.encoding_scheme_alias.iso8859_7", + "8859_7"); + defaultProperties.put("gnu.java.io.encoding_scheme_alias.iso8859_8", + "8859_8"); + defaultProperties.put("gnu.java.io.encoding_scheme_alias.iso8859_9", + "8859_9"); + + defaultProperties.put("gnu.java.io.encoding_scheme_alias.iso-latin-1", + "8859_1"); + defaultProperties.put("gnu.java.io.encoding_scheme_alias.iso-latin-2", + "8859_2"); + defaultProperties.put("gnu.java.io.encoding_scheme_alias.iso-latin-3", + "8859_3"); + defaultProperties.put("gnu.java.io.encoding_scheme_alias.iso-latin-4", + "8859_4"); + defaultProperties.put("gnu.java.io.encoding_scheme_alias.iso-latin-5", + "8859_5"); + defaultProperties.put("gnu.java.io.encoding_scheme_alias.iso-latin-6", + "8859_6"); + defaultProperties.put("gnu.java.io.encoding_scheme_alias.iso-latin-7", + "8859_7"); + defaultProperties.put("gnu.java.io.encoding_scheme_alias.iso-latin-8", + "8859_8"); + defaultProperties.put("gnu.java.io.encoding_scheme_alias.iso-latin-9", + "8859_9"); + + defaultProperties.put("gnu.java.io.encoding_scheme_alias.latin1", + "8859_1"); + defaultProperties.put("gnu.java.io.encoding_scheme_alias.latin2", + "8859_2"); + defaultProperties.put("gnu.java.io.encoding_scheme_alias.latin3", + "8859_3"); + defaultProperties.put("gnu.java.io.encoding_scheme_alias.latin4", + "8859_4"); + defaultProperties.put("gnu.java.io.encoding_scheme_alias.latin5", + "8859_5"); + defaultProperties.put("gnu.java.io.encoding_scheme_alias.latin6", + "8859_6"); + defaultProperties.put("gnu.java.io.encoding_scheme_alias.latin7", + "8859_7"); + defaultProperties.put("gnu.java.io.encoding_scheme_alias.latin8", + "8859_8"); + defaultProperties.put("gnu.java.io.encoding_scheme_alias.latin9", + "8859_9"); + + defaultProperties.put("gnu.java.io.encoding_scheme_alias.UTF-8", "UTF8"); + defaultProperties.put("gnu.java.io.encoding_scheme_alias.utf-8", "UTF8"); + + // XXX FIXME - Temp hack for old systems that set the wrong property + if (defaultProperties.get("java.io.tmpdir") == null) + defaultProperties.put("java.io.tmpdir", + defaultProperties.get("java.tmpdir")); + } + + /** + * Stores the current system properties. This can be modified by + * {@link #setProperties(Properties)}, but will never be null, because + * setProperties(null) sucks in the default properties. + */ + private static Properties properties = new Properties(defaultProperties); /** * The standard InputStream. This is assigned at startup and starts its @@ -86,8 +210,8 @@ public class System * other processes or files. That should all be transparent to you, * however. */ - public static final InputStream in; - + public static final InputStream in + = new FileInputStream(FileDescriptor.in); /** * The standard output PrintStream. This is assigned at startup and * starts its life perfectly valid. Although it is marked final, you can @@ -98,8 +222,8 @@ public class System * output to other processes or files. That should all be transparent to * you, however. */ - public static final PrintStream out; - + public static final PrintStream out + = new PrintStream(new FileOutputStream(FileDescriptor.out)); /** * The standard output PrintStream. This is assigned at startup and * starts its life perfectly valid. Although it is marked final, you can @@ -110,25 +234,8 @@ public class System * output to other processes or files. That should all be transparent to * you, however. */ - public static final PrintStream err; - - /** - * Initialize the properties and I/O streams. - */ - static - { - properties = new Properties(); - VMSystem.insertSystemProperties(properties); - - // XXX FIXME - Temp hack for old systems that set the wrong property - if (properties.get("java.io.tmpdir") == null) - properties.put("java.io.tmpdir", properties.get("java.tmpdir")); - - insertGNUProperties(); - in = new FileInputStream(FileDescriptor.in); - out = new PrintStream(new FileOutputStream(FileDescriptor.out)); - err = new PrintStream(new FileOutputStream(FileDescriptor.err)); - } + public static final PrintStream err + = new PrintStream(new FileOutputStream(FileDescriptor.err)); /** * Set {@link #in} to a new InputStream. This uses some VM magic to change @@ -138,10 +245,14 @@ public class System * @param in the new InputStream * @throws SecurityException if permission is denied * @since 1.1 - * @XXX Perform security check (which means setIn should probably be in - * Java, and add setIn0 as native). */ - public static native void setIn(InputStream in); + public static void setIn(InputStream in) + { + SecurityManager sm = Runtime.getSecurityManager(); + if (sm != null) + sm.checkPermission(new RuntimePermission("setIO")); + setIn0(in); + } /** * Set {@link #out} to a new PrintStream. This uses some VM magic to change @@ -151,10 +262,14 @@ public class System * @param out the new PrintStream * @throws SecurityException if permission is denied * @since 1.1 - * @XXX Perform security check (which means setOut should probably be in - * Java, and add setOut0 as native). */ - public static native void setOut(PrintStream out); + public static void setOut(PrintStream out) + { + SecurityManager sm = Runtime.getSecurityManager(); + if (sm != null) + sm.checkPermission(new RuntimePermission("setIO")); + setOut0(out); + } /** * Set {@link #err} to a new PrintStream. This uses some VM magic to change @@ -164,10 +279,14 @@ public class System * @param err the new PrintStream * @throws SecurityException if permission is denied * @since 1.1 - * @XXX Perform security check (which means setErr should probably be in - * Java, and add setErr0 as native). */ - public static native void setErr(PrintStream err); + public static void setErr(PrintStream err) + { + SecurityManager sm = Runtime.getSecurityManager(); + if (sm != null) + sm.checkPermission(new RuntimePermission("setIO")); + setErr0(err); + } /** * Set the current SecurityManager. If a security manager already exists, @@ -263,7 +382,7 @@ public class System * <code>checkPropertiesAccess</code>. Note that a security manager may * allow getting a single property, but not the entire group. * - * <p>The default properties include: + * <p>The required properties include: * <dl> * <dt>java.version <dd>Java version number * <dt>java.vendor <dd>Java vendor specific string @@ -295,6 +414,19 @@ public class System * <dt>user.dir <dd>User's current working directory * </dl> * + * In addition, gnu defines several other properties, where ? stands for + * each character in '0' through '9': + * <dl> + * <dt> gnu.cpu.endian <dd>big or little + * <dt> gnu.java.io.encoding_scheme_alias.ISO-8859-? <dd>8859_? + * <dt> gnu.java.io.encoding_scheme_alias.iso-8859-? <dd>8859_? + * <dt> gnu.java.io.encoding_scheme_alias.iso8859_? <dd>8859_? + * <dt> gnu.java.io.encoding_scheme_alias.iso-latin-_? <dd>8859_? + * <dt> gnu.java.io.encoding_scheme_alias.latin? <dd>8859_? + * <dt> gnu.java.io.encoding_scheme_alias.UTF-8 <dd>UTF8 + * <dt> gnu.java.io.encoding_scheme_alias.utf-8 <dd>UTF8 + * </dl> + * * @return the system properties, will never be null * @throws SecurityException if permission is denied */ @@ -303,7 +435,6 @@ public class System SecurityManager sm = Runtime.getSecurityManager(); if (sm != null) sm.checkPropertiesAccess(); - //XXX Make sure this is not null, and be thread-safe return properties; } @@ -321,7 +452,8 @@ public class System SecurityManager sm = Runtime.getSecurityManager(); if (sm != null) sm.checkPropertiesAccess(); - // XXX Special case null + if (properties == null) + properties = new Properties(defaultProperties); System.properties = properties; } @@ -340,7 +472,6 @@ public class System SecurityManager sm = Runtime.getSecurityManager(); if (sm != null) sm.checkPropertyAccess(key); - // XXX ensure properties is not null, and be thread-safe return properties.getProperty(key); } @@ -360,7 +491,6 @@ public class System SecurityManager sm = Runtime.getSecurityManager(); if (sm != null) sm.checkPropertyAccess(key); - // XXX ensure properties is not null, and be thread-safe return properties.getProperty(key, def); } @@ -381,23 +511,22 @@ public class System SecurityManager sm = Runtime.getSecurityManager(); if (sm != null) sm.checkPermission(new PropertyPermission(key, "write")); - // XXX ensure properties is not null, and be thread-safe return (String) properties.setProperty(key, value); } /** - * Get an environment variable. <b>WARNING</b>: This is not the preferred - * way to check properties, nor is it guaranteed to work across all - * implementations. Use <code>getProperty</code> instead. + * This used to get an environment variable, but following Sun's lead, + * it now throws an Error. Use <code>getProperty</code> instead. * * @param name the name of the environment variable - * @return the value of the variable, or null - * @deprecated use {@link #getProperty(String)} + * @return this does not return + * @throws Error this is not supported + * @deprecated use {@link #getProperty(String)}; getenv is not supported */ public static String getenv(String name) { - //XXX This should be a native method, which actually uses getenv(3). - return getProperty(name); + throw new Error("getenv no longer supported, use properties instead: " + + name); } /** @@ -498,94 +627,41 @@ public class System * @param libname the library name, as used in <code>loadLibrary</code> * @return the platform-specific mangling of the name * @since 1.2 - * @XXX Add this method, and its support in VMSystem. + */ public static String mapLibraryName(String libname) { - return VMSystem.mapLibraryName(libname); + // XXX Fix this!!!! + return Runtime.nativeGetLibname("", libname); } + + /** + * Detect big-endian systems. + * + * @return true if the system is big-endian. */ + static native boolean isWordsBigEndian(); /** - * Add Classpath specific system properties. - * <br> - * Current properties: - * <br> - * <ul> - * <li> gnu.cpu.endian - big or little</li> - * <li> gnu.java.io.encoding_scheme_alias.ISO-8859-? - 8859_?</li> - * <li> gnu.java.io.encoding_scheme_alias.iso-8859-? - 8859_?</li> - * <li> gnu.java.io.encoding_scheme_alias.iso8859_? - 8859_?</li> - * <li> gnu.java.io.encoding_scheme_alias.iso-latin-_? - 8859_?</li> - * <li> gnu.java.io.encoding_scheme_alias.latin? - 8859_?</li> - * <li> gnu.java.io.encoding_scheme_alias.UTF-8 - UTF8</li> - * <li> gnu.java.io.encoding_scheme_alias.utf-8 - UTF8</li> - * </ul> - * @see gnu.java.io.EncodingManager - */ - static void insertGNUProperties() - { - properties.put("gnu.cpu.endian", - isWordsBigEndian() ? "big" : "little"); + * Set {@link #in} to a new InputStream. + * + * @param in the new InputStream + * @see #setIn(InputStream) + */ + private static native void setIn0(InputStream in); - // Common encoding aliases. See gnu.java.io.EncodingManager. - properties.put("gnu.java.io.encoding_scheme_alias.ISO-8859-1", "8859_1"); - properties.put("gnu.java.io.encoding_scheme_alias.ISO-8859-2", "8859_2"); - properties.put("gnu.java.io.encoding_scheme_alias.ISO-8859-3", "8859_3"); - properties.put("gnu.java.io.encoding_scheme_alias.ISO-8859-4", "8859_4"); - properties.put("gnu.java.io.encoding_scheme_alias.ISO-8859-5", "8859_5"); - properties.put("gnu.java.io.encoding_scheme_alias.ISO-8859-6", "8859_6"); - properties.put("gnu.java.io.encoding_scheme_alias.ISO-8859-7", "8859_7"); - properties.put("gnu.java.io.encoding_scheme_alias.ISO-8859-8", "8859_8"); - properties.put("gnu.java.io.encoding_scheme_alias.ISO-8859-9", "8859_9"); - - properties.put("gnu.java.io.encoding_scheme_alias.iso-8859-1", "8859_1"); - properties.put("gnu.java.io.encoding_scheme_alias.iso-8859-2", "8859_2"); - properties.put("gnu.java.io.encoding_scheme_alias.iso-8859-3", "8859_3"); - properties.put("gnu.java.io.encoding_scheme_alias.iso-8859-4", "8859_4"); - properties.put("gnu.java.io.encoding_scheme_alias.iso-8859-5", "8859_5"); - properties.put("gnu.java.io.encoding_scheme_alias.iso-8859-6", "8859_6"); - properties.put("gnu.java.io.encoding_scheme_alias.iso-8859-7", "8859_7"); - properties.put("gnu.java.io.encoding_scheme_alias.iso-8859-8", "8859_8"); - properties.put("gnu.java.io.encoding_scheme_alias.iso-8859-9", "8859_9"); - - properties.put("gnu.java.io.encoding_scheme_alias.iso8859_1", "8859_1"); - properties.put("gnu.java.io.encoding_scheme_alias.iso8859_2", "8859_2"); - properties.put("gnu.java.io.encoding_scheme_alias.iso8859_3", "8859_3"); - properties.put("gnu.java.io.encoding_scheme_alias.iso8859_4", "8859_4"); - properties.put("gnu.java.io.encoding_scheme_alias.iso8859_5", "8859_5"); - properties.put("gnu.java.io.encoding_scheme_alias.iso8859_6", "8859_6"); - properties.put("gnu.java.io.encoding_scheme_alias.iso8859_7", "8859_7"); - properties.put("gnu.java.io.encoding_scheme_alias.iso8859_8", "8859_8"); - properties.put("gnu.java.io.encoding_scheme_alias.iso8859_9", "8859_9"); - - properties.put("gnu.java.io.encoding_scheme_alias.iso-latin-1", "8859_1"); - properties.put("gnu.java.io.encoding_scheme_alias.iso-latin-2", "8859_2"); - properties.put("gnu.java.io.encoding_scheme_alias.iso-latin-3", "8859_3"); - properties.put("gnu.java.io.encoding_scheme_alias.iso-latin-4", "8859_4"); - properties.put("gnu.java.io.encoding_scheme_alias.iso-latin-5", "8859_5"); - properties.put("gnu.java.io.encoding_scheme_alias.iso-latin-6", "8859_6"); - properties.put("gnu.java.io.encoding_scheme_alias.iso-latin-7", "8859_7"); - properties.put("gnu.java.io.encoding_scheme_alias.iso-latin-8", "8859_8"); - properties.put("gnu.java.io.encoding_scheme_alias.iso-latin-9", "8859_9"); - - properties.put("gnu.java.io.encoding_scheme_alias.latin1", "8859_1"); - properties.put("gnu.java.io.encoding_scheme_alias.latin2", "8859_2"); - properties.put("gnu.java.io.encoding_scheme_alias.latin3", "8859_3"); - properties.put("gnu.java.io.encoding_scheme_alias.latin4", "8859_4"); - properties.put("gnu.java.io.encoding_scheme_alias.latin5", "8859_5"); - properties.put("gnu.java.io.encoding_scheme_alias.latin6", "8859_6"); - properties.put("gnu.java.io.encoding_scheme_alias.latin7", "8859_7"); - properties.put("gnu.java.io.encoding_scheme_alias.latin8", "8859_8"); - properties.put("gnu.java.io.encoding_scheme_alias.latin9", "8859_9"); - - properties.put("gnu.java.io.encoding_scheme_alias.UTF-8", "UTF8"); - properties.put("gnu.java.io.encoding_scheme_alias.utf-8", "UTF8"); - } + /** + * Set {@link #out} to a new PrintStream. + * + * @param out the new PrintStream + * @see #setOut(PrintStream) + */ + private static native void setOut0(PrintStream out); /** - * Detect big-endian systems. + * Set {@link #err} to a new PrintStream. * - * @return true if the system is big-endian. + * @param err the new PrintStream + * @see #setErr(PrintStream) */ - static native boolean isWordsBigEndian(); + private static native void setErr0(PrintStream err); } diff --git a/java/util/PropertyPermission.java b/java/util/PropertyPermission.java index 8a87c1301..bb03e45f3 100644 --- a/java/util/PropertyPermission.java +++ b/java/util/PropertyPermission.java @@ -111,6 +111,7 @@ public final class PropertyPermission extends BasicPermission * * @param name the name of the property * @param actions the action string + * @throws NullPointerException if name is null * @throws IllegalArgumentException if name string contains an * illegal wildcard or actions string contains an illegal action * (this includes a null actions string) @@ -187,16 +188,14 @@ public final class PropertyPermission extends BasicPermission */ public boolean implies(Permission p) { - if (! (p instanceof PropertyPermission)) - return false; - - // We have to check the actions. - PropertyPermission pp = (PropertyPermission) p; - if ((pp.actions & ~actions) != 0) - return false; - - // BasicPermission checks for name. - return super.implies(p); + // BasicPermission checks for name and type. + if (super.implies(p)) + { + // We have to check the actions. + PropertyPermission pp = (PropertyPermission) p; + return (pp.actions & ~actions) == 0; + } + return false; } /** @@ -209,10 +208,7 @@ public final class PropertyPermission extends BasicPermission */ public boolean equals(Object obj) { - if (! (obj instanceof PropertyPermission)) - return false; - PropertyPermission p = (PropertyPermission) obj; - return actions == p.actions && super.equals(p); + return super.equals(obj) && actions == ((PropertyPermission) obj).actions; } /** diff --git a/java/util/PropertyPermissionCollection.java b/java/util/PropertyPermissionCollection.java index 10f2b7e7c..c96560033 100644 --- a/java/util/PropertyPermissionCollection.java +++ b/java/util/PropertyPermissionCollection.java @@ -92,16 +92,22 @@ class PropertyPermissionCollection extends PermissionCollection if (old != null) { if ((pp.actions | old.actions) == old.actions) - pp = old; // Old includes pp. + pp = old; // Old implies pp. else if ((pp.actions | old.actions) != pp.actions) - // Here pp doesn't include old; the only case left is both actions. + // Here pp doesn't imply old; the only case left is both actions. pp = new PropertyPermission(name, "read,write"); } permissions.put(name, pp); } /** - * Returns true if this collection implies the given permission. + * Returns true if this collection implies the given permission. This even + * returns true for this case: + * <pre> + * collection.add(new PropertyPermission("a.*", "read")); + * collection.add(new PropertyPermission("a.b.*", "write")); + * collection.implies(new PropertyPermission("a.b.c", "read,write")); + * <pre> * * @param permission the permission to check * @return true if it is implied by this @@ -111,10 +117,13 @@ class PropertyPermissionCollection extends PermissionCollection if (! (permission instanceof PropertyPermission)) return false; PropertyPermission toImply = (PropertyPermission) permission; + int actions = toImply.actions; + if (all_allowed) { int all_actions = ((PropertyPermission) permissions.get("*")).actions; - if ((toImply.actions & ~all_actions) == 0) + actions &= ~all_actions; + if (actions == 0) return true; } @@ -130,8 +139,12 @@ class PropertyPermissionCollection extends PermissionCollection { PropertyPermission forName = (PropertyPermission) permissions.get(name); - if (forName != null && (toImply.actions & ~forName.actions) == 0) - return true; + if (forName != null) + { + actions &= ~forName.actions; + if (actions == 0) + return true; + } prefixLength = name.lastIndexOf('.', prefixLength); if (prefixLength < 0) |