セキュリティーマネージャーと Java SE JDK

ドキュメント改訂 1.7



はじめに
セキュリティーモデルの進化
セキュリティーマネージャーの進化
セキュリティーマネージャーのメソッド
JDK 1.1 のセキュリティーマネージャー
Java SE JDK のセキュリティーマネージャー
Installing java.lang.SecurityManager as the Default Security Manager
クラスローダおよびクラスローダ深度用メソッドの変更
1.1 スタイルのセキュリティーマネージャーのポーティング方法
SecurityManager メソッドの変更とオーバーライドに関するアドバイス


はじめに

このドキュメントでは、JDK のセキュリティーマネージャーに加えられた変更について説明します。 この変更により、アプリケーションのデフォルトのセキュリティーマネージャーとしてこのセキュリティーマネージャーを使用できるようになりました。

セキュリティーモデルの進化

JDK 1.1 では、ローカルアプリケーションおよび適切にデジタル署名されたアプレットは通常は信頼され、ファイルシステムなどの重要なシステムリソースへの完全なアクセス権を持っていましたが、署名されていないアプレットは信頼されず、限られたりソースにしかアクセスできませんでした。どのリソースへのアクセスを許可するか決める責任は、セキュリティーマネージャーが負っていました。

Java SE JDK のセキュリティーアーキテクチャーはポリシーベースで、きめ細かなアクセス管理が可能です。ロードされたコードには、現在有効なセキュリティーポリシーをもとに「アクセス権」が割り当てられます。個々のアクセス権には、特定のリソースに対して許可されるアクセスが指定されます。たとえば、特定のファイルやディレクトリに対する「読み取り」と「書き込み」のアクセスや、特定のホストとポートへの「接続」アクセスなどです。ポリシーは、署名者や場所の異なるコードに与える権限を指定します。ポリシーは、設定可能な外部のポリシーファイルを使って初期化できます。コードに対し明示的にアクセス権が与えられていなければ、そのコードから、そのアクセス権で保護されたリソースにはアクセスできません。アクセス権とポリシーのこの新しい概念により、JDK ではきめ細かで調節しやすく、柔軟で拡張性の高いアクセス管理を提供できます。アプレットだけでなく、アプリケーション、Bean、サーブレットを含むすべての Java コードに、このようなアクセス管理を指定できるようになりました。

Java のセキュリティーアーキテクチャーの詳細については、セキュリティードキュメントを参照してください。

セキュリティーマネージャーの進化

セキュリティーマネージャーのメソッド

SecurityManager クラスには、名前が check で始まるメソッドが多数あります。たとえば checkReadcheckConnect などです。Java ライブラリのさまざまなメソッドが、セキュリティーが重視されるオペレーションを実行する前に毎回 check メソッドを呼び出します。これにより、セキュリティーマネージャーには、例外をスローしてオペレーションの実行を阻止する機会が与えられます。セキュリティーマネージャーのルーチンは、そのオペレーションが許可されているときには単に呼び出し元に戻るだけですが、そのオペレーションが許可されていないときには SecurityException をスローします。この規則の唯一の例外は checkTopLevelWindow で、これはブール値を返します。

SecurityManager クラスに含まれる、もうひとつの主要なタイプのメソッドは、クラスローダの存在と深度に関係するクラスです。

JDK 1.1 のセキュリティーマネージャー

JDK 1.1 では、java.lang.SecurityManager クラスは abstract クラスでした。セキュリティーマネージャーの check メソッドは、デフォルト実装では例外をスローしました。クラスローダと深度に関連するクラスは適切に、多くの場合はネイティブコードで実装されました。

セキュリティーマネージャーをインストールしようとするアプリケーション (ブラウザなど) はすべて、独自のセキュリティーマネージャーを作成して、デフォルトで例外をスローするメソッドの固定実装を適切に提供する必要がありました。これらのメソッドは、主に check メソッドでした。

JDK 1.1 アプレットのセキュリティーマネージャーモデルを基にしたセキュリティーマネージャーは、一般的には次の 2 点に基づいてアクセス管理を決定します。

  1. クラスローダを持つクラス (JDK 1.1 のアプレット) がスタック上にあるかどうか

  2. クラスローダの深度 (クラスローダを使って定義されたクラスメソッドが、スタックのどれくらいの深さで最近発生したか)

これらのタイプの決定は、クラスローダの存在と深度に関係する SecurityManager メソッドの呼び出しによって行われていました。たとえば、典型的な 1.1 スタイルのセキュリティーマネージャーには、次のような checkExit メソッドがあります。

     public void checkExit(int status) {
       if (inClassLoader()) {
        throw new SecurityException(..);
       } 
     }

このような checkExit メソッドは、クラスローダを使って定義されたクラス (アプレット) がスタックにあるときは Runtime.exit の呼び出しを許可しませんでした。これは前者のケースの例で、クラスローダを持つクラスがスタックにあるかどうかをチェックします。後者のケース (クラスローダの深度) の例は、次のようなものです。

      public void checkCreateClassLoader() {
         if (classLoaderDepth() == 2) {
            throw new SecurityException();
         }
      }

