JDKでのアクセス権

アクセス権は、システム・リソースへのアクセスを表します。アプレット(またはセキュリティ・マネージャとともに実行するアプリケーション)が、リソースへのアクセスを許可されるためには、アクセスを試みるコードに対し、該当するアクセス権を明示的に与える必要があります。

一般に、アクセス権には名前(「ターゲット名」とも呼ばれる)があり、場合によっては、カンマで区切られた1つ以上のアクションのリストを持つこともあります。たとえば、次のコードでは、/tmpディレクトリのabcという名前のファイルへの読取りアクセスを表すFilePermissionオブジェクトを作成します。

perm = new java.io.FilePermission("/tmp/abc", "read");

ここでは、ターゲット名が/tmp/abcで、アクション文字列がreadになります。

重要:

前述の文によって、アクセス権オブジェクトが作成されます。アクセス権オブジェクトは、システム・リソースを表しますが、システム・リソースへのアクセスを許可することはありません。アクセス権オブジェクトは、実効性のあるポリシーに基づいて作成され、コードへ割り当てられ(「付与」され)ます。アクセス権オブジェクトが、あるコードに割り当てられると、そのコードはアクセス権オブジェクトで指定されたシステム・リソースへ、指定された方法でアクセスするアクセス権が付与されます。現在のセキュリティ・マネージャが、アクセス判断を行う際に、アクセス権オブジェクトを作成することもあります。この場合、ターゲットのアクセス権オブジェクトは、要求されたアクセスに基づいて作成されます。さらに、ターゲットのアクセス権オブジェクトは、要求を行うコードに付与され、かつ要求を行うコードが保持する、アクセス権オブジェクトに照らしてチェックされます。

Javaアプリケーション環境のポリシーは、Policyオブジェクトにより表現されます。"JavaPolicy" Policy実装では、1つまたは複数のポリシー構成ファイルからポリシーを指定できます。ポリシー・ファイルは、指定したコード・ソースのコードにどのアクセス権を許可するかを指定します。次は、/home/sysadminディレクトリのコードに対して/tmp/abcファイルへの読取りアクセスを許可するサンプル・ポリシー・ファイルのエントリです。

grant codeBase "file:/home/sysadmin/" {
    permission java.io.FilePermission "/tmp/abc", "read";
};

ポリシー・ファイルの場所、およびポリシー・ファイルにより付与するアクセス権の詳細は、デフォルトのPolicyの実装とポリシー・ファイルの構文を参照してください。

技術的な観点から言うと、リソースへのアクセスを試みる場合は、実行スレッド上のコードに「特権設定」のマークが付けられていないかぎり、実行スレッドが利用するコードはすべて、そのリソースへのアクセス権を保持する必要があります。付録A: 特権ブロックのためのAPIを参照してください。

アクセス権の説明とリスク

次は、組込みのすべてのJDKアクセス権タイプのリストです。各アクセス権タイプのクラスの概要では、各アクセス権を付与した場合のリスクについて説明します。

ノート:

FilePermissionパス名の正規化方法における変更に関する重要な情報については、付録A: FilePermissionのパス名の正規化がデフォルトで無効化を参照してください。

メソッドとその呼出しに必要なアクセス権

次の表は、アクセス権を必要とするメソッドのリストであり、どのSecurityManagerメソッドが呼び出され、どのアクセス権がそのSecurityManagerメソッドのデフォルト実装によってチェックされるかを示します。

ノート:

これは完全なリストではなく、アクセス権を必要とするその他のメソッドも存在します。SecurityExceptionをスローするメソッドと必要なアクセス権の詳細は、Java SEおよびJDK API仕様を参照してください。

SecurityManagerメソッドのデフォルトの実装では、SecurityManagerメソッド列の対応するエントリで示されているアクセス権が現在有効なポリシーで与えられている場合だけ、メソッド列で示したメソッドを呼び出すことができます。たとえば、次のような表の行があるとします。

メソッド 呼び出されるSecurityManagerメソッド アクセス権
java.awt.Toolkit
  public final EventQueue
    getSystemEventQueue()
checkPermission java.awt.AWTPermission "accessEventQueue";

この表の行では、java.awt.ToolkitクラスのgetSystemEventQueueメソッドへの呼出しは、SecurityManagerメソッドcheckPermissionへの呼出しになることを指定します。これは、呼出しスタック上のコードに次のアクセス権が与えられている場合にのみ成功します。

java.awt.AWTPermission "accessEventQueue";

表の行は次の形式を持ち、アクセス権名中の文字列{foo}fooの実行時の値で置き換えらます。

メソッド 呼び出されるSecurityManagerメソッド アクセス権
some.package.class
  public static void someMethod(String foo);
checkXXX SomePermission "{foo}";

次の例を見てください。

メソッド 呼び出されるSecurityManagerメソッド アクセス権
java.io.FileInputStream
  FileInputStream(String name)
checkRead(String) java.io.FilePermission "{name}", "read";

FileInputStreamメソッド(この場合はコンストラクタ)を、次のように引数name/test/MyTestFileを指定して呼び出したとします。

FileInputStream("/test/MyTestFile");

この呼出しは、現在のポリシーで次のアクセス権が設定され、/test/MyTestFileファイルへの読取りアクセスが許可されていないと行えません。

java.io.FilePermission "/test/MyTestFile", "read";

より正確には、アクセス権は、この例のように明示的に設定するか、次のように、別のアクセス権で暗黙的に設定する必要があります:

java.io.FilePermission "/test/*", "read";

/test」ディレクトリに含まれる任意のファイルへの読取りアクセスが許可されています。

中カッコで囲まれた項目が、特定のメソッド引数と同一ではなく、関係のある値を表す場合もあります。次はその例です。

メソッド 呼び出されるSecurityManagerメソッド アクセス権
java.net.DatagramSocket public synchronized void receive(DatagramPacket p); checkAccept({host}, {port}) java.net.SocketPermission "{host}:{port}", "accept";

ここでは、適切なホストおよびポートの値がreceiveメソッドにより計算されて、checkAcceptに渡されます。

ほとんどの場合、呼び出されるSecurityManagerメソッドの名前のみが一覧表示されます。メソッドは、複数ある同名のメソッドのいずれかであり、引数の型も一覧表示されます。たとえば、checkRead(String)checkRead(FileDescriptor)などがあります。引数が関係するその他の場合にも、引数は一覧表示されます。

