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

最終更新日: 1998 年 10 月 30 日

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

Policy オブジェクトが使用するポリシー情報がどこに置かれるかは、Policy の実装によります。デフォルトの Policy の実装では、ポリシー情報を静的なポリシー構成ファイルから得ます。 このドキュメントでは、デフォルトの Policy の実装と、それによって読み取られるポリシーファイルで使用する構文について説明します。 Policy Tool を使った (構文を知る必要のない) ポリシーファイルの作成方法の詳細については、Policy Tool のドキュメント (Solaris 用) (Windows 用) を参照してください。

このドキュメントでは、次の内容について説明します。

デフォルトの Policy の実装
ポリシーファイルのデフォルトの場所
ポリシーの実装の変更
ポリシーファイルの構文
ポリシーファイルの例
ポリシーファイルにおけるプロパティの展開
関連ドキュメント

デフォルトの Policy の実装

デフォルトの Policy の実装では、1 つまたは複数のポリシー構成ファイルからポリシーを指定できます。ポリシー構成ファイルでは、指定されたコードソースからのコードに対し、どのようなアクセス権を与えるかを指定します。

ポリシーファイルは、単純なテキストエディタ、またはグラフィカルな Policy Tool ユーティリティを使って作成できます。

デフォルトでは、システム全体のポリシーファイルが 1 つと、ユーザポリシーファイル (オプション) が 1 つ存在します。

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

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

前述したように、デフォルトでは、システム全体のポリシーファイルが 1 つと、ユーザポリシーファイルが 1 つ存在します。

システムポリシーファイルは、デフォルトでは次の場所にあります。

java.home/lib/security/java.policy  (Solaris)
java.home\lib\security\java.policy  (Windows)

注: java.home は、「java.home」という名前のシステムプロパティの値で、実行環境の格納先ディレクトリ (Java 2 SDK の jre ディレクトリ、または Java 2 Runtime Environment の最上位ディレクトリ) を指します。

システムのポリシーファイルは、システム全体に渡ってコードにアクセス権を与えます。SDK に含まれている java.policy ファイルは、標準拡張機能にすべてのアクセス権を与え、ユーザが特権のないポートで待機したり、「os.name」プロパティや「file.separator」プロパティなどの任意のコードがセキュリティにかかわらない特定の「標準」プロパティを読み込んだりすることを許可します。

ユーザポリシーファイルは、デフォルトでは次の場所にあります。

user.home/.java.policy  (Solaris)
user.home\.java.policy  (Windows)

注: user.home は「user.home」という名前のシステムプロパティの値で、ユーザのホームディレクトリを指定します。Windows のシステムでは、ユーザ名が「uName」の場合、user.homeプロパティの値はデフォルトでは次のように設定されます。

マルチユーザ Windows NT システムでは C:\Winnt\Profiles\uName
マルチユーザ Windows 95 システムでは C:\Windows\Profiles\uName
シングルユーザ Windows 95 システムでは C:\Windows

Policy が初期化されると、まずシステムポリシーがロードされ、次に、ロードされたシステムポリシーにユーザポリシーが追加されます。どちらのポリシーも存在しない場合は、組み込みポリシーが使われます。組み込みポリシーは、オリジナルのサンドボックス (sandbox) ポリシーと同じものです。

ポリシーファイルの場所は、セキュリティプロパティファイルの中で指定されています。 セキュリティプロパティファイルは、次の場所にあります。

java.home/lib/security/java.security  (Solaris)
java.home\lib\security\java.security  (Windows)
前述のように、java.home は 実行環境の格納先ディレクトリ (Java 2 SDK の jre ディレクトリ、または Java 2 Runtime Environment の最上位ディレクトリ) を指します。 ポリシーファイルの場所は、次のような形式の名前を持つプロパティの値として指定されています。
policy.url.n
n は数字です。次に示す形式の行で、それぞれのプロパティの値を指定します。
policy.url.n=URL
ここで、URL は URL の指定を表します。

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

policy.url.1=file:${java.home}/lib/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.1 と policy.url.3 がある場合、policy.url.3 は読み込まれません。

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

アプリケーションを実行するときに、追加のポリシーファイルや別のポリシーファイルを指定することもできます。 この場合は、-Djava.security.policy コマンド行引数を使って java.security.policy プロパティの値を設定します。たとえば、次のように指定します。

    java -Djava.security.manager -Djava.security.policy=someURL SomeApp