このメソッドは、クラスローダの深度が 2 であってはならないことを示しています。つまり、checkCreateClassLoader を呼び出したメソッドを呼び出すメソッドは、クラスローダで定義されたクラスにあってはなりません。たとえば、java.lang.ClassLoader のコンストラクタは checkCreateClassLoader を呼び出します。これは、java.lang.ClassLoader のコンストラクタを呼び出すメソッドが、クラスローダを持っていてはならないことを意味します。したがって、アプレットはクラスローダを直接作成できないことになります。

2 つのメソッドはどちらもアプレットの実行を阻止しようとしますが、2 つには大きな違いがあります。前者のケースでは、スタックのどこかにアプレットがあると checkExit が例外をスローします。これは、組み込みの JDK コードであっても、アプレットから呼び出された場合には、VM を終了できないことを意味します。後者のケースでは、JDK コードはアプレットから呼び出された場合にも、クラスローダを作成することができます。その理由は、使用されるのはクラスローダを持つクラスの深度であり、それが存在するという事実ではないからです。

Java SE JDK のセキュリティーマネージャー

JDK では、java.lang.SecurityManager クラスをアプリケーションのデフォルトのセキュリティーマネージャーとして使用できるよう、多くの変更が加えられました。特に次の点が重要です。

java.lang.SecurityManager をデフォルトのセキュリティーマネージャーとしてインストールする

java.lang.SecurityManager は abstract クラスでなくなったので、デフォルトのセキュリティーマネージャーとしてインストールして使用できるようになりました。これを行うには、VM を起動するときにシステムプロパティーを設定します。

    java -Djava.security.manager YourApp
別の方法として、次のコードを使ってアプリケーションから直接インストールすることもできます。
    System.setSecurityManager(new SecurityManager());
デフォルトのセキュリティーマネージャーの動作は、ポリシーファイルを変更することによってカスタマイズできます。詳細については、ポリシーファイルのセキュリティーガイドを参照してください。

クラスローダおよびクラスローダ深度用メソッドの変更

JDK では、クラスローダとクラスローダ深度に関連する SecurityManager メソッドは推奨されておらず、どの check メソッドからも呼び出されません。新しいセキュリティーマネージャーではこれらのメソッドは使用せず、既存のセキュリティーマネージャーからも削除することをお勧めします。ただし、これらのメソッドは旧バージョンとの互換性のために残されており、JDK でも 1.1 スタイルのセキュリティーマネージャーが動作するように変更されました。

これらのメソッドを次に挙げます。

  • currentClassLoader
  • currentLoadedClass
  • inClassLoader
  • classLoaderDepth

クラスローダと深度に関連するメソッドの修正

クラスローダと深度に関連するメソッドはすべて、次の 3 つの点で修正されました。

  1. これらのメソッドはシステムクラスローダを無視します。システムクラスローダとは、システムクラスローダ (ClassLoader.getSystemClassLoader によって返される) またはその祖先のひとつに等しいクラスローダであると定義されます。

    システムクラスローダによってロードされたクラスには、アプリケーションクラス (CLASSPATH からロードされる)、拡張クラス、組み込み JDK クラスがあるので、これらのメソッドはこの修正により、これらのコードを無視することができます。

    カスタムセキュリティーマネージャーをインストールしているアプリケーションを実行する場合で、かつそのセキュリティーマネージャーが JDK の CLASSPATH からロードされる場合には、そのセキュリティーマネージャーには、システムクラスローダが関連付けられます。JDK 1.1 ではアプリケーションクラスはクラスローダを持ちません。ユーザーがカスタムセキュリティーマネージャー内から classLoaderDepth のようなメソッドを呼び出す予定で、またそのメソッドがシステムクラスローダによりロードされたクラスを無視するように変更されていない場合には、そのメソッドは常に 0 を返します。これは便利とはいえません。同様に、クラスローダメソッドがシステムクラスを無視するように変更されておらず、カスタムのセキュリティーマネージャーが CLASSPATH からロードされる場合にも、たとえば "classLoaderDepth() == 2" のときにオペレーションを許可しないという方法で、セキュリティーマネージャーが決定を行うような場合には、セキュリティーホールが生じます(実際は "classLoaderDepth() <= 2" であるべきです)。

  2. これらのメソッドは、スタック上で「特権つき」のマークがつけられているメソッドに到達すると、チェックを終了します(java.security.AccessController.doPrivileged() および「特権ブロックのための API」を参照)。

  3. これらのメソッドは、AllPermission が与えられているセキュリティーコンテキストを、スタック上にクラスローダが存在しないかのように取り扱います。

1 番目と 2 番目の変更の例として、JDK でセキュリティーマネージャーのインストール後にファイルを開くなどの操作を行う場所があります。1.1 スタイルのセキュリティーマネージャーには、次のような checkRead メソッドを持つものがあります。

       public void checkRead(String file) {
         if (inClassLoader()) {
          throw new SecurityException(..);
         } 
       }

JDK のコードを修正しないと、JDK 自体がファイルを読み込もうとしたときに、システムクラスローダでないクラスローダがスタック上に存在する場合には、JDK で実行するようなチェックがセキュリティー例外を引き起こします。新しいセキュリティーモデルでは、呼び出し元に対して許可されていない可能性のある操作を実行しようとする JDK コードはすべて、doPrivileged ブロックを持ちます。inClassLoader は単に、「特権付き」コードを含むフレームまでのスタックを調べるだけであり、スタックの一番上のコードはシステムクラスローダまたはその上位クラスによりロードされる JDK コードなので、inClassLoader メソッドは false を返し、読み取りを許可します。