次の表は、パッケージ名順になっています。最初にjava.awtパッケージ内のクラスのメソッド、次にjava.beansパッケージ内のクラスのメソッド、という順番です。

表1-5 メソッドおよびそのアクセス権

メソッド SecurityManagerメソッド アクセス権
java.awt.Graphics2d
  public abstract void
    setComposite(Composite comp)
checkPermission このGraphics2Dコンテキストが表示画面上のComponentに描画中であり、かつCompositeAlphaCompositeクラスのインスタンスではなく、カスタム・オブジェクトの場合、java.awt.AWTPermission "readDisplayPixels"。ノート: setCompositeメソッドは、実際には抽象であるため、セキュリティ・チェックを呼び出すことはできない。こうした条件下では、メソッドの実際の実装ごとに、java.awt.AWTPermission("readDisplayPixels")アクセス権でjava.lang.SecurityManager checkPermissionメソッドを呼び出す必要がある。
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"

ノート: getPrintJobメソッドは、実際には抽象であるため、セキュリティ・チェックを呼び出すことはできない。このメソッドの実際の各実装部分では、java.lang.SecurityManager checkPrintJobAccessメソッドを呼び出す必要があり、これは、アクセス権java.lang.RuntimePermission "queuePrintJob"が現在許可されている場合にのみ成功する。

java.awt.Toolkit
  public abstract Clipboard
    getSystemClipboard()
checkPermission

java.awt.AWTPermission "accessClipboard"

ノート: getSystemClipboardメソッドは、実際には抽象であるため、セキュリティ・チェックを呼び出すことはできない。このメソッドの実際の各実装部分では、checkPermissionメソッドを呼び出す必要があり、これは、アクセス権java.awt.AWTPermission "accessClipboard"が現在許可されている場合にのみ成功する。

java.awt.Toolkit
  public final EventQueue
    getSystemEventQueue()
checkPermission java.awt.AWTPermission "accessEventQueue"
java.awt.Window Window()
checkPermission java.awt.AWTPermission "showWindowWithoutWarningBanner"が設定されていると、ウィンドウが表示されるときに、そのウィンドウがアプレットによって作成されていることを警告するバナーは表示されない。設定されていない場合は、バナーが表示される。
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)

(モードは、両方のRandomAccessFileコンストラクタで「r」)

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)      

(モードは「rw」)

checkRead(String)およびcheckWrite(String) java.io.FilePermission "{name}", "read,write"
java.lang.Class
  public static Class forName(
    String name,
    boolean initialize,
    ClassLoader loader)
checkPermission loaderがnullで、呼出し側のクラス・ローダーはnullでない場合、java.lang.RuntimePermission("getClassLoader")になる。
java.lang.Class
  public ClassLoader getClassLoader()
checkPermission 呼出し側のクラス・ローダーがnullの場合、あるいは呼出し側のクラス・ローダーが、クラス・ローダーが要求されているクラスのクラス・ローダーと同じかその上位クラスの場合は、アクセス権は必要ない。それ以外の場合は、java.lang.RuntimePermission "getClassLoader"が必要。
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)、およびこのクラスがパッケージ内にある場合はcheckPackageAccess({pkgName}) 「この」クラスのクラス・ローダーが呼出し側のクラス・ローダーと同一である場合は、デフォルトのcheckMemberAccessはどのようなアクセス権も必要としない。同一でない場合は、java.lang.RuntimePermission "accessDeclaredMembers"が必要。このクラスがパッケージ内にある場合、java.lang.RuntimePermission "accessClassInPackage.{pkgName}"も必要。
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)、およびこのクラスがパッケージ内にある場合はcheckPackageAccess({pkgName}) アクセス・タイプがMember.PUBLICの場合、デフォルトのcheckMemberAccessはどのようなアクセス権も必要としない。このクラスがパッケージ内にある場合、java.lang.RuntimePermission "accessClassInPackage.{pkgName}"が必要。
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 呼出し側のクラス・ローダーがnullの場合、あるいは呼出し側のクラス・ローダーが、クラス・ローダーが要求されているクラスのクラス・ローダーと同じかその上位クラスの場合は、アクセス権は必要ない。それ以外の場合は、java.lang.RuntimePermission "getClassLoader"が必要。

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 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})。ここで、{libName}はlib、filenameまたはlibname引数 java.lang.RuntimePermission "loadLibrary.{libName}"

java.lang.SecurityManagerメソッド

checkPermission 表1-6を参照してください。
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 呼出し側のクラス・ローダーがnullの場合、あるいは呼出し側のクラス・ローダーが、コンテキスト・クラス・ローダーが要求されているスレッドのコンテキスト・クラス・ローダーと同じかその上位クラスの場合は、アクセス権は必要ない。それ以外の場合は、java.lang.RuntimePermission "getClassLoader"が必要。
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)。現在のスレッドが自分以外のスレッドを停止させようとしている場合は、checkPermissionも呼び出される。 java.lang.RuntimePermission "modifyThread"。

現在のスレッドが自分以外のスレッドを停止させようとしている場合、java.lang.RuntimePermission "stopThread"も必要。

java.lang.Thread
  public final synchronized void
    stop(Throwable obj)
checkAccess(this)。現在のスレッドが自分以外のスレッドを停止させようとしている場合、またはobjThreadDeathのインスタンスでない場合は、checkPermissionも呼び出される。 java.lang.RuntimePermission "modifyThread"。

現在のスレッドが自分以外のスレッドを停止させようとしている場合、またはobjThreadDeathのインスタンスではない場合は、java.lang.RuntimePermission "stopThread"も必要。

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()
ThreadGroupメソッドの場合はcheckAccess(this)Threadメソッドの場合はcheckAccess(group) java.lang.RuntimePermission "modifyThreadGroup"
java.lang.ThreadGroup
  public final void interrupt()
checkAccess(this) java.lang.RuntimePermission "modifyThreadGroup"が必要。スレッド・グループ内とそのすべてのサブグループ内のスレッドごとにjava.lang.Thread interrupt()メソッドが呼び出されるため、java.lang.RuntimePermission "modifyThread"も必要。Thread interrupt()メソッドを参照。
java.lang.ThreadGroup
  public final void stop()
