1

次のスニペットについて考えてみます。

(この場合、OpenJDK 6b24-1.11.5-0ubuntu1〜12.10.1は、OracleとOpenJDKの両方のすべてのJVM 6および7が同じ動作をするため、無関係に見えます)

SocketPermission toCheck = new SocketPermission("www.google.ca", "resolve");

SocketPermission checker = new SocketPermission("*.ca:80", "connect");

System.out.println("Result: " + checker.implies(toCheck));

checker = new SocketPermission("*.1e100.net:80", "connect");

System.out.println("Result: " + checker.implies(toCheck));

私が得る結果は次のとおりです。

Result: false
Result: true

問題は、JVMが逆引き参照を実行して、アドレスが解決されたドメインと実際に一致することを確認することであると思われます。

www.google.caドメインを掘り下げると、次のことがわかります。

[rotty@rotty-desktop ~]$ dig www.google.ca ANY

; <<>> DiG 9.8.1-P1 <<>> www.google.ca ANY
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 48015
;; flags: qr rd ra; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;www.google.ca.         IN  ANY

;; ANSWER SECTION:
www.google.ca.      114 IN  A   74.125.226.55
www.google.ca.      114 IN  A   74.125.226.56
www.google.ca.      114 IN  A   74.125.226.63
www.google.ca.      74  IN  AAAA    2607:f8b0:400b:801::1018

;; Query time: 27 msec
;; SERVER: 127.0.1.1#53(127.0.1.1)
;; WHEN: Mon Jan 14 17:18:50 2013
;; MSG SIZE  rcvd: 107

さらに、結果の最初のアドレスを取得してDNSルックアップを実行すると、次のようになります。

[rotty@rotty-desktop ~]$ nslookup 74.125.226.55
Server:     127.0.1.1
Address:    127.0.1.1#53

Non-authoritative answer:
55.226.125.74.in-addr.arpa  name = yyz06s06-in-f23.1e100.net.

Authoritative answers can be found from:

これは問題を明確に示しているようです。権限のない逆引き参照は、ドメインに対して定義された最初の(この場合はローカリティによる)エイリアスを返します。

これは、指定されたドメイン名の基になるアドレスに解決される可能性のある潜在的なエイリアスを知り、宣言する必要があることを意味します。

なぜJVMはそのような一致を必要とするのでしょうか?「解決」プロセスが満たされるには、アドレスが実際に存在するという単純な検証で十分ではないでしょうか。アドレスには、可能な逆マッピングがいくつもある可能性があります。これは実際にどのように機能するでしょうか?

[更新]これが実際にデフォルトのJavaポリシー定義と同じように動作することを明確にするために、次の追加の例を検討してください。

Socket socket = new Socket("www.google.ca", 80);

socket.close();

上記に次のセキュリティポリシーを適用します。

grant {
    permission java.net.SocketPermission "*.ca:80", "connect";
    //permission java.net.SocketPermission "*.1e100.net:80", "connect";
};

プログラムを次のように実行します。

java -Djava.security.manager -Djava.security.policy=../security.policy Test

結果:

Exception in thread "main" java.security.AccessControlException: access denied ("java.net.SocketPermission" "www.google.ca" "resolve")
    at java.security.AccessControlContext.checkPermission(AccessControlContext.java:366)
    at java.security.AccessController.checkPermission(AccessController.java:560)
    at java.lang.SecurityManager.checkPermission(SecurityManager.java:549)
    at java.lang.SecurityManager.checkConnect(SecurityManager.java:1048)
    at java.net.InetAddress.getAllByName0(InetAddress.java:1203)
    at java.net.InetAddress.getAllByName(InetAddress.java:1127)
    at java.net.InetAddress.getAllByName(InetAddress.java:1063)
    at java.net.InetAddress.getByName(InetAddress.java:1013)
    at java.net.InetSocketAddress.<init>(InetSocketAddress.java:142)
    at java.net.Socket.<init>(Socket.java:208)
    at example.security.SocketSecurityExample.test(SocketSecurityExample.java:13)
    at example.security.SocketSecurityExample.main(SocketSecurityExample.java:9)

ポリシーファイルを次のように変更します。

grant {
    //permission java.net.SocketPermission "*.ca:80", "connect";
    permission java.net.SocketPermission "*.1e100.net:80", "connect";
};

コードが適切に実行されます。

4

1 に答える 1

-1

そのアクションは、接続時に JVM によって実行されません。実際のホスト名/IP アドレスを含む SocketPermission を構築し、「implies」を使用して、.policy ファイル内の権限がその権限を意味するかどうかを確認します。

于 2013-01-14T22:36:57.497 に答える