クラスローダ深度の維持

先に説明したように、1.1 アプレットのセキュリティーマネージャーを基にしたセキュリティーマネージャーは、アクセス管理の決定の一部をクラスローダ深度に基づいて行います。例として、前述した checkCreateClassLoader メソッドをもう一度示します。

       public void checkCreateClassLoader() {
          if (classLoaderDepth() == 2) {
             throw new SecurityException();
          }
       }
JDK では、1.1 スタイルのセキュリティーマネージャーで使用されていたとおりに、スタック深度を維持しようとしました。たとえば、java.security.SecureClassLoader のコンストラクタは、そのスーパークラス (ClassLoader) のコンストラクタが同じことを行うとしても、SecurityManager.checkCreateClassLoader への明示的な呼び出しを行います。SecureClassLoader のコンストラクタにチェック機能がない場合は、クラスローダの深度は常に 2 よりも大きいため、1.1 スタイルのセキュリティーマネージャーは信頼されないクラスに対して SecureClassLoader を拡張してクラスローダを構築することを許可します。

1.1 スタイルのセキュリティーマネージャーのポーティング方法

セキュリティーマネージャーを JDK 環境で実行する前に、まず自分のカスタムセキュリティーマネージャーのメソッドをすべて解析しておくことを強くお勧めします。解析を行わないと、セキュリティーホールが生じたり、JDK が適切に動作しなくなることがあります。これは、1.1 スタイルのセキュリティーマネージャーが弱い性質を持っているためです。

可能なら、1.2 の SecurityManager のデフォルト実装を使うようにします。これは、ユーザーと管理者に対して一貫性のある動作を提供するのに役立ちます。これが不可能なら、少なくとも checkXXX メソッドの中でセキュリティー例外をスローする前に super.checkXXX を呼び出すようにしてください。これにより、アクセス管理アルゴリズムの使用が可能になり、JDK 自体が正しく機能するようになります。

JDK では、SecurityManager check メソッドの呼び出しに使用されていた既存のコードは、変更されていません。セキュリティーチェックの必要な新しいコードについては、呼び出しが SecurityManager.checkPermission に対して行われ、新しい SecurityManager check メソッドは追加されません。たとえば、新しく追加された java.lang.System.setProperty メソッドは、java.util.PropertyPermission アクセス権で checkPermission を呼び出します。

SecurityManager クラスを拡張して既存のメソッドをオーバーライドする場合は、注意が必要です。たとえば、checkRead(String file) メソッドをオーバーライドして常にセキュリティー例外をスローするようにすると、JDK 自体が正しく動作しなくなることがあります。つまり、一部の JDK コードでファイルを開く必要がある場合に (プロパティーファイルの読み込みや、JAR ファイルのロードなどのため)、読み取りのたびにセキュリティー例外をスローすると、ファイルを開く操作が必ず失敗することになります。

一般に、デフォルトのメソッドをオーバーライドするのは、セキュリティーの緩和の目的でのみ行うべきであり、セキュリティーの強化の目的には行うべきではありません。セキュリティーを強化したい場合には、デフォルトのポリシーファイルの修正、またはカスタムの java.security.Policy オブジェクトのインストールのどちらかまたは両方を行います。詳細については、ポリシーファイルのセキュリティーガイドを参照してください。

一般に、セキュリティーマネージャーのメソッドをオーバーライドするときは、オーバーライドされた super.checkXXX メソッドが例外をスローする位置に、checkXXX メソッドへの呼び出しを記述する必要があります。例を示します。

      public class MySecurityManager extends SecurityManager {

        public void checkRead(String file) {
          if (someCustomSecurityCheckFails()) {
             super.checkRead(file);
          }
        }
      }
    
カスタムのセキュリティーチェックが失敗した場合には、次に super.checkRead が呼び出されます。checkRead のデフォルト実装では checkPermission が呼び出され、これはデフォルトで AccessController に問い合わせを行います。AccessController を呼び出すことにより、ファイルを読み出す前に AccessController.doPrivileged を行なったシステムコードは、そのファイルの読み取りに成功します。それ以外のすべてのコードはその時点で有効なポリシーに従い、そのファイルへのアクセス権が与えられていない場合には、アクセス管理例外がスローされます。

checkXXX メソッドには、それをオーバーライドするときに super.checkXXX メソッドを呼び出してはならないものがあります。その理由は、これらのメソッドのデフォルト実装は、オーバーライド後のメソッドで実装しているポリシーほど厳しくない場合があるからです。たとえば、デフォルトの checkAccess(ThreadGroup g) メソッドは、システムスレッドグループだけを保護します。独立したスレッドグループ (アプレットスレッドグループなど) をお互いから保護しようとする場合は、通常はセキュリティー例外をスローする位置で super.checkAccess を呼び出すと、カスタムチェックの目的が損なわれるため、通常その位置ではスローしません。その代わり、オーバーライドしたメソッドの最初のステートメントで、super.checkAccess への呼び出しを記述することができます。