checkAccess(this) java.lang.RuntimePermission "modifyThreadGroup"が必要。java.lang.Thread stop()メソッドは、そのスレッド・グループ内およびそのすべてのサブグループ内のスレッドごとに呼び出されるので、java.lang.RuntimePermission "modifyThread"および場合によってはjava.lang.RuntimePermission "stopThread"も必要。Thread stop()メソッドを参照。
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())または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)または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) このアクセス権オブジェクトはチェックされたアクセス権である。
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}" (nameはプロバイダ名)。
java.security.Provider
  public synchronized Object
    put(Object key, Object value)
checkSecurityAccess("putProviderProperty."+{name}) java.security.SecurityPermission "putProviderProperty.{name}" (nameはプロバイダ名)。
java.security.Provider
  public synchronized Object
    remove(Object key)
checkSecurityAccess("removeProviderProperty."+{name}) java.security.SecurityPermission "removeProviderProperty.{name}" (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}"

java.lang.SecurityManagerメソッドのアクセス権チェック

次の表では、java.lang.SecurityManagerメソッドのデフォルトの実装によってチェックされるアクセス権を示します。

指定された各checkメソッドはSecurityManager checkPermissionメソッドを指定されたアクセス権で呼び出します(コンテキスト引数を取るcheckConnectおよびcheckReadメソッドを除く)。これらのメソッドは、AccessControlContextコンテキストを想定し、コンテキストのcheckPermissionメソッドを指定されたアクセス権で呼び出します。

表1-6 java.lang.SecurityManagerのメソッドおよびアクセス権

メソッド アクセス権
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(); 

ノート:

このメソッドは非推奨です。かわりにpublic 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);

cmdが絶対パスの場合:

  java.io.FilePermission "{cmd}", "execute";

それ以外の場合

  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);

ノート:

このメソッドは非推奨です。かわりにpublic 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); 

ノート:

このメソッドは非推奨です。かわりにpublic 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(); 

ノート:

このメソッドは非推奨です。かわりにpublic void checkPermission(Permission perm);を使用
java.awt.AWTPermission "accessClipboard";
public boolean checkTopLevelWindow(Object window); 

ノート:

このメソッドは非推奨です。かわりにpublic 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";

JDKがサポートする権限

次の各権限は標準ではありませんが、JDKでサポートされています。ポリシー・ファイルでこれらの権限を付与することが必要な場合があります。

デフォルトのPolicyの実装とポリシー・ファイルの構文

Javaプログラミング言語のアプリケーション環境のポリシーは、様々なソースを出所とするコードがどのようなアクセス権を使用できるかを指定し、様々なプリンシパルとして実行するもので、Policyオブジェクトによって表されます。具体的には、Policyクラス(java.securityパッケージ内)内のabstractメソッドの実装を提供するPolicyサブクラスによって表されます。

Policyオブジェクトが使用するポリシー情報がどこに置かれるかは、Policyの実装によります。Policyのリファレンス実装では、ポリシー情報を静的なポリシー構成ファイルから得ます。

このドキュメントの残りの部分では、Policyのリファレンス実装と、それによって読み取られるポリシー・ファイルで使用する構文について説明します。

デフォルトのPolicyの実装

Policyのリファレンス実装では、1つまたは複数のポリシー構成ファイルからポリシーを指定できます。ポリシー構成ファイルでは、指定されたコード・ソースからのコードに対してどのようなアクセス権を与え、指定されたプリンシパルとして実行するかを指定します。各構成ファイルは、UTF-8方式でエンコードする必要があります。

デフォルトでは、システム全体のポリシー・ファイルが1つと、ユーザー・ポリシー・ファイル(オプション)が1つ存在します。デフォルトでは、常に、プラットフォーム・クラス・ローダーによってロードされるJDKモジュールまたはその祖先で必要なアクセス権が付与されます。

Policyのリファレンス実装は、そのgetPermissionsメソッドがはじめて呼び出されたとき、あるいは、そのrefreshメソッドが呼び出されたときに初期化されます。初期化時には、ポリシー構成ファイル(ポリシー・ファイルの構文を参照)の解析が行われた後、その情報がPolicyオブジェクトに読み込まれます。

ポリシー・ファイルのデフォルトの場所

デフォルトでは、システム全体のポリシー・ファイルが1つと、ユーザー・ポリシー・ファイル(オプション)が1つ存在します。Policyが初期化されると、まずシステム・ポリシーがロードされ、次に、ロードされたシステム・ポリシーにユーザー・ポリシーが追加されます。どちらのポリシーも存在しない場合は、組込みポリシーが使われます。組込みポリシーは、JDKとともにインストールしたjava.policyファイルと同じです。

システム・ポリシー・ファイルの場所

デフォルトでは、システム・ポリシー・ファイルは<java-home>/conf/security/java.policyです。

システムのポリシー・ファイルは、システム全体にわたってコードにアクセス権を与えます。JDKに含まれているjava.policyファイルは、すべてのユーザーに動的ポートでの待機を許可し、すべてのコードに、セキュリティにかかわらない特定の標準プロパティ(os.nameプロパティやfile.separatorプロパティなど)の読取りを許可します。

ユーザー・ポリシー・ファイルの場所

デフォルトでは、ユーザー・ポリシー・ファイルは<user-home>/.java.policyです。

ポリシー・ファイルの場所と形式

ポリシー・ファイルの場所は、セキュリティ・プロパティ・ファイル<java-home>/conf/security/java.securityで指定されています。

ポリシー・ファイルの場所は、次のような形式の名前を持つプロパティの値として指定されています。

policy.url.n

ここで、nは数値です。次に示す形式の行で、それぞれのプロパティの値を指定します。

policy.url.n=URL

ここで、URLはURLの指定を表します。たとえば、デフォルトのシステムおよびユーザー・ポリシー・ファイルは、セキュリティ・プロパティ・ファイルに次のように指定されています。:

policy.url.1=file:${java.home}/conf/security/java.policy
policy.url.2=file:${user.home}/.java.policy

(${java.home}を使用してjava.homeプロパティの値を指定するなど、特別な構文でプロパティの値を指定する方法の詳細は、ポリシー・ファイル内のプロパティの展開を参照。)