someURL は、ポリシーファイルの場所を示す URL です。 この例では、セキュリティプロパティファイルで指定されたすべてのポリシーファイルに加えて、someURL で指定されたポリシーファイルがロードされます。

注:

次のように指定することもできます。

    java -Djava.security.manager -Djava.security.policy==someURL SomeApp
等号が 2 つ使われていることに注意してください。 この場合は、指定されたポリシーファイルだけが使われ、セキュリティプロパティに示されたポリシーファイルはすべて無視されます。

ポリシーファイルを appletviewer (アプレットビューア) に渡す場合は、次のように -J-Djava.security.policy 引数を指定します。

    appletviewer -J-Djava.security.policy=someURL myApplet
注: セキュリティプロパティファイルで policy.allowSystemProperty プロパティに false が設定されている場合は、-Djava.security.policy のポリシーファイルの値は (java コマンドと appletviewer コマンドのどちらの場合も) 無視されます。policy.allowSystemProperty プロパティの既定値は true です。

ポリシーの実装の変更

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

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

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

    policy.provider=PolicyClassName

PolicyClassName には、目的の Policy 実装クラスを完全修飾名で指定します。デフォルトのセキュリティプロパティファイルでは、このプロパティは次のように指定されています。

    policy.provider=sun.security.provider.PolicyFile

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

   policy.provider=com.mycom.MyPolicy

ポリシーファイルの構文

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

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

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

キーストアエントリ

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

現在、ポリシーファイルで指定できるキーストアエントリは 1 つだけで、2 つ目以降のキーストアエントリは無視されます。 キーストアエントリは、ポリシーファイルの付与エントリの外であれば、どこに指定してもかまいません。keystore エントリの構文は次のとおりです。

    keystore "some_keystore_url", "keystore_type";
"some_keystore_url" にはキーストアの URL を指定し、"keystore_type" にはキーストアのタイプを指定します。

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

    policy.url.1=http://foo.bar.com/fum/some.policy
また、このポリシーファイルには、次のエントリがあるとします。
    keystore ".keystore";
この場合、キーストアは次の場所からロードされます。
    http://foo.bar.com/fum/.keystore
URL に絶対位置を指定することもできます。

キーストアのタイプは、キーストア情報の格納形式とデータ形式を定義するとともに、キーストア内の非公開鍵とキーストア自体の完全性を保護するために使われるアルゴリズムを定義します。Sun Microsystems がサポートするデフォルトのタイプは、Sun Microsystems に所有権があるキーストアタイプ名「JKS」です。したがって、キーストアのタイプが「JKS」であれば、キーストアエントリを指定する必要はありません。

付与エントリ

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

付与エントリには、省略可能な codeBase および signedBy の名前と値のペアのあとに、アクセス権を付与するコードを指定するいくつかの「アクセス権エントリ」が含まれます。 付与エントリの基本形式は、次のとおりです。

  grant signedBy "signer_names", codeBase "URL" {
    permission permission_class_name "target_name", "action", 
        signedBy "signer_names";
    ....
    permission permission_class_name "target_name", "action", 
        signedBy "signer_names";
  };
 	
上の形式でイタリック体になっていない項目は、示されているとおりに指定します。 ただし、大文字と小文字は区別されず、また、以降で説明するように、いくつかの項目は省略可能です。イタリックで示されている項目は、可変の項目です。

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

SignedBy および CodeBase フィールド

signedBy および codeBase の名前と値のペアは省略可能です。 また、これらのフィールドの順序は問われません。

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

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

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

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

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

    grant codeBase "file:/C:/somepath/api/" {
      ...
    }