例を示します。

      public class AppletSecurityManager extends SecurityManager {

        public void checkAccess(ThreadGroup g) {
          // a call to super will throw an exception if someone
          // is trying to modify the system thread group
          super.checkAccess(g);
          ...
          // now perform checks based on which applet thread group
          // the current caller is in to see if they can modify thread group g.
          ...
      }
    

次に、各メソッドをオーバーライドする方法を説明します。

SecurityManager メソッドの変更とオーバーライドに関するアドバイス

ここでは、JDK で java.lang.SecurityManager メソッドに加えられた変更のリストを示し、オーバーライドを実行する際のアドバイスを行います。これらのメソッドの詳細については、SecurityManager クラスの Java ドキュメントを参照してください。

protected boolean inCheck

このフィールドは推奨されなくなり、JDK 内でのこのフィールドの使用はすべて削除されました。inCheck を使う代わりに、checkPermissiondoPrivileged とともに使ってください。

public boolean getInCheck();

このメソッドも推奨されなくなりました。

public SecurityManager();

コンストラクタは、呼び出し元が RuntimePermission("createSecurityManager") アクセス権を持っていると仮定して、複数の SecurityManager の作成が可能になるように修正されました。

protected native Class[] getClassContext();

変更はありません。この呼び出しは、JDK で変更されたメソッド (currentClassLoadercurrentLoadedClassclassLoaderDepthinClassLoader) の 1.1 での動作をエミュレートするために使用できます。

protected ClassLoader currentClassLoader();

JDK 1.1 スタイルのセキュリティーマネージャーでのこのメソッドの典型的な使用方法は、スタックにクラスローダがあるかどうかを調べることです。このとき、クラスローダがない場合は、コードを「信頼できる」ものとして取り扱い、コードにすべての動作を許可します。このメソッドは JDK で修正され、doPrivileged を呼び出す信頼できる JDK コード (実際には、java.security.AllPermission を与えられたすべてのコード) は、1.1 スタイルのセキュリティーマネージャーに信頼されるものとして取り扱われるようになりました。またこのコードは、システムクラスローダを無視するように修正されました。システムクラスローダとは、システムクラスローダ (ClassLoader.getSystemClassLoader によって返される) またはその上位オブジェクトのひとつに等しいクラスローダであると定義されます。

このメソッドは、次の 3 つの場合に null コードを返します。

  1. 実行スタック上のすべてのメソッドが、システムクラスローダまたはその上位オブジェクトの 1 つを使って定義されたクラスからのものである場合
  2. 最初の「特権つき」呼び出し元 (java.security.AccessController.doPrivileged を参照) までの実行スタック上のすべてのメソッドが、システムクラスローダまたはその上位オブジェクトの 1 つを使って定義されたクラスからのものである場合
  3. checkPermission を java.security.AllPermission アクセス権で呼び出した結果、SecurityExeception がスローされなかった場合

このメソッドは推奨されなくなりました。代わりに checkPermission を使用してください。

protected Class currentLoadedClass();

このメソッドは currentClassLoader と同様の方法で修正されました。その時点でのセキュリティーコンテキストに AllPermission が与えられているか、スタック上のすべてのメソッド (存在する場合は、特権を持つ最初の呼び出し元まで) がシステムクラスローダまたはその上位クラスの 1 つを使って定義されたクラスからのものである場合には、null を返します。

このメソッドは推奨されなくなりました。代わりに checkPermission を使用してください。

protected int classDepth(String name);

動作に変更はありません。このメソッドは推奨されなくなりました。代わりに checkPermission を使用してください。

protected int classLoaderDepth();

このメソッドは currentClassLoader と同様の方法で修正されました。その時点でのセキュリティーコンテキストに AllPermission が与えられているか、スタック上のすべてのメソッド (存在する場合は、特権を持つ最初の呼び出し元まで) がシステムクラスローダまたはその祖先の 1 つを使って定義されたクラスからのものである場合には、-1 を返します。

このメソッドは推奨されなくなりました。代わりに checkPermission を使用してください。

protected boolean inClass(String name);

動作に変更はありません。このメソッドは推奨されなくなりました。代わりに checkPermission を使用してください。

protected boolean inClassLoader();

このメソッドは、currentClassLoader が null 以外のクラスローダを返す場合には、true を返します。そのため、このメソッドは currentClassLoader と同じセマンティクスに従います。

このメソッドは推奨されなくなりました。代わりに checkPermission を使用してください。

public Object getSecurityContext();

このメソッドは、java.security.AccessController.getContext への呼び出しとともに作成された java.security.AccessControlContext オブジェクトを返します。JDK 1.1 では、このメソッドはデフォルトで null を返していました。

public void checkPermission(Permission perm);

これは、JDK に新しく追加されたメソッドです。指定されたアクセス権で java.security.AccessController.checkPermission を呼び出します。内部的には、JDK は直接 AccessController を呼び出さずに、常に SecurityManager.checkPermission を呼び出します。このため、プログラマはこのメソッドをオーバーライドして、監査や GUI ダイアログのような機能を追加することができます。

public void checkPermission(Permission perm, Object context);

これは、JDK に新しく追加されたメソッドです。contextAccessControlContext のインスタンスである場合は、AccessControlContext.checkPermission メソッドが、指定されたアクセス権に従って呼び出されます。

contextAccessControlContext のインスタンスでない場合は、SecurityException がスローされます。

public void checkCreateClassLoader();

このメソッドは修正されました。checkPermissionRuntimePermission("createClassLoader") アクセス権で呼び出します。

このメソッドをオーバーライドする場合は、オーバーライドされたメソッドが通常は例外をスローする位置で、super.checkCreateClassLoader への呼び出しを行う必要があります。例を示します。

  public class MySecurityManager extends SecurityManager {

    public void checkCreateClassLoader() {
      if (someCustomSecurityCheckFails()) {
        super.checkCreateClassLoader();
      }
    }
  }

public void checkAccess(Thread t);

スレッドの引数がシステムスレッド (親が null であるスレッドグループに属するスレッド) の場合、このメソッドは RuntimePermission("modifyThread") アクセス権で checkPermission を呼び出します。

より厳しいポリシーが必要なアプリケーションでは、このメソッドをオーバーライドする必要があります。

このメソッドをオーバーライドする場合は、オーバーライド後のメソッドの最初のステートメントで super.checkAccess メソッドを呼び出すか、同様のセキュリティーチェックを行う必要があります。

このメソッドをオーバーライドする場合は、オーバーライド後のメソッドでは、呼び出し元のスレッドが RuntimePermission("modifyThread") アクセス権を持つかどうかをチェックして、持っている場合には何もせずに終了するようにします。これは、そのアクセス権を与えられたコード (JDK 自体など) がどんなスレッドでも扱えるようにするためです。

例を示します。

  public class MySecurityManager extends SecurityManager {

    public void checkAccess(Thread t) {
      // a call to super will throw an exception if someone
      // is trying to modify a system thread
      super.checkAccess(t);
      ...
      if (someCustomSecurityCheckForOtherThreadsFails()) {
        // if the check fails, instead of throwing an exception,
        // call checkPermission, which will throw an exception
        // if need be
        checkPermission(new RuntimePermission("modifyThread"));  
      }
      ...
    }
  }

public void checkAccess(ThreadGroup g);

スレッドグループの引数がシステムスレッドグループ (親が null) の場合、このメソッドは、RuntimePermission("modifyThreadGroup") アクセス権で checkPermission を呼び出します。

より厳しいポリシーが必要なアプリケーションでは、このメソッドをオーバーライドする必要があります。

このメソッドをオーバーライドする場合は、オーバーライド後のメソッドの最初のステートメントで super.checkAccess メソッドを呼び出すか、同様のセキュリティーチェックを行う必要があります。

このメソッドをオーバーライドする場合は、オーバーライド後のメソッドでは、呼び出し元のスレッドが RuntimePermission("modifyThreadGroup") アクセス権を持つかどうかをチェックして、持っている場合には何もせずに終了するようにします。これは、そのアクセス権を与えられたコード (JDK 自体など) がどんなスレッドグループでも扱えるようにするためです。

例を示します。

  public class MySecurityManager extends SecurityManager {

    public void checkAccess(ThreadGroup g) {
      // a call to super will throw an exception if someone
      // is trying to modify the system thread group
      super.checkAccess(g);
      ...
      if (someCustomSecurityCheckForOtherThreadGroupsFails()) {
        // if the check fails, instead of throwing an exception,
        // call checkPermission, which will throw an exception
        // if need be
        checkPermission(new RuntimePermission("modifyThreadGroup"));  
      }
      ...
    }
  }

public void checkExit(int status);

このメソッドは修正されました。checkPermissionRuntimePermission("exitVM") アクセス権で呼び出します。

このメソッドをオーバーライドする場合は、オーバーライドされたメソッドが通常は例外をスローする位置で、super.checkExit への呼び出しを行う必要があります。例を示します。

  public class MySecurityManager extends SecurityManager {

    public void checkExit(int status) {
      if (someCustomSecurityCheckFails()) {
        super.checkExit(status);
      }
    }
  }

public void checkExec(String cmd);

このメソッドは修正されました。checkPermissionFilePermission で呼び出します。cmd が絶対パス (java.io.File.isAbsolute を参照) の場合は、FilePermission のターゲットとしてそのまま渡されます。cmd が絶対パスでない場合は、特別なターゲット "<<ALL FILES>>" が使用されます。このターゲットを使用する理由は、個別のプラットフォームで実行されるコマンドの実際のパスを判断するのは、環境変数などの要因のために困難なためです。

このメソッドをオーバーライドする場合は、オーバーライドされたメソッドが通常は例外をスローする位置で、super.checkExec への呼び出しを行う必要があります。例を示します。

  public class MySecurityManager extends SecurityManager {

    public void checkExec(String cmd) {
      if (someCustomSecurityCheckFails()) {
        super.checkExec(cmd);
      }
    }
  }

public void checkLink(String lib);

このメソッドは修正されました。checkPermissionRuntimePermission("loadLibrary."+lib) アクセス権で呼び出します。

このメソッドをオーバーライドする場合は、オーバーライドされたメソッドが通常は例外をスローする位置で、super.checkLink への呼び出しを行う必要があります。例を示します。

  public class MySecurityManager extends SecurityManager {

    public void checkLink(String lib) {
      if (someCustomSecurityCheckFails()) {
        super.checkLink(lib);
      }
    }
  }

public void checkRead(FileDescriptor fd);

このメソッドは修正されました。checkPermissionRuntimePermission("readFileDescriptor") アクセス権で呼び出します。

このメソッドをオーバーライドする場合は、オーバーライドされたメソッドが通常は例外をスローする位置で、super.checkRead への呼び出しを行う必要があります。例を示します。

  public class MySecurityManager extends SecurityManager {

    public void checkRead(FileDescriptor fd) {
      if (someCustomSecurityCheckFails()) {
        super.checkRead(fd);
      }
    }
  }

public void checkRead(String file);

このメソッドは修正されました。checkPermissionFilePermission(file,"read") アクセス権で呼び出します。

このメソッドをオーバーライドする場合は、オーバーライドされたメソッドが通常は例外をスローする位置で、super.checkRead への呼び出しを行う必要があります。例を示します。

  public class MySecurityManager extends SecurityManager {

    public void checkRead(String file) {
      if (someCustomSecurityCheckFails()) {
        super.checkRead(file);
      }
    }
  }

public void checkRead(String file, Object context);

このメソッドは修正されました。contextAccessControlContext のインスタンスである場合は、AccessControlContext.checkPermission メソッドが、FilePermission(file,"read") のアクセス権に従って呼び出されます。

contextAccessControlContext のインスタンスでない場合は、SecurityException がスローされます。

このメソッドをオーバーライドする場合は、オーバーライドされたメソッドが通常は例外をスローする位置で、super.checkRead への呼び出しを行う必要があります。例を示します。

  public class MySecurityManager extends SecurityManager {

    public void checkRead(String file, Object context) {
      if (someCustomSecurityCheckFails()) {
        super.checkRead(file, context);
      }
    }
  }

public void checkWrite(FileDescriptor fd);

このメソッドは修正されました。checkPermissionRuntimePermission("writeFileDescriptor") アクセス権で呼び出します。

このメソッドをオーバーライドする場合は、オーバーライドされたメソッドが通常は例外をスローする位置で、super.checkWrite への呼び出しを行う必要があります。次に例を示します。

  public class MySecurityManager extends SecurityManager {

    public void checkWrite(FileDescriptor fd) {
      if (someCustomSecurityCheckFails()) {
        super.checkWrite(fd);
      }
    }
  }

public void checkWrite(String file);

このメソッドは修正されました。checkPermissionFilePermission(file,"write") アクセス権で呼び出します。

このメソッドをオーバーライドする場合は、オーバーライドされたメソッドが通常は例外をスローする位置で、super.checkWrite への呼び出しを行う必要があります。例を示します。

  public class MySecurityManager extends SecurityManager {

    public void checkWrite(String file) {
      if (someCustomSecurityCheckFails()) {
        super.checkWrite(file);
      }
    }
  }

public void checkDelete(String file);

このメソッドは修正されました。checkPermissionFilePermission(file,"delete") アクセス権で呼び出します。

このメソッドをオーバーライドする場合は、オーバーライドされたメソッドが通常は例外をスローする位置で、super.checkDelete への呼び出しを行う必要があります。例を示します。

  public class MySecurityManager extends SecurityManager {

    public void checkDelete(String file) {
      if (someCustomSecurityCheckFails()) {
        super.checkDelete(file);
      }
    }
  }

public void checkConnect(String host, int port);

このメソッドは修正されました。ポートが -1 でない場合には、checkPermissionSocketPermission(host+":"+port,"connect") アクセス権で呼び出します。ポートが -1 の場合は、checkPermissionSocketPermission(host,"resolve") アクセス権で呼び出します。

この動作には JDK 1.1 との一貫性があり、ポートが -1 である場合は、IP アドレスのルックアップが行われていることを示します。

このメソッドをオーバーライドする場合は、オーバーライドされたメソッドが通常は例外をスローする位置で、super.checkConnect への呼び出しを行う必要があります。例を示します。

  public class MySecurityManager extends SecurityManager {

    public void checkConnect(String host, int port) {
      if (someCustomSecurityCheckFails()) {
        super.checkConnect(host, port);
      }
    }
  }

public void checkConnect(String host, int port, Object context);

このメソッドは修正されました。contextAccessControlContext のインスタンスである場合は、ポートが -1 に等しくないときには、AccessControlContext.checkPermission メソッドが SocketPermission(host+":"+port,"connect") アクセス権で呼び出されます。ポートが -1 に等しいときは、checkPermissionSocketPermission(host,"resolve") のアクセス権に従って呼び出されます。

contextAccessControlContext のインスタンスでない場合は、SecurityException がスローされます。

このメソッドをオーバーライドする場合は、オーバーライドされたメソッドが通常は例外をスローする位置で、super.checkConnect への呼び出しを行う必要があります。例を示します。

  public class MySecurityManager extends SecurityManager {

    public void checkConnect(String host, int port, Object context) {
      if (someCustomSecurityCheckFails()) {
        super.checkConnect(host, port, context);
      }
    }
  }

public void checkListen(int port)

このメソッドは修正されました。ポートが 0 でない場合は、checkPermissionSocketPermission("localhost:"+port,"listen") で呼び出します。ポートが 0 の場合は、checkPermissionSocketPermission("localhost:1024-","listen") で呼び出します。

このメソッドをオーバーライドする場合は、オーバーライドされたメソッドが通常は例外をスローする位置で、super.checkListen への呼び出しを行う必要があります。例を示します。

  public class MySecurityManager extends SecurityManager {

    public void checkListen(int port) {
      if (someCustomSecurityCheckFails()) {
        super.checkListen(port);
      }
    }
  }

public void checkAccept(String host, int port);

このメソッドは修正されました。checkPermissionSocketPermission(host+":"+port,"accept") アクセス権で呼び出します。

このメソッドをオーバーライドする場合は、オーバーライドされたメソッドが通常は例外をスローする位置で、super.checkAccept への呼び出しを行う必要があります。例を示します。

  public class MySecurityManager extends SecurityManager {

    public void checkAccept(String host, int port) {
      if (someCustomSecurityCheckFails()) {
        super.checkAccept(host, port);
      }
    }
  }

public void checkMulticast(InetAddress maddr);

このメソッドは修正されました。checkPermissionSocketPermission(maddr.getHostAddress(),"accept,connect") アクセス権で呼び出します。

このメソッドをオーバーライドする場合は、オーバーライドされたメソッドが通常は例外をスローする位置で、super.checkMulticast への呼び出しを行う必要があります。例を示します。

  public class MySecurityManager extends SecurityManager {

    public void checkMultiCast(InetAddress maddr) {
      if (someCustomSecurityCheckFails()) {
        super.checkMultiCast(maddr);
      }
    }
  }

public void checkMulticast(InetAddress maddr, byte ttl);

このメソッドは修正されました。checkPermissionSocketPermission(maddr.getHostAddress(),"accept,connect") アクセス権で呼び出します。

このメソッドをオーバーライドする場合は、オーバーライドされたメソッドが通常は例外をスローする位置で、super.checkMulticast への呼び出しを行う必要があります。例を示します。

  public class MySecurityManager extends SecurityManager {

    public void checkMultiCast(InetAddress maddr, byte ttl) {
      if (someCustomSecurityCheckFails()) {
        super.checkMultiCast(maddr, ttl);
      }
    }
  }

public void checkPropertiesAccess();

このメソッドは修正されました。checkPermissionPropertyPermission("*", "read,write") アクセス権で呼び出します。

このメソッドをオーバーライドする場合は、オーバーライドされたメソッドが通常は例外をスローする位置で、super.checkPropertiesAccess への呼び出しを行う必要があります。例を示します。

  public class MySecurityManager extends SecurityManager {

    public void checkPropertiesAccess() {
      if (someCustomSecurityCheckFails()) {
        super.checkPropertiesAccess();
      }
    }
  }

public void checkPropertyAccess(String key);

このメソッドは修正されました。checkPermissionPropertyPermission(key, "read") アクセス権で呼び出します。

このメソッドをオーバーライドする場合は、オーバーライドされたメソッドが通常は例外をスローする位置で、super.checkPropertyAccess への呼び出しを行う必要があります。例を示します。

  public class MySecurityManager extends SecurityManager {

    public void checkPropertyAccess(String key) {
      if (someCustomSecurityCheckFails()) {
        super.checkPropertiesAccess(key);
      }
    }
  }

public boolean checkTopLevelWindow(Object window);

このメソッドは修正されました。checkPermissionAWTPermission("showWindowWithoutWarningBanner") アクセス権で呼び出し、SecurityException がスローされない場合は true を返します。それ以外の場合は false を返します。

このメソッドをオーバーライドする場合は、オーバーライドされたメソッドが通常 false を返す位置で、super.checkTopLevelWindow への呼び出しを行い、super.checkTopLevelWindow の値を返す必要があります。例を示します。

  public class MySecurityManager extends SecurityManager {

    public void checkTopLevelWindow(Object window) {
      if (someCustomSecurityCheckFails()) {
        return super.checkTopLevelWindow(window);
      } else {
        return true;
      }
    }
  }

public void checkPrintJobAccess();

このメソッドは修正されました。checkPermissionRuntimePermission("queuePrintJob") アクセス権で呼び出します。

このメソッドをオーバーライドする場合は、オーバーライドされたメソッドが通常は例外をスローする位置で、super.checkPrintJobAccess への呼び出しを行う必要があります。例を示します。

  public class MySecurityManager extends SecurityManager {

    public void checkPrintJobAccess() {
      if (someCustomSecurityCheckFails()) {
        super.checkPrintJobAccess();
      }
    }
  }

public void checkSystemClipboardAccess();

このメソッドは修正されました。checkPermissionAWTPermission("accessClipboard") アクセス権で呼び出します。

このメソッドをオーバーライドする場合は、オーバーライドされたメソッドが通常は例外をスローする位置で、super.checkSystemClipboardAccess への呼び出しを行う必要があります。例を示します。

  public class MySecurityManager extends SecurityManager {

    public void checkSystemClipboardAccess() {
      if (someCustomSecurityCheckFails()) {
        super.checkSystemClipboardAccess();
      }
    }
  }

public void checkAwtEventQueueAccess();

このメソッドは修正されました。checkPermissionAWTPermission("accessEventQueue") アクセス権で呼び出します。

このメソッドをオーバーライドする場合は、オーバーライドされたメソッドが通常は例外をスローする位置で、super.checkAwtEventQueueAccess への呼び出しを行う必要があります。例を示します。

  public class MySecurityManager extends SecurityManager {

    public void checkAwtEventQueueAccess() {
      if (someCustomSecurityCheckFails()) {
        super.checkAwtEventQueueAccess();
      }
    }
  }

public void checkPackageAccess(String pkg);

このメソッドは修正されました。最初に、java.security.Security.getProperty("package.access") を呼び出してコンマで区切られたリストを取得することにより、制限付きのパッケージのリストを得ます。次に、pkg が制限付きパッケージのどれかで開始するかどうか、または等しいかどうかをチェックします。該当する場合には、checkPermissionRuntimePermission("accessClassInPackage."+pkg) アクセス権で呼び出されます。

このメソッドをオーバーライドする場合は、オーバーライドされたメソッドの 1 行目で、super.checkPackageAccess への呼び出しを行う必要があります。例を示します。

  public class MySecurityManager extends SecurityManager {

    public void checkPackageAccess(String pkg) {
      super.checkPackageAccess(pkg);
      ...
      someCustomSecurityCheck();
      ...
    }
  }

public void checkPackageDefinition(String pkg);

このメソッドは修正されました。最初に、java.security.Security.getProperty("package.definition") を呼び出してコンマで区切られたリストを取得することにより、制限付きのパッケージのリストを得ます。次に、pkg が制限付きパッケージのどれかで開始するかどうか、または等しいかどうかをチェックします。該当する場合には、checkPermissionRuntimePermission("defineClassInPackage."+pkg) アクセス権で呼び出されます。

このメソッドをオーバーライドする場合は、オーバーライドされたメソッドの 1 行目で、super.checkPackageDefinition への呼び出しを行う必要があります。例を示します。

  public class MySecurityManager extends SecurityManager {

    public void checkPackageDefinition(String pkg) {
      super.checkPackageDefinition(pkg);
      ...
      someCustomSecurityCheck();
      ...
    }
  }

public void checkSetFactory();

このメソッドは修正されました。checkPermissionRuntimePermission("setFactory") アクセス権で呼び出します。

このメソッドをオーバーライドする場合は、オーバーライドされたメソッドが通常は例外をスローする位置で、super.checkSetFactory への呼び出しを行う必要があります。例を示します。

  public class MySecurityManager extends SecurityManager {

    public void checkSetFactory() {
      if (someCustomSecurityCheckFails()) {
        super.checkSetFactory();
      }
    }
  }

public void checkMemberAccess(Class clazz, int which);

このメソッドは修正されました。デフォルトのポリシーは PUBLIC メンバーへのアクセスおよび、呼び出し元と同じクラスローダを持つクラスへのアクセスを許可します。それ以外の場合はすべて、checkPermissionRuntimePermission("accessDeclaredMembers") アクセス権で呼び出されます。

このメソッドをオーバーライドする場合は、super.checkMemberAccess への呼び出しは行えません。checkMemberAccess のデフォルト実装は、スタック深度 4 にあることをチェックされるコードに依存します。次に例を示します。

     someCaller[3]
     java.lang.Class.someReflectionAPI [2]
     java.lang.Class.checkMemberAccess [1]
     SecurityManager.checkMemberAccess [0]
この動作をエミュレートするには、getClassContext を呼び出し、デフォルトの checkMemberAccess メソッドの場合と同様に、インデックス 3 のクラスのクラスローダを調べる必要があります。
  if (which != Member.PUBLIC) {
    Class stack[] = getClassContext();
    /*
     * stack depth of 4 should be the caller of one of the
     * methods in java.lang.Class that invoke checkMember
     * access. The stack should look like:
     * 
     * someCaller [3]
     * java.lang.Class.someReflectionAPI  [2]
     * java.lang.Class.checkMemberAccess [1]
     * MySecurityManager.checkMemberAccess [0]
     *
     */
    if ((stack.length<4) || 
      (stack[3].getClassLoader() != clazz.getClassLoader())) {
      if (checkMemberAccessPermission == null)
        checkMemberAccessPermission = 
          new RuntimePermission("accessDeclaredMembers");
      checkPermission(checkMemberAccessPermission);
    }
  }

このメソッドは、JDK で現在でも呼び出し元の深度に基づいている唯一のセキュリティーマネージャーメソッドです。このメソッドが存在する理由は、呼び出し元が、自分と同じクラスローダからのクラスに反映できるようにするためです。

public void checkSecurityAccess(String target);

このメソッドは修正されました。指定されたアクセス権ターゲット名に対する SecurityPermission オブジェクトを作成し、そのアクセス権で checkPermission を呼び出します。

このメソッドをオーバーライドする場合は、オーバーライドされたメソッドが通常は例外をスローする位置で、super.checkSecurityAccess への呼び出しを行う必要があります。例を示します。

  public class MySecurityManager extends SecurityManager {

    public void checkSecurityAccess(String target) {
      if (someCustomSecurityCheckFails()) {
        super.checkSecurityAccess(target);
      }
    }
  }

public ThreadGroup getThreadGroup();

このメソッドは修正されていません。


Copyright © 1997-2001 Sun Microsystems, Inc. All Rights Reserved.

コメントの送付先: java-security@sun.com。これは購読リストではありません。
Sun
Java Software