URLをいくつも指定して(http://形式のものを含む)、該当するポリシー・ファイルをすべてロードすることもできます。また、上に示したポリシー・ファイルの指定のうち、2番目のポリシー・ファイルの指定をコメント・アウトするか、あるいは修正すれば、デフォルト・ユーザー・ポリシー・ファイルの読込みを無効にすることができます。

アルゴリズムは、policy.url.1から処理を開始して、番号を1つずつ増やしながら、URLが見つからなくなるまで処理を続けます。したがって、policy.url.1policy.url.3がある場合、policy.url.3は読み込まれません。

実行時に新しいポリシー・ファイルを指定する

アプリケーションを実行するときに、追加のポリシー・ファイルや別のポリシー・ファイルを指定することもできます。これは、-Djava.security.policyコマンド行引数を使用してjava.security.policyプロパティの値を設定することで実行できます。たとえば、次のコマンドを入力した場合(ここで、someURLはポリシー・ファイルの場所を指定するURL)、指定したポリシー・ファイルが、セキュリティ・プロパティ・ファイルに指定されているすべてのポリシー・ファイルに加えてロードされます。

java -Djava.security.manager -Djava.security.policy=someURL SomeApp

次に示すとおり、URLは通常のURLでも、単純に現在のディレクトリのポリシー・ファイルの名前でもかまいません。:

java -Djava.security.manager -Djava.security.policy=mypolicy SomeApp

-Djava.security.managerオプションによってデフォルト・セキュリティ・マネージャがインストールされるので、このアプリケーションに対してはポリシーのチェックが行われます。アプリケーションSomeAppがセキュリティ・マネージャをインストールする場合は、この引数は必要ありません。

次のコマンドを使用した場合(等号が2つ使用されていることに注意)、指定されたポリシー・ファイルのみが使用され、セキュリティ・プロパティ・ファイルに示されたポリシー・ファイルはすべて無視されます。

java -Djava.security.manager -Djava.security.policy==someURL SomeApp

ノート:

セキュリティ・プロパティ・ファイル内のpolicy.allowSystemProperty プロパティがfalseに設定されている場合、-Djava.security.policyオプションのポリシー・ファイル値は無視されます。デフォルトは、trueです。

Policyの実装の変更

セキュリティ・プロパティ・ファイル(JDKのconf/securityディレクトリのjava.securityファイル)を編集すれば、Policyのリファレンス実装を変更できます。

新しいポリシー・クラスを作成し、Policyのリファレンス実装クラスと置き換えることもできます。この場合は、Policy抽象クラスのサブクラスを作成し、getPermissionsメソッド(必要に応じてその他のメソッドも)を実装します。

java.securityで設定できるプロパティの例を次に示します。


    policy.provider=PolicyClassName

PolicyClassNameには、目的のPolicy実装クラスを完全修飾名で指定します。

デフォルトのセキュリティ・プロパティ・ファイルでは、このプロパティは次のように指定されています。


    policy.provider=sun.security.provider.PolicyFile

カスタマイズするには、次のように、このプロパティに別のクラスを指定します。


    policy.provider=com.mycom.MyPolicy

ポリシー・ファイルの構文

インストールしたJDKのポリシー構成ファイルでは、指定されたコード・ソースからのコードに対し、どのようなアクセス権(システム・リソースへのアクセスの種類)を与え、指定したプリンシパルとして実行するかを指定します。

アプレット(またはセキュリティ・マネージャの下で動作しているアプリケーション)が、ファイルの読み書きなど、セキュリティ保護された操作を行うためには、その操作を行うためのアクセス権が与えられている必要があります。Policyのリファレンス実装では、ポリシー構成ファイルの付与エントリによって、そのアクセス権を与える必要があります。ただし、同じ(URLの)場所にあるファイルと、その場所のサブディレクトリにあるファイルの読取りアクセス権は、常に自動的に付与されます。したがって、そうしたファイルの読取りでは、アクセス権を明示する必要はありません。

ポリシー構成ファイルは、エントリのリストで構成されます。1つのkeystoreエントリと、0以上のgrantエントリを持たせることができます。

キーストア・エントリ

キーストアは、秘密キーと、対応する公開キーを認証するX.509証明書チェーンなどのデジタル証明書が格納されたデータベースです。キーストアの作成と管理には、keytoolユーティリティを使用します。ポリシー構成ファイルで指定されているキーストアは、そのファイルのgrantエントリで指定されている署名者の公開キーを照合するために使用されます。署名者の別名を指定しているgrantエントリがある場合、またはプリンシパルの別名を指定しているgrantエントリがある場合は、ポリシー構成ファイルに必ずkeystoreエントリを置きます。

このとき、ポリシー・ファイル内で有効なkeystore/keystorePasswordURLエントリは1つのみです。最初のエントリ以外の後続エントリは無視されます。このエントリは、ファイルのgrantエントリ外部の任意の場所に配置できます。構文は次のとおりです。


keystore "some_keystore_url", "keystore_type", "keystore_provider";
keystorePasswordURL "some_password_url";

各構成要素は次のとおりです。

some_keystore_url
キーストアのURLの場所を指定します。
some_password_url
キーストア・パスワードのURLの場所を指定します。
keystore_type
キーストアのタイプを指定します。
keystore_provider
キーストア・プロバイダを指定します。

ノート:

  • some_keystore_urlからの入力ストリームはKeyStore.loadメソッドに渡されます。

  • URLとしてNONEが指定されている場合は、nullのストリームがKeyStore.loadメソッドに渡されます。NONEは、キーストアがファイルベースでない場合にURLで指定してください。たとえば、ハードウェア・トークン・デバイスに置かれている場合などです。

  • URLは、ポリシー・ファイルがある場所からの相対位置を表します。たとえば、セキュリティ・プロパティ・ファイルの中でポリシー・ファイルが次のように指定されているとします。

        policy.url.1=http://foo.example.com/fum/some.policy
    

    また、このポリシー・ファイルには、次のエントリがあるとします。

        keystore ".keystore";
    

    この場合、キーストアは次の場所からロードされます。

        http://foo.example.com/fum/.keystore
    
  • URLに絶対位置を指定することもできます。

キーストアのタイプは、キーストア情報の格納形式とデータ形式を定義するとともに、キーストア内の秘密キーとキーストア自体の整合性を保護するために使われるアルゴリズムを定義します。デフォルトの型は"PKCS12"です。したがって、キーストアのタイプがPKCS12であれば、キーストア・エントリを指定する必要はありません。

付与エントリ

実行されるコードは、常に、特定の「コード・ソース」(CodeSource型のオブジェクトによって表される)から来ると考えられます。コード・ソースは、コードの出所を表す場所(URL)だけでなく、コードの署名に使われた秘密キーに対応する公開キーを含んだ証明書への参照も含みます。コード・ソース内の証明書は、ユーザーのキーストアからのシンボリックな別名によって参照されます。コードはさらに、特定のプリンシパル(Principal型のオブジェクトによって表される)またはプリンシパルのグループとして実行されると考えられます。

付与エントリには、オプションのcodeBasesignedBy、およびプリンシパルの名前と値のペアのあとに、アクセス権を付与するコードを指定する1つ以上の「アクセス権エントリ」が含まれます。付与エントリの基本形式は、次のとおりです。

  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";
      ...
  };

