Java アプリケーション環境のポリシーは、さまざまなソースを出所とするコードがどのようなアクセス権を使用できるかを指定するもので、Policy オブジェクトによって表されます。具体的には、Policy
クラス (java.security
パッケージ内) で定義されている抽象メソッドを実装した Policy
サブクラスによって表されます。
Policy オブジェクトが使用するポリシー情報がどこに置かれるかは、Policy の実装によります。デフォルトの Policy の実装では、ポリシー情報を静的なポリシー構成ファイルから得ます。Policy Tool を使った (構文を知る必要のない) ポリシーファイルの作成方法の詳細については、Policy Tool のドキュメント (Solaris 用) (Windows 用) を参照してください。
この文書では、次の内容について説明します。
デフォルトの 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」という名前のシステムプロパティの値で、JDK のインストール先ディレクトリを指定します。
システムのポリシーファイルは、システム全体に渡ってコードにアクセス権を与えます。JDK に含まれている
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:¥WindowsPolicy が初期化されると、まずシステムポリシーがロードされ、次に、ロードされたシステムポリシーにユーザポリシーが追加されます。どちらのポリシーも存在しない場合は、組み込みポリシーが使われます。組み込みポリシーは、オリジナルの sandbox ポリシーと同じものです。
ポリシーファイルの場所は、セキュリティプロパティファイルの中で指定されています。セキュリティプロパティファイルは、次の場所にあります。
前述のように、java.home は JDK がインストールされているディレクトリを表しています。ポリシーファイルの場所は、次のような形式の名前を持つプロパティの値として指定されています。java.home/lib/security/java.security (Solaris) java.home¥lib¥security¥java.security (Windows)n は数字です。以下の形式の行で、このようなプロパティの値を指定します。policy.url.nURL では URL を指定します。policy.url.n=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 SomeAppsomeURL は、ポリシーファイルの場所を示す URL です。この例では、セキュリティプロパティファイルで指定されたすべてのポリシーファイルに加えて、someURL で指定されたポリシーファイルがロードされます。注:
- 次に示すとおり、URL は 通常の URL でも、単純に現在のディレクトリのポリシーファイルの名前でもかまいません。
java -Djava.security.manager -Djava.security.policy=mypolicy WriteFile
- -Djava.security.manager 引数によってデフォルトセキュリティマネージャがインストールされるので、このアプリケーションに対してはポリシーのチェックが行われます。アプリケーション SomeApp がセキュリティマネージャをインストールする場合は、-Djava.security.manager 引数を指定する必要はありません。
次のように指定することもできます。
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 抽象クラスのサブクラスを作成し、
getPermissions
メソッド (必要に応じてその他のメソッドも) を実装します。セキュリティプロパティファイル (JDK の
lib/security
ディレクトリのjava.security
ファイル) を編集すれば、デフォルトの Policy の実装を変更できます。
java.security
で設定できるプロパティの例を次に示します。policy.provider=PolicyClassNamePolicyClassName には、目的の Policy 実装クラスを完全修飾名で指定します。デフォルトのセキュリティプロパティファイルでは、このプロパティは次のように指定されています。
policy.provider=sun.security.provider.PolicyFileカスタマイズするには、次のように、このプロパティに別のクラスを指定します。
policy.provider=com.mycom.MyPolicy
インストールした JDK のポリシー構成ファイルでは、指定されたコードソースからのコードに対し、どのようなアクセス権 (システムリソースへのアクセスの種類) を与えるかを指定します。
アプレット (またはセキュリティマネージャの下で動作しているアプリケーション) が、ファイルの読み書きなど、セキュリティ保護された操作を行うためには、その操作を行うためのアクセス権が与えられていなければなりません。デフォルトの Policy の実装では、ポリシー構成ファイルの付与エントリによって、そのアクセス権を与えなければなりません。詳しくは、下の説明と「Java セキュリティアーキテクチャ」を参照してください。ただし、同じ (URL の) 場所にあるファイルと、その場所のサブディレクトリにあるファイルの読み取りアクセス権は、常に自動的に与えられます。したがって、そのようなアクセス権については、明示的に指定する必要はありません。
ポリシー構成ファイルは、エントリのリストで構成されます。ポリシー構成ファイルはキーストアエントリを 1 つ含むことができ、0 個以上の「付与」エントリを含みます。
キーストアエントリ
キーストアは、非公開鍵と、対応する公開鍵を認証する X.509 証明書などのデジタル証明書が格納されたデータベースです。キーストアの作成と管理には、keytool ユーティリティ (Solaris 用)、(Windows 用) を使います。ポリシー構成ファイルで指定されたキーストアは、ポリシー構成ファイルの付与エントリで指定された署名者の公開鍵を参照するときに使われます。署名者の別名を指定している付与エントリがある場合は、ポリシー構成ファイルでキーストアを指定する必要があります (下の説明を参照)。
現在、ポリシーファイルで指定できるキーストアエントリは 1 つだけで、2 つ目以降のキーストアエントリは無視されます。キーストアエントリは、ポリシーファイルの付与エントリの外であれば、どこに指定してもかまいません。キーストアエントリの構文を次に示します。
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/.keystoreURL に絶対位置を指定することもできます。キーストアのタイプは、キーストア情報の格納形式とデータ形式を定義するとともに、キーストア内の非公開鍵とキーストア自体の完全性を保護するために使われるアルゴリズムを定義します。米国 Sun Microsystems, Inc. がサポートしているデフォルトのキーストアのタイプは、「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 ○ java.sun.com/people/gong/ java.sun.com/people/gong/ ○ java.sun.com/people/gong/ java.sun.com/people/gong/* ○ java.sun.com/people/gong/ java.sun.com/people/gong/- ○ java.sun.com/people/gong/appl.jar java.sun.com/people/gong/ × java.sun.com/people/gong/appl.jar java.sun.com/people/gong/- ○ java.sun.com/people/gong/appl.jar java.sun.com/people/gong/* ○ java.sun.com/people/gong/appl.jar java.sun.com/people/- ○ java.sun.com/people/gong/appl.jar java.sun.com/people/* × java.sun.com/people/gong/ java.sun.com/people/- ○ java.sun.com/people/gong/ java.sun.com/people/* × アクセス権エントリ
permission entry は、
permission
で始まります。先に示したテンプレートのpermission_class_name
の部分には、実際には、java.io.FilePermission
やjava.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 が与えられます。システムクラスはポリシーによる制限を受けません。アクセス権エントリの各項目は、指定の順序 (
permission
、permission_class_name、"target_name"、"action"、およびsignedBy
"signer_names") で指定しなければなりません。各エントリはセミコロンで終わります。識別子 (
permission
、signedBy
、codeBase
など) では大文字と小文字は区別されませんが、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 プロパティを追加したりできることを示しています。
- ローカルファイルシステムの「/home/sysadmin/」ディレクトリにある、署名された JAR ファイルからコードがロードされた
- 署名が、キーストア内の別名 sysadmin によって参照される公開鍵で認証される
コードソースを指定する要素は、どちらも (または両方を) 省略可能です。
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/ ディレクトリの下に置かれたコードは、プロバイダの追加と削除が行えます。コードに署名は必要ありません。
codeBase
とsignedBy
を両方とも省略した例を次に示します。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.2
に設定されている場合でも、次のように変換されます。grant codeBase "file:C:/jdk1.2/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 "${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} プロパティが展開され、「user.home」の値がC:¥users¥cathy
であるとすると、最終的には次のようになります。"C:¥users¥cathy¥foo.bat"もちろん、プラットフォームに依存しないために、次のように、明示的にスラッシュを使うのではなく ${/} を使うようにした方が望ましいといえます。"${user.home}${/}foo.bat"
- JDK 1.2 におけるアクセス権
- Policy Tool (Solaris 用) (Windows 用)
Copyright © 1997-98 Sun Microsystems, Inc. All Rights Reserved. コメントの送付先: java-security@java.sun.com これは購読リストではありません。 |
![]() Java ソフトウェア |