Information about the built-in JDK permission types and associated risks of granting each permission. Information about methods that require permissions to be in effect in order to be successful, and for each method lists the required permission.
A permission represents access to a system resource. In order for a resource access to be allowed for an applet (or an application running with a security manager), the corresponding permission must be explicitly granted to the code attempting the access.
A permission typically has a name (often referred to as a "target name") and, in some cases, a comma-separated list of one or more actions.
For example, the following code creates a FilePermission
object representing read access to the file named abc
in the /tmp
directory:
perm = new java.io.FilePermission("/tmp/abc", "read");
Here, the target name is "/tmp/abc
" and the action string is "read
".
Important:
The above statement creates a permission object. A permission object represents, but does not grant access to, a system resource. Permission objects are constructed and assigned ("granted") to code based on the policy in effect. When a permission object is assigned to some code, that code is granted the permission to access the system resource specified in the permission object, in the specified manner. A permission object may also be constructed by the current security manager when making access decisions. In this case, the (target) permission object is created based on the requested access, and checked against the permission objects granted to and held by the code making the request."JavaPolicy"
Policy implementation, the policy can be specified within one or more policy configuration files. The policy file(s) specify what permissions are allowed for code from specified code sources. A sample policy file entry that grants code from the /home/sysadmin
directory read access to the file /tmp/abc
is
grant codeBase "file:/home/sysadmin/" { permission java.io.FilePermission "/tmp/abc", "read"; };To know more about policy file locations and granting permissions in policy files, see Default Policy Implementation and Policy File Syntax.
List of built-in JDK permission types and the risks of granting each permission.
NIO-related related target names.
selectorProvider charsetProviderThese RuntimePermissions are required to be granted to classes which subclass and implement java.nio.channel.spi.SelectorProvider or java.nio.charset.spi.CharsetProvider. The permission is checked during invocation of the abstract base class constructor. These permissions ensure trust in classes which implement these security-sensitive provider mechanisms. For more information, see
java.nio.channels.spi.SelectorProvider
java.nio.channels.spi.CharsetProvider
List of all the methods that require permissions, and for each method the corresponding SecurityManager
method it calls.
Note:
The list of all the methods discussed in this document is not complete and does not include several methods that require permissions. SeeAPI Documentation
for additional information on methods that throw SecurityException
and the permissions that are required.In the default SecurityManager
method implementations, a call to a method in the Method column can only be successful if the permission specified in the corresponding entry in the SecurityManager Method column is allowed by the policy currently in effect.
Example 1-1 SecurityManager checkPermission Method
getSystemEventQueue
method in the java.awt.Toolkit
class results in a call to the checkPermission
SecurityManager method, which can only be successful if the following permission is granted to code on the call stack:
java.awt.AWTPermission "accessEventQueue";
Method | SecurityManager Method | Permission |
---|---|---|
java.awt.Toolkit getSystemEventQueue(); |
checkPermission |
java.awt.AWTPermission "accessEventQueue"; |
The following convention means the runtime value of foo
replaces the string {foo}
in the permission name:
Method | SecurityManager Method | Permission |
---|---|---|
some.package.class public static void someMethod(String foo); |
checkXXX |
SomePermission "{foo}"; |
Example 1-2 SecurityManager checkRead Method
FileInputStream
method in the java.io.FileInputStream
class results in a call to the checkRead
SecurityManager method, which can only be successful if the following permission is granted to code on the call stack:
Method | SecurityManager Method | Permission |
---|---|---|
java.io.FileInputStream FileInputStream(String name) |
checkRead(String) |
java.io.FilePermission "{name}", "read"; |
If the FileInputStream
method (in this case, a constructor) is called with "/test/MyTestFile"
as the name
argument, as in
FileInputStream("/test/MyTestFile");
then in order for the call to succeed, the following permission must be set in the current policy, allowing read access to the file "/test/MyTestFile"
:
java.io.FilePermission "/test/MyTestFile", "read";
More specifically, the permission must either be explicitly set, as above, or implied by another permission, such as the following:
java.io.FilePermission "/test/*", "read";
which allows read access to any files in the "/test"
directory.
Example 1-3 SecurityManager checkAccept Method
In some cases, a term in braces is not exactly the same as the name of a specific method argument but is meant to represent the relevant value:
Method | SecurityManager Method | Permission |
---|---|---|
java.net.DatagramSocket public synchronized void receive(DatagramPacket p); |
checkAccept({host}, {port}) |
java.net.SocketPermission "{host}:{port}", "accept"; |
Here, the appropriate host and port values are calculated by the receive
method and passed to checkAccept
.
In most cases, just the name of the SecurityManager method called is listed. Where the method is one of multiple methods of the same name, the argument types are also listed, for example for checkRead(String)
and checkRead(FileDescriptor)
. In other cases where arguments may be relevant, they are also listed.
Methods and the Permissions
The following table is ordered by package name, the methods in classes in the java.awt
package are listed first, followed by methods in classes in the java.io
package, and so on:
Table 1-6 Methods and the Permissions
Method | SecurityManager Method | Permission |
---|---|---|
java.awt.Graphics2d public abstract void setComposite(Composite comp) |
checkPermission | java.awt.AWTPermission "readDisplayPixels" if this Graphics2D context is drawing to a Component on the display screen and the Composite is a custom object rather than an instance of the AlphaComposite class. Note: The setComposite method is actually abstract and thus can't invoke security checks. Each actual implementation of the method should call the java.lang.SecurityManager checkPermission method with a java.awt.AWTPermission("readDisplayPixels") permission under the conditions noted. |
java.awt.Robot public Robot() public Robot(GraphicsDevice screen) |
checkPermission | java.awt.AWTPermission "createRobot" |
java.awt.Toolkit public void addAWTEventListener( AWTEventListener listener, long eventMask) public void removeAWTEventListener( AWTEventListener listener) |
checkPermission | java.awt.AWTPermission "listenToAllAWTEvents" |
java.awt.Toolkit public abstract PrintJob getPrintJob( Frame frame, String jobtitle, Properties props) |
checkPrintJobAccess |
java.lang.RuntimePermission "queuePrintJob" Note: The getPrintJob method is actually abstract and thus can't invoke security checks. Each actual implementation of the method should call the java.lang.SecurityManager checkPrintJobAccess method, which is successful only if the java.lang.RuntimePermission "queuePrintJob" permission is currently allowed. |
java.awt.Toolkit public abstract Clipboard getSystemClipboard() |
checkPermission |
java.awt.AWTPermission "accessClipboard" Note: The getSystemClipboard method is actually abstract and thus can't invoke security checks. Each actual implementation of the method should call the checkPermission method, which is successful only if the java.awt.AWTPermission "accessClipboard" permission is currently allowed. |
java.awt.Toolkit public final EventQueue getSystemEventQueue() |
checkPermission | java.awt.AWTPermission "accessEventQueue" |
java.awt.Window Window() |
checkPermission | If java.awt.AWTPermission "showWindowWithoutWarningBanner" is set, the window will be displayed without a banner warning that the window was created by an applet. It it's not set, such a banner will be displayed. |
java.beans.Beans public static void setDesignTime( boolean isDesignTime) public static void setGuiAvailable( boolean isGuiAvailable) java.beans.Introspector public static synchronized void setBeanInfoSearchPath(String path[]) java.beans.PropertyEditorManager public static void registerEditor( Class targetType, Class editorClass) public static synchronized void setEditorSearchPath(String path[]) |
checkPropertiesAccess | java.util.PropertyPermission "*", "read,write" |
java.io.File public boolean delete() public void deleteOnExit() |
checkDelete(String) | java.io.FilePermission "{name}", "delete" |
java.io.FileInputStream FileInputStream(FileDescriptor fdObj) |
checkRead(FileDescriptor) | java.lang.RuntimePermission "readFileDescriptor" |
java.io.FileInputStream FileInputStream(String name) FileInputStream(File file) java.io.File public boolean exists() public boolean canRead() public boolean isFile() public boolean isDirectory() public boolean isHidden() public long lastModified() public long length() public String[] list() public String[] list( FilenameFilter filter) public File[] listFiles() public File[] listFiles( FilenameFilter filter) public File[] listFiles( FileFilter filter) java.io.RandomAccessFile RandomAccessFile(String name, String mode) RandomAccessFile(File file, String mode) (where mode is "r" in both of these) |
checkRead(String) | java.io.FilePermission "{name}", "read" |
java.io.FileOutputStream FileOutputStream(FileDescriptor fdObj) |
checkWrite(FileDescriptor) | java.lang.RuntimePermission "writeFileDescriptor" |
java.io.FileOutputStream FileOutputStream(File file) FileOutputStream(String name) FileOutputStream(String name, boolean append) java.io.File public boolean canWrite() public boolean createNewFile() public static File createTempFile( String prefix, String suffix) public static File createTempFile( String prefix, String suffix, File directory) public boolean mkdir() public boolean mkdirs() public boolean renameTo(File dest) public boolean setLastModified(long time) public boolean setReadOnly() |
checkWrite(String) | java.io.FilePermission "{name}", "write" |
java.io.ObjectInputStream protected final boolean enableResolveObject(boolean enable); java.io.ObjectOutputStream protected final boolean enableReplaceObject(boolean enable) |
checkPermission | java.io.SerializablePermission "enableSubstitution" |
java.io.ObjectInputStream protected ObjectInputStream() java.io.ObjectOutputStream protected ObjectOutputStream() |
checkPermission | java.io.SerializablePermission "enableSubclassImplementation" |
java.io.RandomAccessFile RandomAccessFile(String name, String mode) (where mode is "rw") |
checkRead(String) and checkWrite(String) | java.io.FilePermission "{name}", "read,write" |
java.lang.Class public static Class forName( String name, boolean initialize, ClassLoader loader) |
checkPermission | If loader is null, and the caller's class loader is not null, then java.lang.RuntimePermission("getClassLoader") |
java.lang.Class public ClassLoader getClassLoader() |
checkPermission | If the caller's class loader is null, or is the same as or an ancestor of the class loader for the class whose class loader is being requested, no permission is needed. Otherwise, java.lang.RuntimePermission "getClassLoader" is required. |
java.lang.Class public Class[] getDeclaredClasses() public Field[] getDeclaredFields() public Method[] getDeclaredMethods() public Constructor[] getDeclaredConstructors() public Field getDeclaredField( String name) public Method getDeclaredMethod(...) public Constructor getDeclaredConstructor(...) |
checkMemberAccess(this, Member.DECLARED) and, if this class is in a package, checkPackageAccess({pkgName}) | Default checkMemberAccess does not require any permissions if "this" class's classloader is the same as that of the caller. Otherwise, it requires java.lang.RuntimePermission "accessDeclaredMembers". If this class is in a package, java.lang.RuntimePermission "accessClassInPackage.{pkgName}" is also required. |
java.lang.Class public Class[] getClasses() public Field[] getFields() public Method[] getMethods() public Constructor[] getConstructors() public Field getField(String name) public Method getMethod(...) public Constructor getConstructor(...) |
checkMemberAccess(this, Member.PUBLIC) and, if class is in a package, checkPackageAccess({pkgName}) | Default checkMemberAccess does not require any permissions when the access type is Member.PUBLIC. If this class is in a package, java.lang.RuntimePermission "accessClassInPackage.{pkgName}" is required. |
java.lang.Class public ProtectionDomain getProtectionDomain() |
checkPermission | java.lang.RuntimePermission "getProtectionDomain" |
java.lang.ClassLoader ClassLoader() ClassLoader(ClassLoader parent) |
checkCreateClassLoader | java.lang.RuntimePermission "createClassLoader" |
java.lang.ClassLoader public static ClassLoader getSystemClassLoader() public ClassLoader getParent() |
checkPermission | If the caller's class loader is null, or is the same as or an ancestor of the class loader for the class whose class loader is being requested, no permission is needed. Otherwise, java.lang.RuntimePermission "getClassLoader" is required. |
java.lang.Runtime public Process exec(String command) public Process exec(String command, String envp[]) public Process exec(String cmdarray[]) public Process exec(String cmdarray[], String envp[]) |
checkExec | java.io.FilePermission "{command}", "execute" |
java.lang.Runtime public void exit(int status) public static void runFinalizersOnExit(boolean value) java.lang.System public static void exit(int status) public static void runFinalizersOnExit(boolean value) |
checkExit(status) where status is 0 for runFinalizersOnExit | java.lang.RuntimePermission "exitVM.{status}" |
java.lang.Runtime public void addShutdownHook(Thread hook) public boolean removeShutdownHook(Thread hook) |
checkPermission | java.lang.RuntimePermission "shutdownHooks" |
java.lang.Runtime public void load(String lib) public void loadLibrary(String lib) java.lang.System public static void load(String filename) public static void loadLibrary( String libname) |
checkLink({libName}) where {libName} is the lib, filename or libname argument | java.lang.RuntimePermission "loadLibrary.{libName}" |
java.lang.SecurityManager methods |
checkPermission | See Table 1-7. |
java.lang.System public static Properties getProperties() public static void setProperties(Properties props) |
checkPropertiesAccess | java.util.PropertyPermission "*", "read,write" |
java.lang.System public static String getProperty(String key) public static String getProperty(String key, String def) |
checkPropertyAccess | java.util.PropertyPermission "{key}", "read" |
java.lang.System public static void setIn(InputStream in) public static void setOut(PrintStream out) public static void setErr(PrintStream err) |
checkPermission | java.lang.RuntimePermission "setIO" |
java.lang.System public static String setProperty(String key, String value) |
checkPermission | java.util.PropertyPermission "{key}", "write" |
java.lang.System public static synchronized void setSecurityManager(SecurityManager s) |
checkPermission | java.lang.RuntimePermission "setSecurityManager" |
java.lang.Thread public ClassLoader getContextClassLoader() |
checkPermission | If the caller's class loader is null, or is the same as or an ancestor of the context class loader for the thread whose context class loader is being requested, no permission is needed. Otherwise, java.lang.RuntimePermission "getClassLoader" is required. |
java.lang.Thread public void setContextClassLoader (ClassLoader cl) |
checkPermission | java.lang.RuntimePermission "setContextClassLoader" |
java.lang.Thread public final void checkAccess() public void interrupt() public final void suspend() public final void resume() public final void setPriority (int newPriority) public final void setName(String name) public final void setDaemon(boolean on) |
checkAccess(this) | java.lang.RuntimePermission "modifyThread" |
java.lang.Thread public static int enumerate(Thread tarray[]) |
checkAccess({threadGroup}) | java.lang.RuntimePermission "modifyThreadGroup" |
java.lang.Thread public final void stop() |
checkAccess(this). Also checkPermission if the current thread is trying to stop a thread other than itself. | java.lang.RuntimePermission "modifyThread". .
Also |
java.lang.Thread public final synchronized void stop(Throwable obj) |
checkAccess(this). Also checkPermission if the current thread is trying to stop a thread other than itself or obj is not an instance of ThreadDeath. | java.lang.RuntimePermission "modifyThread".
Also |
java.lang.Thread Thread() Thread(Runnable target) Thread(String name) Thread(Runnable target, String name) java.lang.ThreadGroup ThreadGroup(String name) ThreadGroup(ThreadGroup parent, String name) |
checkAccess({parentThreadGroup}) | java.lang.RuntimePermission "modifyThreadGroup" |
java.lang.Thread Thread(ThreadGroup group, ...) java.lang.ThreadGroup public final void checkAccess() public int enumerate(Thread list[]) public int enumerate(Thread list[], boolean recurse) public int enumerate(ThreadGroup list[]) public int enumerate(ThreadGroup list[], boolean recurse) public final ThreadGroup getParent() public final void setDaemon(boolean daemon) public final void setMaxPriority(int pri) public final void suspend() public final void resume() public final void destroy() |
checkAccess(this) for ThreadGroup methods, or checkAccess(group) for Thread methods | java.lang.RuntimePermission "modifyThreadGroup" |
java.lang.ThreadGroup public final void interrupt() |
checkAccess(this) | Requires java.lang.RuntimePermission "modifyThreadGroup" . Also requires java.lang.RuntimePermission "modifyThread" , since the java.lang.Thread interrupt() method is called for each thread in the thread group and in all of its subgroups. See the Thread interrupt() method. |
java.lang.ThreadGroup public final void stop() |
checkAccess(this) | Requires java.lang.RuntimePermission "modifyThreadGroup" . Also requires java.lang.RuntimePermission "modifyThread" and possibly java.lang.RuntimePermission "stopThread" , since the java.lang.Thread stop() method is called for each thread in the thread group and in all of its subgroups. See the Thread stop() method. |
java.lang.reflect.AccessibleObject public static void setAccessible(...) public void setAccessible(...) |
checkPermission | java.lang.reflect.ReflectPermission "suppressAccessChecks" |
java.net.Authenticator public static PasswordAuthentication requestPasswordAuthentication( InetAddress addr, int port, String protocol, String prompt, String scheme) |
checkPermission | java.net.NetPermission "requestPasswordAuthentication" |
java.net.Authenticator public static void setDefault(Authenticator a) |
checkPermission | java.net.NetPermission "setDefaultAuthenticator" |
java.net.MulticastSocket public void joinGroup(InetAddress mcastaddr) public void leaveGroup(InetAddress mcastaddr) |
checkMulticast(InetAddress) | java.net.SocketPermission( mcastaddr.getHostAddress(), "accept,connect") |
java.net.DatagramSocket public void send(DatagramPacket p) |
checkMulticast(p.getAddress()) or
checkConnect( p.getAddress().getHostAddress(), p.getPort()) |
if (p.getAddress().isMulticastAddress()) { java.net.SocketPermission( (p.getAddress()).getHostAddress(), "accept,connect") } else {port = p.getPort(); host = p.getAddress().getHostAddress(); if (port == -1) java.net.SocketPermission "{host}","resolve"; else java.net.SocketPermission "{host}:{port}","connect" |
java.net.MulticastSocket public synchronized void send(DatagramPacket p, byte ttl) |
checkMulticast(p.getAddress(), ttl) or
checkConnect( p.getAddress().getHostAddress(), p.getPort()) |
if (p.getAddress().isMulticastAddress()) { java.net.SocketPermission( (p.getAddress()).getHostAddress(), "accept,connect") } else { port = p.getPort(); host = p.getAddress().getHostAddress(); if (port == -1) java.net.SocketPermission "{host}","resolve"; else java.net.SocketPermission "{host}:{port}","connect" } |
java.net.InetAddress public String getHostName() public static InetAddress[] getAllByName(String host) public static InetAddress getLocalHost() java.net.DatagramSocket public InetAddress getLocalAddress() |
checkConnect({host}, -1) | java.net.SocketPermission "{host}", "resolve" |
java.net.ServerSocket ServerSocket(...) java.net.DatagramSocket DatagramSocket(...) java.net.MulticastSocket MulticastSocket(...) |
checkListen({port}) | java.net.SocketPermission "localhost:{port}","listen"; |
java.net.ServerSocket public Socket accept() protected final void implAccept(Socket s) |
checkAccept({host}, {port}) | java.net.SocketPermission "{host}:{port}", "accept" |
java.net.ServerSocket public static synchronized void setSocketFactory(...) java.net.Socket public static synchronized void setSocketImplFactory(...) java.net.URL public static synchronized void setURLStreamHandlerFactory(...) java.net.URLConnection public static synchronized void setContentHandlerFactory(...) public static void setFileNameMap(FileNameMap map) java.net.HttpURLConnection public static void setFollowRedirects(boolean set) java.rmi.activation.ActivationGroup public static synchronized ActivationGroup createGroup(...) public static synchronized void setSystem(ActivationSystem system) java.rmi.server.RMISocketFactory public synchronized static void setSocketFactory(...) |
checkSetFactory | java.lang.RuntimePermission "setFactory" |
java.net.Socket Socket(...) |
checkConnect({host}, {port}) | java.net.SocketPermission "{host}:{port}", "connect" |
java.net.DatagramSocket public synchronized void receive(DatagramPacket p) |
checkAccept({host}, {port}) | java.net.SocketPermission "{host}:{port}", "accept" |
java.net.URL URL(...) |
checkPermission | java.net.NetPermission "specifyStreamHandler" |
java.net.URLClassLoader URLClassLoader(...) |
checkCreateClassLoader | java.lang.RuntimePermission "createClassLoader" |
java.security.AccessControlContext public AccessControlContext(AccessControlContext acc, DomainCombiner combiner) public DomainCombiner getDomainCombiner() |
checkPermission | java.security.SecurityPermission "createAccessControlContext" |
java.security.Identity public void addCertificate(...) |
checkSecurityAccess( "addIdentityCertificate") | java.security.SecurityPermission "addIdentityCertificate" |
java.security.Identity public void removeCertificate(...) |
checkSecurityAccess( "removeIdentityCertificate") | java.security.SecurityPermission "removeIdentityCertificate" |
java.security.Identity public void setInfo(String info) |
checkSecurityAccess( "setIdentityInfo") | java.security.SecurityPermission "setIdentityInfo" |
java.security.Identity public void setPublicKey(PublicKey key) |
checkSecurityAccess( "setIdentityPublicKey") | java.security.SecurityPermission "setIdentityPublicKey" |
java.security.Identity public String toString(...) |
checkSecurityAccess( "printIdentity") | java.security.SecurityPermission "printIdentity" |
java.security.IdentityScope protected static void setSystemScope() |
checkSecurityAccess( "setSystemScope") | java.security.SecurityPermission "setSystemScope" |
java.security.Permission public void checkGuard(Object object) |
checkPermission(this) | this Permission object is the permission checked |
java.security.Policy public static Policy getPolicy() |
checkPermission | java.security.SecurityPermission "getPolicy" |
java.security.Policy public static void setPolicy(Policy policy) |
checkPermission | java.security.SecurityPermission "setPolicy" |
java.security.Policy public static Policy getInstance(String type, SpiParameter params) getInstance(String type, SpiParameter params, String provider) getInstance(String type, SpiParameter params, Provider provider) |
checkPermission | java.security.SecurityPermission "createPolicy.{type}" |
java.security.Provider public synchronized void clear() |
checkSecurityAccess( "clearProviderProperties."+{name}) | java.security.SecurityPermission "clearProviderProperties.{name}" where name is the provider name. |
java.security.Provider public synchronized Object put(Object key, Object value) |
checkSecurityAccess( "putProviderProperty."+{name}) | java.security.SecurityPermission "putProviderProperty.{name}" where name is the provider name. |
java.security.Provider public synchronized Object remove(Object key) |
checkSecurityAccess( "removeProviderProperty."+{name}) | java.security.SecurityPermission "removeProviderProperty.{name}" where name is the provider name. |
java.security.SecureClassLoader SecureClassLoader(...) |
checkCreateClassLoader | java.lang.RuntimePermission "createClassLoader" |
java.security.Security public static void getProperty(String key) |
checkPermission | java.security.SecurityPermission "getProperty.{key}" |
java.security.Security public static int addProvider(Provider provider) public static int insertProviderAt(Provider provider, int position); |
checkSecurityAccess( "insertProvider."+provider.getName()) | java.security.SecurityPermission "insertProvider.{name}" |
java.security.Security public static void removeProvider(String name) |
checkSecurityAccess( "removeProvider."+name) | java.security.SecurityPermission "removeProvider.{name}" |
java.security.Security public static void setProperty(String key, String datum) |
checkSecurityAccess( "setProperty."+key) | java.security.SecurityPermission "setProperty.{key}" |
java.security.Signer public PrivateKey getPrivateKey() |
checkSecurityAccess( "getSignerPrivateKey") | java.security.SecurityPermission "getSignerPrivateKey" |
java.security.Signer public final void setKeyPair(KeyPair pair) |
checkSecurityAccess( "setSignerKeypair") | java.security.SecurityPermission "setSignerKeypair" |
java.sql.DriverManager public static synchronized void setLogWriter(PrintWriter out) |
checkPermission | java.sql.SQLPermission "setLog" |
java.sql.DriverManager public static synchronized void setLogStream(PrintWriter out) |
checkPermission | java.sql.SQLPermission "setLog" |
java.util.Locale public static synchronized void setDefault(Locale newLocale) |
checkPermission | java.util.PropertyPermission "user.language","write" |
java.util.zip.ZipFile ZipFile(String name) |
checkRead | java.io.FilePermission "{name}","read" |
javax.security.auth.Subject public static Subject getSubject(final AccessControlContext acc) |
checkPermission | javax.security.auth.AuthPermission "getSubject" |
javax.security.auth.Subject public void setReadOnly() |
checkPermission | javax.security.auth.AuthPermission "setReadOnly" |
javax.security.auth.Subject public static Object doAs(final Subject subject, final PrivilegedAction action) |
checkPermission | javax.security.auth.AuthPermission "doAs" |
javax.security.auth.Subject public static Object doAs(final Subject subject, final PrivilegedExceptionAction action) throws java.security.PrivilegedActionException |
checkPermission | javax.security.auth.AuthPermission "doAs" |
javax.security.auth.Subject public static Object doAsPrivileged(final Subject subject, final PrivilegedAction action, final AccessControlContext acc) |
checkPermission | javax.security.auth.AuthPermission "doAsPrivileged" |
javax.security.auth.Subject public static Object doAsPrivileged(final Subject subject, final PrivilegedExceptionAction action, final AccessControlContext acc) throws java.security.PrivilegedActionException |
checkPermission | javax.security.auth.AuthPermission "doAsPrivileged" |
javax.security.auth.SubjectDomainCombiner public Subject getSubject() |
checkPermission | javax.security.auth.AuthPermission "getSubjectFromDomainCombiner" |
javax.security.auth.SubjectDomainCombiner public Subject getSubject() |
checkPermission | javax.security.auth.AuthPermission "getSubjectFromDomainCombiner" |
javax.security.auth.login.LoginContext public LoginContext(String name) throws LoginException |
checkPermission | javax.security.auth.AuthPermission "createLoginContext.{name}" |
javax.security.auth.login.LoginContext public LoginContext(String name, Subject subject) throws LoginException |
checkPermission | javax.security.auth.AuthPermission "createLoginContext.{name}" |
javax.security.auth.login.LoginContext public LoginContext(String name, CallbackHandler callbackHandler) throws LoginException |
checkPermission | javax.security.auth.AuthPermission "createLoginContext.{name}" |
javax.security.auth.login.LoginContext public LoginContext(String name, Subject subject, CallbackHandler callbackHandler) throws LoginException |
checkPermission | javax.security.auth.AuthPermission "createLoginContext.{name}" |
javax.security.auth.login.Configuration public static Configuration getConfiguration() |
checkPermission | javax.security.auth.AuthPermission "getLoginConfiguration" |
javax.security.auth.login.Configuration public static void setConfiguration(Configuration configuration) |
checkPermission | javax.security.auth.AuthPermission "setLoginConfiguration" |
javax.security.auth.login.Configuration public static void refresh() |
checkPermission | javax.security.auth.AuthPermission "refreshLoginConfiguration" |
javax.security.auth.login.Configuration public static Configuration getInstance(String type, SpiParameter params) getInstance(String type, SpiParameter params, String provider) getInstance(String type, SpiParameter params, Provider provider) |
checkPermission | javax.security.auth.AuthPermission "createLoginConfiguration.{type}" |
List of permissions that are checked for by the default implementations of the java.lang.SecurityManager
methods.
Each of the specified check
methods calls the SecurityManager
checkPermission
method with the specified permission, except for the checkConnect
and checkRead
methods that take a context argument. Those methods expect the context to be an AccessControlContext
and they call the context's checkPermission
method with the specified permission.
Table 1-7 java.lang.SecurityManager Methods and Permissions
Method | Permission |
---|---|
public void checkAccept(String host, int port); | java.net.SocketPermission "{host}:{port}", "accept"; |
public void checkAccess(Thread t); | java.lang.RuntimePermission "modifyThread"; |
public void checkAccess(ThreadGroup g); | java.lang.RuntimePermission "modifyThreadGroup"; |
public void checkAwtEventQueueAccess();
Note: This method is deprecated; use insteadpublic void checkPermission(Permission perm); |
java.awt.AWTPermission "accessEventQueue"; |
public void checkConnect(String host, int port); | if (port == -1) java.net.SocketPermission "{host}","resolve"; else java.net.SocketPermission "{host}:{port}","connect"; |
public void checkConnect(String host, int port, Object context); | if (port == -1) java.net.SocketPermission "{host}","resolve"; else java.net.SocketPermission "{host}:{port}","connect"; |
public void checkCreateClassLoader(); | java.lang.RuntimePermission "createClassLoader"; |
public void checkDelete(String file); | java.io.FilePermission "{file}", "delete"; |
public void checkExec(String cmd); | if cmd is an absolute path: java.io.FilePermission "{cmd}", "execute"; else java.io.FilePermission "<<ALL_FILES>>", "execute"; |
public void checkExit(int status); | java.lang.RuntimePermission "exitVM.{status}"; |
public void checkLink(String lib); | java.lang.RuntimePermission "loadLibrary.{lib}"; |
public void checkListen(int port); | java.net.SocketPermission "localhost:{port}","listen"; |
public void checkMemberAccess(Class clazz, int which);
Note: This method is deprecated; use insteadpublic void checkPermission(Permission perm); |
if (which != Member.PUBLIC) { if (currentClassLoader() != clazz.getClassLoader()) { checkPermission( new java.lang.RuntimePermission("accessDeclaredMembers")); } } |
public void checkMulticast(InetAddress maddr); | java.net.SocketPermission(maddr.getHostAddress(),"accept,connect"); |
public void checkMulticast(InetAddress maddr, byte ttl);
Note: This method is deprecated; use insteadpublic void checkPermission(Permission perm); |
java.net.SocketPermission(maddr.getHostAddress(),"accept,connect"); |
public void checkPackageAccess(String pkg); | java.lang.RuntimePermission "accessClassInPackage.{pkg}"; |
public void checkPackageDefinition(String pkg); | java.lang.RuntimePermission "defineClassInPackage.{pkg}"; |
public void checkPrintJobAccess(); | java.lang.RuntimePermission "queuePrintJob"; |
public void checkPropertiesAccess(); | java.util.PropertyPermission "*", "read,write"; |
public void checkPropertyAccess(String key); | java.util.PropertyPermission "{key}", "read,write"; |
public void checkRead(FileDescriptor fd); | java.lang.RuntimePermission "readFileDescriptor"; |
public void checkRead(String file); | java.io.FilePermission "{file}", "read"; |
public void checkRead(String file, Object context); | java.io.FilePermission "{file}", "read"; |
public void checkSecurityAccess(String target); | java.security.SecurityPermission "{target}"; |
public void checkSetFactory(); | java.lang.RuntimePermission "setFactory"; |
public void checkSystemClipboardAccess();
Note: This method is deprecated; use insteadpublic void checkPermission(Permission perm); |
java.awt.AWTPermission "accessClipboard"; |
public boolean checkTopLevelWindow(Object window);
Note: This method is deprecated; use insteadpublic void checkPermission(Permission perm); |
java.awt.AWTPermission "showWindowWithoutWarningBanner"; |
public void checkWrite(FileDescriptor fd); | java.lang.RuntimePermission "writeFileDescriptor"; |
public void checkWrite(String file); | java.io.FilePermission "{file}", "write"; |
public SecurityManager(); | java.lang.RuntimePermission "createSecurityManager"; |
The policy for a Java programming language application environment (specifying which permissions are available for code from various sources, and executing as various principals) is represented by a Policy object. More specifically, it is represented by a Policy
subclass providing an implementation of the abstract methods in the Policy
class (which is in the java.security
package).
The source location for the policy information utilized by the Policy object is up to the Policy implementation. The Policy reference implementation obtains its information from static policy configuration files.
The rest of this document pertains to the Policy reference implementation and the syntax that must be used in policy files it reads:
Compose a policy file with any text editor.
In the Policy reference implementation, the policy can be specified within one or more policy configuration files. The configuration file(s) specify what permissions are allowed for code from a specified code source, and executed by a specified principal. Each configuration file must be encoded in UTF-8.
There is by default a single system-wide policy file, and a single (optional) user policy file. By default, permissions required by JDK modules that are loaded by the platform class loader or its ancestors are always granted.
The Policy reference implementation is initialized the first time its getPermissions method is called, or whenever its refresh method is called. Initialization involves parsing the policy configuration file(s) (see Policy File Syntax), and then populating the Policy object.
There is by default a single system-wide policy file, and a single (optional) user policy file. When the Policy is initialized, the system policy is loaded in first, and then the user policy is added to it. If neither policy is present, a built-in policy is used. This built-in policy is the same as the java.policy
file installed with the JRE.
System Policy File Locations
By default, the system policy file is <java-home>/conf/security/java.policy
.
The system policy file is meant to grant system-wide code permissions. The java.policy
file installed with the JDK allows anyone to listen on dynamic ports, and allows any code to read certain "standard" properties that are not security-sensitive, such as the os.name
and file.separator
properties.
User Policy File Location
By default, the user policy file is <user-home>/.java.policy
.
Configure Policy File Location and Format
Policy file locations are specified in the security properties file <java-home>/conf/security/java.security
.
The policy file locations are specified as the values of properties whose names are of the form
policy.url.n
Here, n
is a number. You specify each such property value in a line of the following form:
policy.url.n=URL
Here, URL
is a URL specification. For example, the default system and user policy files are defined in the security properties file as:
policy.url.1=file:${java.home}/conf/security/java.policy policy.url.2=file:${user.home}/.java.policy
(See Property Expansion for information about specifying property values via a special syntax, such as specifying the java.home
property value via ${java.home}
.)
You can actually specify a number of URLs (including ones of the form "http://
"), and all the designated policy files will get loaded. You can also comment out or change the second one to disable reading the default user policy file.
The algorithm starts at policy.url.1
, and keeps incrementing until it does not find a URL. Thus if you have policy.url.1
and policy.url.3
, and policy.url.3
will never be read.
Example 1-4 Specifying an Additional Policy File at Runtime
It is also possible to specify an additional or a different policy file when invoking execution of an application. This can be done via the
command line argument, which sets the value of the -Djava.security.policy
java.security.policy
property. For example, if you use following command, where someURL
is a URL specifying the location of a policy file, then the specified policy file will be loaded in addition to all the policy files that are specified in the security properties file.
java -Djava.security.manager -Djava.security.policy=someURL SomeApp
The URL can be any regular URL or simply the name of a policy file in the current directory, as in:
java -Djava.security.manager -Djava.security.policy=mypolicy SomeApp
The -Djava.security.manager
option ensures that the default security manager is installed, and thus the application is subject to policy checks. It is not required if the application SomeApp installs a security manager.
If you use the following command (note the double equals) then just the specified policy file will be used; all the ones indicated in the security properties file will be ignored.
java -Djava.security.manager -Djava.security.policy==someURL SomeApp
Note:
The policy file value of the-Djava.security.policy
option is ignored if the policy.allowSystemProperty
property in the security properties file is set to false. The default is true.The Policy reference implementation can be modified by editing the security properties file, which is the java.security
file in the conf/security
directory of the JDK.
An alternative policy class can be given to replace the Policy reference implementation class, as long as the former is a subclass of the abstract Policy class and implements the getPermissions method (and other methods as necessary).
One of the types of properties you can set in java.security
is of the following form:
policy.provider=PolicyClassName
PolicyClassName must specify the fully qualified name of the desired Policy
implementation class.
The default security properties file entry for this property is the following:
policy.provider=sun.security.provider.PolicyFile
To customize, you can change the property value to specify another class, as in
policy.provider=com.mycom.MyPolicy
The policy configuration file(s) for a JDK installation specifies what permissions (which types of system resource accesses) are granted to code from a specified code source, and executed as a specified principal.
For an applet (or an application running under a security manager) to be allowed to perform secured actions (such as reading or writing a file), the applet (or application) must be granted permission for that particular action. In the Policy reference implementation, that permission must be granted by a grant entry in a policy configuration file. See below and the Java Security Architecture Specification for more information. (The only exception is that code always automatically has permission to read files from its same (URL) location, and subdirectories of that location; it does not need explicit permission to do so.)
A policy configuration file essentially contains a list of entries. It may contain a "keystore" entry, and contains zero or more "grant" entries.
The keytool utility is used to create and administer keystores.
A keystore is a database of private keys and their associated digital certificates such as X.509 certificate chains authenticating the corresponding public keys. The keytool utility is used to create and administer keystores. The keystore specified in a policy configuration file is used to look up the public keys of the signers specified in the grant entries of the file. A keystore entry must appear in a policy configuration file if any grant entries specify signer aliases, or if any grant entries specify principal aliases.
At this time, there can be only one keystore
/keystorePasswordURL
entry in the policy file (other entries following the first one are ignored). This entry can appear anywhere outside the file's grant entries. It has the following syntax:
keystore "some_keystore_url", "keystore_type", "keystore_provider"; keystorePasswordURL "some_password_url";
Here,
Note:
The input stream from some_keystore_url
is passed to the KeyStore.load method.
If NONE is specified as the URL, then a null stream is passed to the KeyStore.load method. NONE should be specified in the URL if the KeyStore is not file-based. For example, if it resides on a hardware token device.
The URL is relative to the policy file location. If the policy file is specified in the security properties file as:
policy.url.1=http://foo.example.com/fum/some.policy
and that policy file has an entry:
keystore ".keystore";
then the keystore will be loaded from:
http://foo.example.com/fum/.keystore
The URL can also be absolute.
A keystore type defines the storage and data format of the keystore information, and the algorithms used to protect private keys in the keystore and the integrity of the keystore itself. The default type is a proprietary keystore type named "PKCS12". Thus, if the keystore type is "PKCS12", it does not need to be specified in the keystore entry.
Grant entry is used to specify which code you want to grant permissions.
Code being executed is always considered to come from a particular "code source" (represented by an object of type CodeSource
). The code source includes not only the location (URL) where the code originated from, but also a reference to the certificate(s) containing the public key(s) corresponding to the private key(s) used to sign the code. Certificates in a code source are referenced by symbolic alias names from the user's keystore. Code is also considered to be executed as a particular principal (represented by an object of type Principal
), or group of principals.
Each grant entry includes one or more "permission entries" preceded by optional codeBase
, signedBy
, and principal name/value pairs that specify which code you want to grant the permissions. The basic format of a grant entry is the following:
grant signedBy "signer_names", codeBase "URL", principal principal_class_name "principal_name", principal principal_class_name "principal_name", ... { permission permission_class_name "target_name", "action", signedBy "signer_names"; permission permission_class_name "target_name", "action", signedBy "signer_names"; ... };
All non-italicized items above must appear as is (although case doesn't matter and some are optional, as noted below). Italicized items represent variable values.
A grant entry must begin with the word grant
.
The signedBy
, codeBase
, and principal
values are optional, and the order of these fields does not matter.
A signedBy
value indicates the alias for a certificate stored in the keystore. The public key within that certificate is used to verify the digital signature on the code; you grant the permission(s) to code signed by the private key corresponding to the public key in the keystore entry specified by the alias.
The signedBy
value can be a comma-separated list of multiple aliases. An example is "Adam,Eve,Charles", which means "signed by Adam and Eve and Charles"; the relationship is AND, not OR. To be more exact, a statement like "Code signed by Adam" means "Code in a class file contained in a JAR which is signed using the private key corresponding to the public key certificate in the keystore whose entry is aliased by Adam".
The signedBy
field is optional in that, if it is omitted, it signifies "any signer". It doesn't matter whether the code is signed or not or by whom.
A principal value specifies a class_name
/principal_name
pair which must be present within the executing thread's principal set. The principal set is associated with the executing code by way of a Subject.
The principal_class_name
may be set to the wildcard value, *, which allows it to match any Principal
class. In addition, the principal_name
may also be set to the wildcard value, *, allowing it to match any Principal
name. When setting the principal_class_name
or principal_name
to *, do not surround the * with quotes. Also, if you specify a wildcard principal class, you must also specify a wildcard principal name.
The principal field is optional in that, if it is omitted, it signifies "any principals".
The principal class_name/principal_name pair
is specified as a single quoted string, it is treated as a keystore alias.
The keystore is consulted and queried (via the alias) for an X509 Certificate. If one is found, the principal class_name is automatically treated as javax.security.auth.x500.X500Principal
, and the principal_name
is automatically treated as the subject distinguished name from the certificate. If an X509 Certificate mapping is not found, the entire grant entry is ignored.
A codeBase
value indicates the code source location; you grant the permission(s) to code from that location. An empty codeBase
entry signifies "any code"; it doesn't matter where the code originates from.
Note:
AcodeBase
value is a URL and thus should always utilize slashes (never backslashes) as the directory separator, even when the code source is actually on a Windows system. Thus, if the source location for code on a Windows system is actually C:\somepath\api\
, then the policy codeBase
entry should look like:
grant codeBase "file:/C:/somepath/api/" { ... };
The exact meaning of a codeBase
value depends on the characters at the end. A codeBase
with a trailing "/"
matches all class files (not JAR files) in the specified directory. A codeBase
with a trailing "/*"
matches all files (both class and JAR files) contained in that directory. A codeBase
with a trailing "/-"
matches all files (both class and JAR files) in the directory and recursively all files in subdirectories contained in that directory. The following table illustrates the different cases:
Table 1-8 KeyStore Alias
Codebase URL of Downloaded Code | Codebase URL in Policy | Match? |
---|---|---|
www.example.com/people/gong/ | www.example.com/people/gong | Yes |
www.example.com/people/gong/ | www.example.com/people/gong/ | Yes |
www.example.com/people/gong/ | www.example.com/people/gong/* | Yes |
www.example.com/people/gong/ | www.example.com/people/gong/- | Yes |
www.example.com/people/gong/appl.jar | www.example.com/people/gong/ | No |
www.example.com/people/gong/appl.jar | www.example.com/people/gong/- | Yes |
www.example.com/people/gong/appl.jar | www.example.com/people/gong/* | Yes |
www.example.com/people/gong/appl.jar | www.example.com/people/- | Yes |
www.example.com/people/gong/appl.jar | www.example.com/people/* | No |
www.example.com/people/gong/ | www.example.com/people/- | Yes |
www.example.com/people/gong/ | www.example.com/people/* | No |
A permission entry is specified in the order (permission
, permission_class_name, "target_name", "action", and signedBy
"signer_names
A permission entry must begin with the word permission
. The word permission_class_name
in the template above would actually be a specific permission type, such as java.io.FilePermission
or java.lang.RuntimePermission
.
The "action" is required for many permission types, such as java.io.FilePermission
(where it specifies what type of file access is permitted). It is not required for categories such as java.lang.RuntimePermission
where it is not necessary, you either have the permission specified by the "target_name
" value following the permission_class_name or you don't.
The signedBy
name/value pair for a permission entry is optional. If present, it indicates a signed permission. That is, the permission class itself must be signed by the given alias(es) in order for the permission to be granted. For example, suppose you have the following grant entry:
grant { permission Foo "foobar", signedBy "FooSoft"; };
Then this permission of type Foo is granted if the Foo.class
permission was placed in a JAR file and the JAR file was signed by the private key corresponding to the public key in the certificate specified by the "FooSoft" alias, or if Foo.class
is a system class, since system classes are not subject to policy restrictions.
Items that appear in a permission entry must appear in the specified order (permission
, permission_class_name, "target_name", "action", and signedBy
"signer_names"). An entry is terminated with a semicolon.
Case is unimportant for the identifiers (permission
, signedBy
, codeBase
, etc.) but is significant for the permission_class_name or for any string that is passed in as a value.
The file path specifications on Windows systems should include two backslashes for each actual single backslash.
Note:
When you are specifying a java.io.FilePermission
, the "target_name" is a file path. On Windows systems, whenever you directly specify a file path in a string (but not in a codeBase URL), you need to include two backslashes for each actual single backslash in the path, as in
grant { permission java.io.FilePermission "C:\\users\\cathy\\foo.bat", "read"; };
The reason this is necessary is because the strings are processed by a tokenizer (java.io.StreamTokenizer
), which allows “\” to be used as an escape string (for example, "\n” to indicate a new line) and which thus requires two backslashes to indicate a single backslash. After the tokenizer has processed the above file path string, converting double backslashes to single backslashes, the end result is
"C:\users\cathy\foo.bat"
Examples of policy configuration files, with different configuration of the codeBase
and signedBy
values. Examples of grant statements with different principal based entry and KeyStore values.
Example 1-5 Sample Policy Configuration File
An example of two entries in a policy configuration file is as follows:
// If the code is signed by "Duke", grant it read/write access to all // files in /tmp: grant signedBy "Duke" { permission java.io.FilePermission "/tmp/*", "read,write"; }; // Grant everyone the following permission: grant { permission java.util.PropertyPermission "java.vendor", "read"; };
Example 1-6 Sample Policy Configuration File
/home/sysadmin/
" directory on the local file system.sysadmin
" in the keystore.grant signedBy "sysadmin", codeBase "file:/home/sysadmin/*" { permission java.security.SecurityPermission "Security.insertProvider.*"; permission java.security.SecurityPermission "Security.removeProvider.*"; permission java.security.SecurityPermission "Security.setProperty.*"; };
Example 1-7 Sample Where codeBase is Missing
Either component of the code source (or both) may be missing. An example where codeBase
is missing :
grant signedBy "sysadmin" { permission java.security.SecurityPermission "Security.insertProvider.*"; permission java.security.SecurityPermission "Security.removeProvider.*"; };
If this policy is in effect, code that comes in a JAR File signed by "sysadmin
" can add/remove providers, regardless of where the JAR File originated from.
Example 1-8 Sample Without signedBy
grant codeBase "file:/home/sysadmin/-" { permission java.security.SecurityPermission "Security.insertProvider.*"; permission java.security.SecurityPermission "Security.removeProvider.*"; };
In this case, code that comes from anywhere beneath the "/home/sysadmin/
" directory on the local filesystem can add/remove providers. The code does not need to be signed.
Example 1-9 Sample Without codeBase or signedBy
grant { permission java.security.SecurityPermission "Security.insertProvider.*"; permission java.security.SecurityPermission "Security.removeProvider.*"; };
Here, with both code source components missing, any code (regardless of where it originated from, or whether or not it is signed, or who signed it) can add/remove providers.
Example 1-10 Sample Executing As X500Principal
grant principal javax.security.auth.x500.X500Principal "cn=Alice" { permission java.io.FilePermission "/home/Alice", "read, write"; };
This permits any code executing as the X500Principal, "cn=Alice
", permission to read and write to "/home/Alice
”.
Example 1-11 Sample Executing As X500Principal Without a Distinguished Name
grant principal javax.security.auth.x500.X500Principal * { permission java.io.FilePermission "/tmp", "read, write"; };
This permits any code executing as an X500Principal (regardless of the distinguished name), permission to read and write to "/tmp
”.
Example 1-12 Grant Statement With CodeBase and X500Principal Information
grant codebase "http://www.games.example.com", signedBy "Duke", principal javax.security.auth.x500.X500Principal "cn=Alice" { permission java.io.FilePermission "/tmp/games", "read, write"; };
This allows code downloaded from "www.games.example.com
", signed by "Duke
", and executed by "cn=Alice
", permission to read and write into the "/tmp/games
" directory.
Example 1-13 Grant Statement With KeyStore Alias
keystore "http://foo.example.com/blah/.keystore"; grant principal "alice" { permission java.io.FilePermission "/tmp/games", "read, write"; };
alice
" will be replaced by
javax.security.auth.x500.X500Principal "cn=Alice"assuming the X.509 certificate associated with the keystore alias,
alice
, has a subject distinguished name of "cn=Alice
". This allows code executed by the X500Principal "cn=Alice
" permission to read and write into the "/tmp/games
" directory.Property expansion is possible in policy files and in the security properties file.
Property expansion is similar to expanding variables in a shell. That is, when a string like
${some.property}
appears in a policy file, or in the security properties file, it will be expanded to the value of the system property. For example,
permission java.io.FilePermission "${user.home}", "read";
will expand "${user.home}
" to use the value of the "user.home" system property. If that property's value is "/home/cathy
", then the above is equivalent to
permission java.io.FilePermission "/home/cathy", "read";In order to assist in platform-independent policy files, you can also use the special notation of "
${/}
", which is a shortcut for ${file.separator}
". This allows things like
permission java.io.FilePermission "${user.home}${/}*", "read";If the value of the "
user.home
" property is /home/cathy
, and you are on Solaris, Linux, or macOS, the above gets converted to:
permission java.io.FilePermission "/home/cathy/*", "read";If on the other hand the "
user.home
" value is C:\users\cathy
and you are on a Windows system, the above gets converted to:
permission java.io.FilePermission "C:\users\cathy\*", "read";Also, as a special case, if you expand a property in a codebase, such as
grant codeBase "file:${java.home}/lib/ext/"then any file.separator characters will be automatically converted to
/
's. Thus on a Windows system, the above would get converted to
grant codeBase "file:C:/jdk1.4/lib/ext/"even if "
java.home
" is set to C:\jdk1.4\
Thus you don't need to use ${/}
in codebase strings (and you shouldn't). Property expansion takes place anywhere a double quoted string is allowed in the policy file. This includes the "signer_names", "URL", "target_name", and "action" fields. Whether or not property expansion is allowed is controlled by the value of the "policy.expandProperties
" property in the security properties file. If the value of this property is true (the default), expansion is allowed.
Note:
You can't use nested properties; they will not work. For example,"${user.${foo}}"doesn't work, even if the "
foo
" property is set to "home
". The reason is the property parser doesn't recognize nested properties; it simply looks for the first "${
", and then keeps looking until it finds the first "}
" and tries to interpret the result (in this case, "${user.$foo}
") as a property, but fails if there is no such property.Note:
If a property can't be expanded in a grant entry, permission entry, or keystore entry, that entry is ignored. For example, if the system property "foo
" is not defined and you have:
grant codeBase "${foo}" { permission ...; permission ...; };
then all the permissions in this grant entry are ignored. If you have
grant { permission Foo "${foo}"; permission Bar "barTarget"; };then only the "
permission Foo...
" entry is ignored. And finally, if you have
keystore "${foo}";
then the keystore entry is ignored.
The file path specifications on Windows systems should include two backslashes for each actual single backslash.
In Windows systems, when you directly specify a file path in a string (but not in a codeBase URL), you need to include two backslashes for each actual single backslash in the path, as in
grant { permission java.io.FilePermission "C:\\users\\cathy\\foo.bat", "read"; };
This is because the strings are processed by a tokenizer (java.io.StreamTokenizer
), which allows "\
" to be used as an escape string (e.g., "\n
" to indicate a new line) and which thus requires two backslashes to indicate a single backslash. After the tokenizer has processed the above file path string, converting double backslashes to single backslashes, the end result is
"C:\users\cathy\foo.bat"
Expansion of a property in a string takes place after the tokenizer has processed the string. Thus if you have the string
"${user.home}\\foo.bat"
then first the tokenizer processes the string, converting the double backslashes to a single backslash, and the result is
"${user.home}\foo.bat"Then the
${user.home}
property is expanded and the end result is
"C:\users\cathy\foo.bat"assuming the "
user.home
" value is C:\users\cathy
. Of course, for platform independence, it would be better if the string was initially specified without any explicit slashes, i.e., using the ${/}
property instead, as in
"${user.home}${/}foo.bat"
A canonical path is a path that doesn’t contain any links or shortcuts. Performing pathname canonicalization in FilePermission
object can negatively affect performance.
Before JDK 9, path names were canonicalized when two FilePermission
objects were compared. This allowed a program to access a file using a different name than the name that was granted to a FilePermission
object in a policy file, as long as the object pointed to the same file. Because the canonicalization had to access the underlying file system, it could be quite slow.
In JDK 9, path-name canonicalization is disabled by default. This means two FilePermission
objects aren’t equal to each other if one uses an absolute path and the other uses a relative path, or one uses a symbolic link and the other uses a target, or one uses a Windows long name and the other uses a DOS-style 8.3 name. This is true even if they all point to the same file in the file system.
Therefore, if a pathname is granted to a FilePermission
object in a policy file, then the program should also access that file using the same path-name style. For example, if the path name in the policy file is using a symbolic link, then the program should also use that symbolic link. Accessing the file with the target path name will fail the permission check.
Compatibility Layer
A compatibility layer has been added to ensure that granting a FilePermission
object for a relative path will permit applications to access the file with an absolute path (and conversly). This works for the default Policy provider and the Limited doPrivileged
calls.
For example, a FilePermission
object on a file with a relative path name of "a"
no longer implies a FilePermission
object on the same file with an absolute path name as "/pwd/a"
("pwd"
is the current working directory). Granting code a FilePermission
object to read "a"
allows that code to also read "/pwd/a"
when a Security Manager is enabled.
The compatibility layer doesn’t cover translations between symbolic links and targets, or Windows long names and DOS-style 8.3 names, or any other different name forms that can be canonicalized to the same name.
Customizing Path-Name Canonicalization
The system properties in Table 1-9 can be used to customize theFilePermission
path-name canonicalization. See How to Specify a java.lang.System Property.
Table 1-9 System Properties to Customize Pathname Canonicalization
System Property | Default Value | Description |
---|---|---|
jdk.io.permissionsUseCanonicalPath |
false |
The system property can be used to enable or disable pathname canonicalization in the
|
jdk.security.filePermCompat |
false |
The system property can be used to extend the compatibility layer to support third-party Policy implementations.
|
The policy files can be expanded using two protocols self
and alias
forms of expansion in the policy files.
${{protocol:protocol_data}}
${{protocol}}
There are two protocols supported in the default policy file implementation:
${{self}}
The protocol, self
, denotes a replacement of the entire string, ${{self}}
, with one or more principal class/name pairs. The exact replacement performed depends upon the contents of the grant clause to which the permission belongs.
If the grant clause does not contain any principal information, the permission will be ignored (permissions containing ${{self}}
in their target names are only valid in the context of a principal-based grant clause). For example, BarPermission
will always be ignored in the following grant clause:
grant codebase "www.example.com", signedby "duke" { permission BarPermission "... ${{self}} ..."; };If the grant clause contains principal information,
${{self}}
will be replaced with that same principal information. For example, ${{self}}
in BarPermission
will be replaced with javax.security.auth.x500.X500Principal "cn=Duke"
in the following grant clause:
grant principal javax.security.auth.x500.X500Principal "cn=Duke" { permission BarPermission "... ${{self}} ..."; };If there is a comma-separated list of principals in the grant clause, then
${{self}}
will be replaced by the same comma-separated list or principals. In the case where both the principal class and name are wildcarded in the grant clause, ${{self}}
is replaced with all the principals associated with the Subject
in the current AccessControlContext
.
The following example describes a scenario involving both self
and KeyStore Alias Replacement together:
keystore "http://foo.example.com/blah/.keystore"; grant principal "duke" { permission BarPermission "... ${{self}} ..."; };In the above example, "
duke
" will first be expanded into javax.security.auth.x500.X500Principal "cn=Duke"
assuming the X.509 certificate associated with the KeyStore
alias, "duke
", has a subject distinguished name of "cn=Duke
". Next, ${{self}}
will be replaced with the same principal information that was just expanded in the grant clause: javax.security.auth.x500.X500Principal "cn=Duke"
.${{alias:alias_name}}
The protocol, alias
, denotes a java.security.KeyStore alias substitution. The KeyStore
used is the one specified in the Keystore Entry. alias_name represents an alias into the KeyStore
. ${{alias:alias_name}}
is replaced with javax.security.auth.x500.X500Principal "DN"
, where DN represents the subject distinguished name of the certificate belonging to alias_name. For example:
keystore "http://foo.example.com/blah/.keystore"; grant codebase "www.example.com" { permission BarPermission "... ${{alias:duke}} ..."; };In the above example the X.509 certificate associated with the alias, duke, is retrieved from the
KeyStore
, foo.example.com/blah/.keystore. Assuming duke's certificate specifies "o=dukeOrg, cn=duke
" as the subject distinguished name, then ${{alias:duke}}
is replaced with javax.security.auth.x500.X500Principal "o=dukeOrg, cn=duke"
.
The permission entry is ignored under the following error conditions:
Background information about what privileged code is and what it is used for, followed by illustrations of the use of the API. It covers the following topics:
Description of the doPrivileged API and the use of the privileged feature.
No Return Value, No Exception Thrown
If you do not need to return a value from within the privileged block, your call to doPrivileged
can look like Example 1-14.
Note that the invocation of doPrivileged
with a lambda expression explicitly casts the lambda expression as of type PrivilegedAction<Void>
. Another version of the method doPrivileged
exists that takes an object of type PrivilegedExceptionAction
; see Handling Exceptions.
PrivilegedAction
is a functional interface with a single abstract method, named run
, that returns a value of type specified by its type parameter.
Note that this example ignores the return value of the run
method. Also, depending on what privileged code actually consists of, you might have to make some changes due to the way inner classes work. For example, if privileged code throws an exception or attempts to access local variables, then you will have to make some changes, which is described later.
Be very careful in your use of the privileged construct, and always remember to make the privileged code section as small as possible. That is, try to limit the code within the run
method to only what needs to be run with privileges, and do more general things outside the run
method. Also note that the call to doPrivileged
should be made in the code that wants to enable its privileges. Do not be tempted to write a utility class that itself calls doPrivileged
as that could lead to security holes. You can write utility classes for PrivilegedAction
classes though, as shown in the preceding example. See Guideline 9-3: Safely invoke java.security.AccessController.doPrivileged
in Secure Coding Guidelines for the Java Programming Language.
Example 1-14 Sample Code for Privileged Block
The following code specifies privileged code three ways:In a class that implements the interface PrivilegedAction
.
In an anonymous class.
In a lambda expression.
import java.security.*; public class NoReturnNoException { class MyAction implements PrivilegedAction<Void> { public Void run() { // Privileged code goes here, for example: System.loadLibrary("awt"); return null; // nothing to return } } public void somemethod() { MyAction mya = new MyAction(); // Become privileged: AccessController.doPrivileged(mya); // Anonymous class AccessController.doPrivileged(new PrivilegedAction<Void>() { public Void run() { // Privileged code goes here, for example: System.loadLibrary("awt"); return null; // nothing to return } }); // Lambda expression AccessController.doPrivileged((PrivilegedAction<Void>) () -> { // Privileged code goes here, for example: System.loadLibrary("awt"); return null; // nothing to return } ); } public static void main(String... args) { NoReturnNoException myApplication = new NoReturnNoException(); myApplication.somemethod(); } }
Sample code to return a value.
If you need to return a value, then you can do something like the following:
System.out.println( AccessController.doPrivileged((PrivilegedAction<String>) () -> System.getProperty("user.name") ) );
If you are using a lambda expression or anonymous inner class, then any local variables you access must be final
or effectively final.
For example:
String lib = "awt"; AccessController.doPrivileged((PrivilegedAction<Void>) () -> { System.loadLibrary(lib); return null; // nothing to return } ); AccessController.doPrivileged(new PrivilegedAction<Void>() { public Object run() { System.loadLibrary(lib); return null; // nothing to return } });
The variable lib
is effectively final because its value has not been modified. For example, suppose you add the following assignment statement after the declaration of the variable lib
:
lib = "swing";
The compiler generates the following errors when it encounters the invocation System.loadLibrary
both in the lambda expression and the anonymous class:
error: local variables referenced from a lambda expression must be final or effectively final
error: local variables referenced from an inner class must be final or effectively final
See Accessing Members of an Enclosing Class in Local Classes for more information.
If there are cases where you cannot make an existing variable effectively final (because it gets set multiple times), then you can create a new final
variable right before invoking the doPrivileged
method, and set that variable equal to the other variable. For example:
String lib; // The lib variable gets set multiple times so you can't make it // effectively final. // Create a final String that you can use inside of the run method final String fLib = lib; AccessController.doPrivileged((PrivilegedAction<Void>) () -> { System.loadLibrary(fLib); return null; // nothing to return } );
If the action performed in your run
method could throw a checked exception (one that must be listed in the throws
clause of a method), then you need to use the PrivilegedExceptionAction
interface instead of the PrivilegedAction
interface.
Example 1-15 Sample for Handling Exceptions
If a checked exception is thrown during execution of the run
method, then it is placed in a PrivilegedActionException
wrapper exception that is then thrown and should be caught by your code, as illustrated in the following example:
public void processSomefile() throws IOException { try { Path path = FileSystems.getDefault().getPath("somefile"); BufferedReader br = AccessController.doPrivileged( (PrivilegedExceptionAction<BufferedReader>) () -> Files.newBufferedReader(path) ); // ... read from file and do something } catch (PrivilegedActionException e) { // e.getException() should be an instance of IOException // as only checked exceptions will be wrapped in a // PrivilegedActionException. throw (IOException) e.getException(); } }
Variant of the doPrivileged
has three parameters, one of which you use to specify the subset of privileges.
As of JDK 8, a variant of doPrivileged
is available that enables code to assert a subset of its privileges, without preventing the full traversal of the stack to check for other permissions. This variant of the doPrivileged
variant has three parameters, one of which you use to specify this subset of privileges. For example, the following excerpt asserts a privilege to retrieve system properties:
// Returns the value of the specified property. All code // is allowed to read the app.version and app.vendor // properties. public String getProperty(final String prop) { return AccessController.doPrivileged( (PrivilegedAction<String>) () -> System.getProperty(prop), null, new java.util.PropertyPermission("app.version", "read"), new java.util.PropertyPermission("app.vendor", "read") ); }
The first parameter of this version of doPrivileged
is of type java.security.PrivilegedAction
. In this example, the first parameter is a lambda expression that implements the functional interface PrivilegedAction
whose run
method returns the value of the system property specified by the parameter prop
.
The second parameter of this version of doPrivileged
is of type AccessControlContext
. Sometimes you need to perform an additional security check within a different context, such as a worker thread. You can obtain an AccessControlContext
instance from a particular calling context with the method AccessControlContext.getContext
. If you specify null
for this parameter (as in this example), then the invocation of doPrivileged
does not perform any additional security checks.
The third parameter of this version of doPrivileged
is of type
, which is a varargs parameter. This means that you can specify one or more Permission
...Permission
parameters or an array of Permission
objects, as in Permission[]
. In this example, the invocation of doPrivileged
can retrieve the properties app.version
and app.vendor
.
You can use this three parameter variant of doPrivileged
in a mode of least privilege or a mode of more privilege.
The typical use case of the doPrivileged
method is to enable the method that invokes it to perform one or more actions that require permission checks without requiring the callers of the current method to have all the necessary permissions.
For example, the current method might need to open a file or make a network request for its own internal implementation purposes.
Before JDK 8, calls to doPrivileged
methods had only two parameters. They worked by granting temporary privileges to the calling method and stopping the normal full traversal of the stack for access checking when it reached that class, rather than continuing up the call stack where it might reach a method whose defining class does not have the required permission. Typically, the class that is calling doPrivileged
might have additional permissions that are not required in that code path and which might also be missing from some caller classes.
Normally, these extra permissions are not exercised at runtime. Not elevating them through use of doPrivileged
helps to block exploitation of any incorrect code that could perform unintended actions. This is especially true when the PrivilegedAction
is more complex than usual, or when it calls code outside the class or package boundary that might evolve independently over time.
The three-parameter variant of doPrivileged
is generally safer to use because it avoids unnecessarily elevating permissions that are not intended to be required. However, it executes less efficiently so simple or performance-critical code paths might choose not to use it.
When coding the current method, you want to temporarily extend the permission of the calling method to perform an action.
For example, a framework I/O API might have a general purpose method for opening files of a particular data format. This API would take a normal file path parameter and use it to open an underlying FileInputStream
using the calling code's permissions. However, this might also allow any caller to open the data files in a special directory that contains some standard demonstration samples.
The callers of this API could be directly granted a FilePermission
for read access. However, it might not be convenient or possible for the security policy of the calling code to be updated. For example, the calling code could be a sandboxed applet.
One way to implement this is for the code to check the incoming path and determine if it refers to a file in the special directory. If it does, then it would call doPrivileged
, enabling all permissions, then open the file inside the PrivilegedAction
. If the file was not in the special directory, the code would open the file without using doPrivileged
.
This technique requires the implementation to carefully handle the requested file path to determine if it refers to the special shared directory. The file path must be canonicalized before calling doPrivileged
so that any relative path will be processed (and permission to read the user.dir
system property will be checked) prior to determining if the path refers to a file in the special directory. It must also prevent malicious "../" path elements meant to escape out of the special directory.
A simpler and better implementation would use the variant of doPrivileged
with the third parameter. It would pass a FilePermission
with read access to the special directory as the third parameter. Then any manipulation of the file would be inside the PrivilegedAction
. This implementation is simpler and much less prone to contain a security flaw.
Marking code as privileged enables a piece of trusted code to temporarily enable access to more resources than are available directly to the code that called it.
The policy for a JDK installation specifies what permissions which types of system resource accesses — are allowed for code from specified code sources. A code source (of type CodeSource
) essentially consists of the code location (URL) and a reference to the certificates containing the public keys corresponding to the private keys used to sign the code (if it was signed).
The policy is represented by a Policy
object. More specifically, it is represented by a Policy
subclass providing an implementation of the abstract methods in the Policy
class (which is in the java.security
package).
The source location for the policy information used by the Policy
object depends on the Policy
implementation. The Policy
reference implementation obtains its information from policy configuration files. See Default Policy Implementation and Policy File Syntax for information about the Policy
reference implementation and the syntax that must be used in policy files it reads. For information about using the Policy Tool to create a policy file (without needing to know the required syntax), see Policy Tool .
A protection domain encompasses a CodeSource
instance and the permissions granted to code from that CodeSource
, as determined by the security policy currently in effect. Thus, classes signed by the same keys and from the same URL are typically placed in the same domain, and a class belongs to one and only one protection domain. (However, classes signed by the same keys and from the same URL but loaded by separate class loader instances are typically placed in separate domains.) Classes that have the same permissions but are from different code sources belong to different domains.
Currently, all classes shipped with the JDK are loaded with all permissions (this may change in future releases). Most of these classes are placed in a unique system domain. In addition, the extension class loader loads code from JAR files contained in the <java_home>/jre/lib/ext
directory into separate domains (because the code in these JAR files have unique URLs), but these domains are separate from the unique system domain reserved for classes shipped with the JDK.
Each applet or application runs in its appropriate domain, determined by its code source. For an applet (or an application running under a security manager) to be allowed to perform a secured action (such as reading or writing a file), the applet or application must be granted permission for that particular action.
More specifically, whenever a resource access is attempted, all code traversed by the execution thread up to that point must have permission for that resource access, unless some code on the thread has been marked as privileged. That is, suppose that access control checking occurs in a thread of execution that has a chain of multiple callers. (Think of this as multiple method calls that potentially cross the protection domain boundaries.) When the AccessController
.checkPermission
method is invoked by the most recent caller, the basic algorithm for deciding whether to allow or deny the requested access is as follows: If the code for any caller in the call chain does not have the requested permission, then an AccessControlException
is thrown, unless the following is true: a caller whose code is granted the said permission has been marked as privileged, and all parties subsequently called by this caller (directly or indirectly) have the said permission.
Note:
The methodAccessController.checkPermission
is normally invoked indirectly through invocations of specific SecurityManager
methods that begin with the word check
such as checkConnect
or through the method SecurityManager.checkPermission
. Normally, these checks only occur if a SecurityManager
has been installed; code checked by the AccessController.checkPermission
method first checks if the method System.getSecurityManager
returns null.Marking code as privileged enables a piece of trusted code to temporarily enable access to more resources than are available directly to the code that called it. This is necessary in some situations. For example, an application might not be allowed direct access to files that contain fonts, but the system utility to display a document must obtain those fonts, on behalf of the user. The system utility must become privileged in order to obtain the fonts.
doPrivileged
method can be invoked reflectively using java.lang.reflect.Method.invoke
.
doPrivileged
method can be invoked reflectively using java.lang.reflect.Method.invoke
. In this case, the privileges granted in privileged mode are not those of Method.invoke
but of the non-reflective code that invoked it. Otherwise, system privileges could erroneously (or maliciously) be conferred on user code. Note that similar requirements exist when using reflection in the existing API.