イタリック以外のすべてのアイテムはそのまま表示する必要があります(ただし、大文字と小文字は区別されず、一部はオプションです)。イタリックで示されている項目は、可変の項目です。

付与エントリは、grantで始まります。

SignedBy、Principal、およびCodeBaseフィールド

signedBycodeBase、およびprincipalの値はオプションです。また、これらのフィールドの順序は問われません。

signedBy値

signedByの値は、キーストアに格納された証明書の別名を示します。証明書内の公開キーは、コードのデジタル署名の検証に使われます。別名によって指定されたキーストア・エントリ内の公開キーに対応する、秘密キーで署名されたコードに、アクセス権を付与します。

signedByの値には、複数の別名をカンマで区切って指定できます。たとえば、"Adam,Eve,Charles"のように指定できます。この場合は、各要素がORではなくANDで結ばれ、「Adam、EveおよびCharlesによって署名された」という意味になります。より厳密には、「Adamによって署名されたコード」とは、「Adamという別名が付けられたエントリを持つキーストアにある公開キー証明書に対応する、秘密キーを使って署名されたJARファイルに含まれている、クラス・ファイル内のコード」という意味です。

signedByフィールドはオプションです。省略した場合は、「任意の署名者」という意味になります。コードに署名が付いているかどうか、だれが署名しているかは問われなくなります。

principal値

プリンシパルの値はclass_nameprincipal_nameのペアを指定します。このペアは、実行中のスレッドのプリンシパル・セット内にある必要があります。プリンシパル・セットは、Subjectによって実行するコードに関連付けられます。

principal_class_nameにワイルドカード値(*)を設定することで、任意のPrincipalクラスに一致させることができます。さらに、principal_nameにワイルドカード値(*)を設定することで、任意のPrincipal名に一致させることができます。principal_class_nameまたはprincipal_nameに*を設定するときは、*を引用符で囲まないでください。また、ワイルドカードのプリンシパル・クラスを指定する場合は、ワイルドカードのプリンシパル名も指定する必要があります。

プリンシパル・フィールドは省略可能です。省略した場合は、「任意のプリンシパル」という意味になります。

キーストア別名の置換

プリンシパルclass_name/principal_nameのペアが単一引用符で囲まれた文字列として指定される場合は、キーストアの別名として扱われます。キーストアは別名を経由してX509証明書を調査し、問い合わせます。キーストアがある場合、プリンシパルclass_nameは自動的にjavax.security.auth.x500.X500Principalとして扱われ、principal_nameは自動的に証明書のサブジェクト識別名として扱われます。X509証明書のマッピングが見つからない場合は、grantエントリはすべて無視されます。

codeBase値

codeBaseの値は、コードが置かれる場所を示します。この場所からコードにアクセス権を付与します。codeBaseエントリを省略した場合は、「任意のコード」という意味になり、コードの出所は問われません。

ノート:

codeBaseの値はURLであるため、コード・ソースがWindowsシステム上にある場合であっても、ディレクトリのセパレータには、バックスラッシュではなく、必ずスラッシュを使用します。したがって、Windowsシステム上でコードの場所がC:\somepath\api\の場合、codeBaseポリシー・エントリは次のように指定します。

grant codeBase "file:/C:/somepath/api/" {
    ...
};