codeBase の値の正確な意味は、末尾の文字によって変わります。末尾が「/」の codeBase は、指定されたディレクトリ内のすべてのクラスファイル (JAR ファイルでない) に一致します。末尾が「/*」の codeBase は、そのディレクトリ内にあるすべてのファイル (クラスファイルと JAR ファイルの両方) に一致します。末尾が「/-」の codeBase は、ディレクトリのすべてのファイル (クラスファイルと JAR ファイルの両方)、および再帰的にそのディレクトリのサブディレクトリにあるすべてのファイルを表します。次の表では、さまざまなケースを示します。

ダウンロードされたコードの codebase URL ポリシーの codebase URL 一致するかどうか
java.sun.com/people/gong/ java.sun.com/people/gong
Y
java.sun.com/people/gong/ java.sun.com/people/gong/
Y
java.sun.com/people/gong/ java.sun.com/people/gong/*
Y
java.sun.com/people/gong/ java.sun.com/people/gong/-
Y
java.sun.com/people/gong/appl.jar java.sun.com/people/gong/
N
java.sun.com/people/gong/appl.jar java.sun.com/people/gong/-
Y
java.sun.com/people/gong/appl.jar java.sun.com/people/gong/*
Y
java.sun.com/people/gong/appl.jar java.sun.com/people/-
Y
java.sun.com/people/gong/appl.jar java.sun.com/people/*
N
java.sun.com/people/gong/ java.sun.com/people/-
Y
java.sun.com/people/gong/ java.sun.com/people/*
N

アクセス権エントリ

permission entry は、permission で始まります。先に示したテンプレートの permission_class_name の部分には、実際には、java.io.FilePermissionjava.lang.RuntimePermission など、特定のアクセス権型を指定します。

java.io.FilePermission (どのような種類のファイルアクセスを許可するかを指定) など、多くのアクセス権型では、"action" が必須です。java.lang.RuntimePermission など、アクションの指定が必要でないアクセス権型では、"action" を指定する必要はありません。この場合は、permission_class_name のあとの "target_name" 値で指定されたアクセス権が与えられるか、アクセス権が与えられないかのどちらかになります。

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

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

この場合、アクセス権 Foo.class がある JAR ファイルに置かれていて、その JAR ファイルが別名 "FooSoft" により指定される証明書に含まれている公開鍵に対応する非公開鍵によって署名されているか、Foo.class がシステムクラスである場合に、このアクセス権型 Foo が与えられます。 システムクラスはポリシーによる制限を受けません。

アクセス権エントリの各項目は、指定の順序 (permissionpermission_class_name、"target_name"、"action"、および signedBy "signer_names") で指定しなければなりません。各エントリはセミコロンで終わります。

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

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

別のポリシー構成ファイルの例を次に示します。

  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.*";
  };
これは、次の条件を満たすコードだけが Security クラス内のメソッドを呼び出して、プロバイダの追加または削除を行なったり、Security プロパティを追加したりできることを示しています。

コードソースを指定する要素は、どちらも (または両方を) 省略可能です。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.*";
  };
この例では、コードソースを指定する要素がどちらも省略されています。 したがって、出所がどこか、署名が付いているか、誰の署名が付いているかに関係なく、どのコードでもプロバイダの追加と削除が行えます。

ポリシーファイルにおけるプロパティの展開

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

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

    ${some.property}
この文字列はシステムプロパティの値に展開されます。次に例を示します。
    permission java.io.FilePermission "${user.home}", "read";
この場合、"${user.home}" は、システムプロパティ 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 である場合、これは次のように変換されます。
    permission java.io.FilePermission "/home/cathy/*", "read";
一方、「user.home」 の値が C:\users\cathy で、プラットフォームが Windows である場合は、次のように変換されます。
    permission java.io.FilePermission "C:\users\cathy\*", "read";
また、特殊なケースとして、次のようにコードベースのプロパティを展開する場合は、file.separator 文字は自動的に / に変換されます。
    grant codeBase "file:${java.home}/lib/ext/"
したがって、Windows システムでは、「java.home」が C:\jdk1.3\jre に設定されている場合でも、次のように変換されます。
    grant codeBase "file:C:/jdk1.3/jre/lib/ext/"
したがって、コードベース文字列では ${/} を使う必要はありません。 また、使うべきではありません。

プロパティの展開は、ポリシーファイル内で、二重引用符で囲まれた文字列が使用できる場所であればどこでも行われます。プロパティの展開が行われる場所としては、"signer_names""URL""target_name""action" の各フィールドが挙げられます。

プロパティの展開が許可されるかどうかは、セキュリティプロパティファイル内の policy.expandProperties プロパティの値によって管理されています。このプロパティの値が true (デフォルト) の場合は、展開が許可されます。

注: 入れ子のプロパティは使用できません。次に例を示します。

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

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

    grant codeBase "${foo}" {
      permission ...;
      permission ...;
    };
次の場合は、permission Foo... エントリだけが無視されます。
    grant {
      permission Foo "${foo}";
      permission Bar;
    };
また次の場合は、keystore エントリが無視されます。
    keystore "${foo}";

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

関連ドキュメント


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

コメントの送付先: java-security@sun.com これはメーリングリストではありません。
Sun
Java ソフトウェア