codeBase値の正確な意味は、末尾の文字によって異なります。末尾が/codeBaseは、指定されたディレクトリ内のすべてのクラス・ファイル(JARファイルを除く)を示します。末尾が/*codeBaseは、そのディレクトリ内にあるすべてのファイル(クラス・ファイルとJARファイルの両方)を示します。末尾が/-codeBaseは、指定されたディレクトリとその下の全サブディレクトリ内のすべてのファイル(クラス・ファイルとJARファイルの両方)を示します。次の表では、様々なケースを示します。

表1-7 ダウンロードされたコードとポリシー・ファイル間のcodeBase URLの対応

ダウンロードされたコードのcodebase URL ポリシー・ファイルのcodeBase URL 一致するかどうか
www.example.com/usr/ann/ www.example.com/usr/ann はい
www.example.com/usr/ann/ www.example.com/usr/ann/ はい
www.example.com/usr/ann/ www.example.com/usr/ann/* はい
www.example.com/usr/ann/ www.example.com/usr/ann/- はい
www.example.com/usr/ann/appl.jar www.example.com/usr/ann/ いいえ
www.example.com/usr/ann/appl.jar www.example.com/usr/ann/- はい
www.example.com/usr/ann/appl.jar www.example.com/usr/ann/* はい
www.example.com/usr/ann/appl.jar www.example.com/usr/- はい
www.example.com/usr/ann/appl.jar www.example.com/usr/* いいえ
www.example.com/usr/ann/ www.example.com/usr/- はい
www.example.com/usr/ann/ www.example.com/usr/* いいえ

モジュラ・ランタイム・イメージ(jlinkツールを参照)を使用している場合は、ポリシー・ファイルでjrt URLをcodeBase値として指定することで、イメージ内のアプリケーションとライブラリ・モジュールにアクセス権を付与できます。jrt URLの詳細は、『JEP 220: Modular Run-Time Images』を参照してください。

次の例では、モジュールcom.greetingsに対してfooプロパティの読取りアクセス権を付与します。

grant codeBase "jrt:/com.greetings" {
    permission java.util.PropertyPermission "foo", "read";
};
アクセス権エントリ

アクセス権エントリは、単語permissionで始まります。前の項にあるテンプレートの単語permission_class_nameは、実際にはjava.io.FilePermissionjava.lang.RuntimePermissionなどの特定のアクセス権タイプになります。

java.io.FilePermission (どのような種類のファイル・アクセスを許可するかを指定)など、多くのアクセス権タイプでは"action"が必須です。java.lang.RuntimePermissionなどのカテゴリでは不要なため、必須ではありません。permission_class_nameの後の"target_name"値で指定されたアクセス権が与えられるか、アクセス権が与えられないかのどちらかになります。

アクセス権エントリのsignedByの名前と値のペアは省略可能です。この値が存在する場合は、署名付きアクセス権であることを示します。つまり、そのアクセス権を与えられるようにするためには、アクセス権クラスそれ自体が、指定された別名によって署名されていなければなりません。たとえば、次のような付与エントリがあるとします。

  grant {
      permission Foo "foobar", signedBy "FooSoft";
  };

この場合、このアクセス権タイプFooが与えられるのは、あるJARファイルにアクセス権Foo.classが置かれていて、そのJARファイルが、別名FooSoftにより指定された証明書内の公開キーに対応する秘密キーによって署名されているときか、Foo.classがシステム・クラスであるときです(システム・クラスはポリシーによる制限を受けないため)。

アクセス権エントリの各項目は、指定された順序(permissionpermission_class_name、"target_name"、"action"、およびsignedBy "signer_names")で並んでいる必要があります。各エントリはセミコロンで終わります。

識別子(permissionsignedBycodeBaseなど)では大文字と小文字は区別されませんが、permission_class_nameと、値として引き渡される文字列については大文字と小文字が区別されます。

ノート:

FilePermissionパス名の正規化方法における変更に関する重要な情報については、付録A: FilePermissionのパス名の正規化がデフォルトで無効化を参照してください。

Windowsシステムでのファイル・パスの指定

java.io.FilePermissionを指定する場合、"target_name"はファイル・パスになります。Windowsシステムでは、ファイル・パスをcodebase URLではなく直接文字列で指定する場合は、パス中のバックスラッシュは、次のように2つ重ねて指定する必要があります

    grant {
        permission java.io.FilePermission "C:\\users\\cathy\\foo.bat", "read";
    };

これは、文字列はトークナイザ(java.io.StreamTokenizer)によって処理され、トークナイザは「\」をエスケープ文字列と解釈するため(たとえば、「\n」は改行を表す)、バックスラッシュそのものを表すには、バックスラッシュを2つ重ねる必要があるからです。トークナイザが上のファイル・パス文字列の処理を終え、二重のバックスラッシュが単一のバックスラッシュに変換されると、結果は次のようになります

    "C:\users\cathy\foo.bat"

ポリシー・ファイルの例

次のポリシー構成には、次の2つのエントリがあります。

  // 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";
  }; 

次のポリシー構成ファイルは、次の条件を満たすコードのみSecurityクラス内のメソッドを呼び出して、プロバイダの追加または削除を行ったり、Securityプロパティを設定できることを指定します。

  • ローカル・ファイル・システムの"/home/sysadmin/"ディレクトリにある、署名されたJARファイルからコードがロードされた。
  • 署名が、キーストア内の別名sysadminによって参照される公開キーで認証される。
  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.*";
  };

ポリシー・エントリのいずれか(または両方)を省略可能です。

次は、codeBaseを省略したポリシー構成ファイルです。

  grant signedBy "sysadmin" {
      permission java.security.SecurityPermission "Security.insertProvider.*";
      permission java.security.SecurityPermission "Security.removeProvider.*";
  };

このポリシーが有効な場合、"sysadmin"によって署名されたJARファイルに含まれるコードは、JARファイルの出所に関係なく、プロバイダの追加と削除を行えます。

次は、署名者を省略したポリシー構成ファイルです。

  grant codeBase "file:/home/sysadmin/-" {
      permission java.security.SecurityPermission "Security.insertProvider.*";
      permission java.security.SecurityPermission "Security.removeProvider.*";
  };

この場合、ローカル・ファイル・システムの"home/sysadmin/"ディレクトリに置かれたコードは、プロバイダの追加と削除を行うことができます。コードに署名は必要ありません。

次は、codeBasesignedByを両方とも省略したポリシー構成ファイルです。

  grant {
      permission java.security.SecurityPermission "Security.insertProvider.*";
      permission java.security.SecurityPermission "Security.removeProvider.*";
  };

この例では、コード・ソースを指定する要素がどちらも省略されています。したがって、出所がどこか、署名が付いているか、だれの署名が付いているかに関係なく、どのコードでもプロバイダの追加と削除が行えます。

次は、プリンシパルベースのエントリを表しています。

  grant principal javax.security.auth.x500.X500Principal "cn=Alice" {
      permission java.io.FilePermission "/home/Alice", "read, write";
  };

これにより、X500Principalのアクセス権cn=Aliceとして実行するコードは/home/Aliceを読み取ることも書き込むことも可能になります。

次は、ワイルドカード値を含むプリンシパルベースのエントリを表しています。

  grant principal javax.security.auth.x500.X500Principal * {
      permission java.io.FilePermission "/tmp", "read, write";
  };

これにより、X500Principalのアクセス権(識別名に関係なく)として実行するコードは/tmpを読み取ることも書き込むことも可能になります。

次の例は、codesource情報とprincipal情報を持つgrant文を表しています。

  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";
  };

これにより、"Duke"によって署名され、"www.games.example.com"からダウンロードされたコードが"cn=Alice"によって実行されると、"/tmp/games"ディレクトリへの読取り権と書出し権が与えられます。

次の例は、キーストアの別名を置き換えるgrant文を示しています。

  keystore "http://foo.example.com/blah/.keystore";

  grant principal "alice" {
      permission java.io.FilePermission "/tmp/games", "read, write";
  };

"alice"は次のように置き換えられます。

    javax.security.auth.x500.X500Principal "cn=Alice"

これは、キーストア別名aliceに関連付けられたX.509証明書に、サブジェクトの識別名"cn=Alice"があることが前提となります。これにより、X500Principalのアクセス権"cn=Alice"によって実行されるコードに、"/tmp/games"ディレクトリへの読取り権と書出し権が与えられます。

ポリシー・ファイル内のプロパティの展開

ポリシー・ファイルとセキュリティ・プロパティ・ファイルでは、プロパティの展開が可能です。

プロパティの展開は、シェルでの変数の展開に似ています。ポリシー・ファイルまたはセキュリティ・プロパティ・ファイルに次のような文字列がある場合、

    ${some.property}

この文字列はシステム・プロパティの値に展開されます。たとえば、

    permission java.io.FilePermission "${user.home}", "read";

この場合、"${user.home}"は、システム・プロパティ"user.home"の値に展開されます。そのプロパティの値が/home/cathyの場合、上の例は次のようになります

    permission java.io.FilePermission "/home/cathy", "read";

プラットフォームにより異なるポリシー・ファイルを使いやすくするために、${/}という特殊な表記(${file.separator}の簡略形)も使用できます。この表現を使用して、次のような指定が可能です。

    permission java.io.FilePermission "${user.home}${/}*", "read";

user.homeプロパティの値が/home/cathyで、使用しているのがSolaris、LinuxまたはmacOSであれば、上の例は次のように変換されます:

    permission java.io.FilePermission "/home/cathy/*", "read";

また、user.homeの値がC:\users\cathyで、使用しているのがWindowsシステムであれば、上の例は次のように変換されます:

    permission java.io.FilePermission "C:\users\cathy\*", "read";

特殊なケースとして、コード・ベースのプロパティを次のように記述すると、

    grant codeBase "file:${my.libraries}/api/"

ファイル・セパレータ文字は自動的に/文字に変換されます。たとえば、値がmy.librariesである場合はC:\Users\me\libとなります。したがって、Windowsシステムでは、前の例は次のように変換されます

    grant codeBase "file:C:/Users/me/lib/api/"

したがって、コード・ベース文字列では${/}を使用する必要はありません(使用しないでください)。プロパティの展開は、ポリシー・ファイル内で、二重引用符で囲まれた文字列が使用できる場所であればどこでも行われます。これには、"signer_names""URL""target_name""action"の各フィールドが含まれます。プロパティの展開が許可されるかどうかは、セキュリティ・プロパティ・ファイルの"policy.expandProperties"プロパティの値によって決まります。このプロパティの値がtrue (デフォルト)の場合は、展開が許可されます。

ノート:

ネストされたプロパティは使用できません。たとえば、

    "${user.${foo}}"

この例では、"foo"プロパティが"home"に設定されている場合であっても、エラーになります。これは、プロパティ構文解析プログラムはネストされたプロパティを認識しないためです。プロパティ構文解析プログラムは、最初の${を見つけると、次に最初の}を探し、その結果(この場合は${user.$foo})をプロパティと解釈しようとします。しかし、そのようなプロパティがない場合はエラーになります。

ノート:

付与エントリ、アクセス権エントリまたはキーストア・エントリで展開できないプロパティがある場合、そのエントリは無視されます。たとえば、次のようにシステム・プロパティ"foo"が定義されていない場合、

    grant codeBase "${foo}" {
        permission ...;
        permission ...;
    };

このgrantエントリ内のpermissionはすべて無視されます。また、次のような場合、

    grant {
        permission Foo "${foo}";
        permission Bar "barTarget";
    };

"permission Foo..."エントリだけが無視されます。また、次のように指定されている場合、

    keystore "${foo}";

この場合は、keystoreエントリが無視されます。

Windowsシステム、ファイル・パス、およびプロパティの展開

Windowsシステムでのファイル・パス仕様には、実際の1つバックスラッシュごとに、2つのバックスラッシュを含める必要があります。

Windowsシステムでのファイル・パスの指定で説明したように、Windowsシステムでは、ファイル・パスをcodebase URLではなく直接文字列で指定する場合は、パス内の実際の単一のバックスラッシュごとに、次のように2つのバックスラッシュを含める必要があります

    grant {
        permission java.io.FilePermission "C:\\users\\cathy\\foo.bat", "read";
    };

これは、文字列はトークナイザ(java.io.StreamTokenizer)によって処理され、トークナイザは\をエスケープ文字列と解釈するため(たとえば、\nは改行を表す)、バックスラッシュそのものを表すには、バックスラッシュを2つ重ねる必要があるからです。トークナイザが上のファイル・パス文字列の処理を終え、二重のバックスラッシュが単一のバックスラッシュに変換されると、結果は次のようになります

    "C:\users\cathy\foo.bat"

文字列中のプロパティの展開は、トークナイザがその文字列の処理を完了したあとに行われます。たとえば、次のような文字列があるとします。

    "${user.home}\\foo.bat"

トークナイザは、この文字列中の二重のバックスラッシュを単一のバックスラッシュに変換し、結果は次のようになります。

    "${user.home}\foo.bat"
次に、${user.home}プロパティが展開されて次のようになります。
    "C:\users\cathy\foo.bat"
ここでは、"user.home"の値をC:\users\cathyとしています。もちろん、プラットフォームに依存しないために、明示的にスラッシュを使うのではなく、${/}プロパティを使って次のように指定する方が望ましいと言えます。
    "${user.home}${/}foo.bat"

ポリシー・ファイルにおける一般的な展開

ポリシー・ファイルでは一般化された形式の展開もサポートされています。たとえば、アクセス権名が次の形式の文字列を含んでいるとします。

${{protocol:protocol_data}}

このような文字列がアクセス権名に含まれている場合、protocolの値で実行される展開のタイプが決まり、protocol_dataを使用して展開が実行されます。protocol_dataは空にすることも可能で、その場合、上の文字列は次のような形式になります:

${{protocol}}

デフォルトのポリシー・ファイルの実装では、次の2つのプロトコルがサポートされます。

  1. ${{self}}

    プロトコルselfは、${{self}}文字列全体を1つ以上のプリンシパル・クラスとプリンシパル名のペアに置き換えることを示します。実際に実行される置換えは、permissionを含むgrant節の内容によって決まります。

    grant節にプリンシパルの情報が含まれていない場合は、permissionは無視されます。プリンシパルベースのgrant節のコンテキストでは、ターゲット名に${{self}}を含むpermissionのみが有効です。たとえば、次のgrant節内のBarPermissionは常に無視されます。

    grant codebase "www.example.com", signedby "duke" {
        permission BarPermission "... ${{self}} ...";
    };

    grant句にプリンシパル情報が含まれている場合は、${{self}}がそのプリンシパル情報に置き換えられます。たとえば、次のgrant句のBarPermission内の${{self}}は、javax.security.auth.x500.X500Principal "cn=Duke"に置き換えられます。

    grant principal javax.security.auth.x500.X500Principal "cn=Duke" {
        permission BarPermission "... ${{self}} ...";
    };
    

    grant句内にカンマで区切られたプリンシパルのリストがある場合、${{self}}は、そのカンマで区切られたプリンシパルのリストに置き換えられます。grant句内のプリンシパル・クラスとプリンシパル名がどちらもワイルドカードになっている場合、${{self}}は、現在のAccessControlContext内のSubjectに関連付けられたすべてのプリンシパルに置き換えられます。

    次の例は、selfキーストア別名の置換の両方を含むシナリオを示しています。

    keystore "http://foo.example.com/blah/.keystore";
    
    grant principal "duke" {
        permission BarPermission "... ${{self}} ...";
    };
    

    上の例では、初めにdukeが、javax.security.auth.x500.X500Principal "cn=Duke"に展開されますが、KeyStoreの別名"duke"に関連付けられたX.509証明書に、サブジェクトの識別名"cn=Duke"があることが前提となります。次に、${{self}}が、grant節内で展開されたその同じプリンシパル情報に置き換えられます。javax.security.auth.x500.X500Principal "cn=Duke"

  2. ${{alias:alias_name}}

    プロトコルaliasは、java.security.KeyStore別名の置換を示します。KeyStoreエントリに指定されたKeyStoreが使用されます。alias_nameは、KeyStoreの別名を表します。${{alias:alias_name}}は、javax.security.auth.x500.X500Principal "DN"に置き換えられます。このDNは、alias_nameに属する証明書のサブジェクト識別名を表します。たとえば:

    keystore "http://foo.example.com/blah/.keystore";
    
    grant codebase "www.example.com" {
        permission BarPermission "... ${{alias:duke}} ...";
    };
    

    上の例の別名dukeに関連付けられているX.509証明書は、KeyStore (foo.example.com/blah/.keystore)から取得されます。dukeの証明書がサブジェクト識別名としてo=dukeOrg, cn=dukeを指定し、${{alias:duke}}javax.security.auth.x500.X500Principal "o=dukeOrg, cn=duke"で置き換えられるものとします。

    次のエラー条件に該当する場合、アクセス権エントリは無視されます。

    • keystoreエントリが指定されていない
    • alias_nameが指定されていない
    • alias_nameの証明書を取得できない
    • 取得される証明書がX.509証明書ではない

付録A: FilePermissionのパス名の正規化がデフォルトで無効化

正規パスは、リンクやショートカットを含まないパスです。FilePermissionオブジェクトでパス名正規化を実行すると、パフォーマンスに悪影響を与える可能性があります。

JDK 9より前は、2つのFilePermissionオブジェクトが比較されるときに、パス名が正規化されました。これにより、プログラムで、ポリシー・ファイル内でFilePermissionオブジェクトに付与されている名前とは異なる名前を使用してファイルにアクセスできました(そのオブジェクトが同じファイルを指している場合)。正規化では、基にあるファイル・システムにアクセスする必要があったため、非常に低速になる場合がありました。

JDK 9では、パス名正規化はデフォルトでは無効になっています。これは、一方が絶対パスを使用し他方が相対パスを使用する場合、一方がシンボリック・リンクを使用し他方がターゲットを使用する場合、または一方がWindowsロング・ネームを使用し他方がDOS形式の8.3ネームを使用する場合は、2つのFilePermissionオブジェクトが互いに等しくないということです。これは、それらすべてがファイル・システム内の同じファイルを指している場合でも当てはまります。

したがって、パス名がポリシー・ファイルのFilePermissionオブジェクトに付与されている場合、プログラムは同じパス名形式を使用してファイルにアクセスする必要もあります。たとえば、ポリシー・ファイル内のパス名でシンボリック・リンクが使用されている場合、プログラムでもそのシンボリック・リンクを使用する必要があります。ターゲット・パス名でファイルにアクセスすると、アクセス権チェックに失敗します。

互換性レイヤー

相対パスのFilePermissionオブジェクトの付与により(逆に)アプリケーションに絶対パスでのファイルへのアクセスが許可されるように、互換性レイヤーが追加されています。これは、デフォルトのPolicyプロバイダおよび制限付きdoPrivileged呼出しで機能します。

たとえば、相対パス名がaのファイル上のFilePermissionオブジェクトは、絶対パス名が/pwd/a (pwdは現在の作業ディレクトリ)の同一ファイル上のFilePermissionオブジェクトを意味するわけではなくなりました。セキュリティ・マネージャが有効になっている場合は、aを読み取るFilePermissionオブジェクトをコードに付与すると、そのコードで/pwd/aも読み取ることができます。

互換性レイヤーは、シンボリック・リンクとターゲット、Windowsロング・ネームとDOS形式8.3ネーム、または同じ名前に正規化できる他の様々な名前形式の間の変換には対応していません。

パス名正規化のカスタマイズ

表1-8のシステム・プロパティは、FilePermissionパス名正規化のカスタマイズに使用できます。java.lang.Systemプロパティの指定方法を参照してください。

表1-8 パス名正規化をカスタマイズするシステム・プロパティ

システム・プロパティ デフォルト値 説明
jdk.io.permissionsUseCanonicalPath false

このシステム・プロパティは、FilePermissionオブジェクトでのパス名正規化を有効または無効にするために使用できます。

  • FilePermissionパス名正規化を無効にするには、jdk.io.permissionsUseCanonicalPath=falseと設定します。

  • FilePermissionパス名正規化を有効にするには、jdk.io.permissionsUseCanonicalPath=trueと設定します。

jdk.security.filePermCompat false

このシステム・プロパティは、サードパーティのPolicyの実装をサポートするように互換性レイヤーを拡張するために使用できます。

  • このシステム・プロパティを無効にするには、jdk.security.filePermCompat=falseと設定します。

    相対パスのFilePermissionで、アプリケーションが、デフォルトPolicyプロバイダおよび制限付きdoPrivilegedメソッドの絶対パスを使用してファイルにアクセスできるようになります。

  • サードパーティのPolicyの実装をサポートするように互換性レイヤーを拡張するには、jdk.security.filePermCompat=trueと設定します。

    相対パスのFilePermissionで、アプリケーションが、デフォルトPolicyプロバイダ、制限付きdoPrivilegedメソッド、およびサードパーティのPolicyの実装の絶対パスを使用してファイルにアクセスできるようになります。