设置哪个权限,以避免使用 https-URLS 的 Security-Manager 出错?

Which permission to set, to avoid error with Security-Manager with https-URLS?

在面向客户的软件中,我们必须阅读给定的 URLs 来解析他们的内容。此外,客户需要激活 Tomcat-Security-Manager 以让 Java-Policies 控制程序的功能。

现在,读取 URLs 异常 "javax.net.ssl.SSLKeyException: RSA premaster secret error" 发生,但仅在特定条件下发生:

安全违规发生在 Java-Code 的某处,限制在我们的代码库中的 AllPermission 并不能阻止错误。

所以,有没有人有想法,为Java 6 设置哪个权限,以便它可以处理HTTPS?

其他信息:运行 在 tomcat 中,在带有 OpenJDK 的 Debian-Linux 上。

编辑:我将 Java-Param“-Djava.security.debug=access,failure”添加到变量 JAVA_OPTS 中的 Tomcats /etc/default/tomcat6。但是在日志中我没有其他消息。代码可能会在触发之前询问权限吗?

EDIT2:我找到了正确的位置并获得了完整的堆栈跟踪(删除了特定的客户部分):

javax.net.ssl.SSLKeyException: RSA premaster secret error

            at [...]
            at javax.security.auth.Subject.doAsPrivileged(Subject.java:537)
            at javax.security.auth.Subject.doAsPrivileged(Subject.java:537)
            at javax.security.auth.Subject.doAsPrivileged(Subject.java:537)
            at javax.security.auth.Subject.doAsPrivileged(Subject.java:537)
            at javax.security.auth.Subject.doAsPrivileged(Subject.java:537)
            at javax.security.auth.Subject.doAsPrivileged(Subject.java:537)
            at javax.security.auth.Subject.doAsPrivileged(Subject.java:537)
            at javax.security.auth.Subject.doAsPrivileged(Subject.java:537)
            at javax.security.auth.Subject.doAsPrivileged(Subject.java:537)
            at javax.security.auth.Subject.doAsPrivileged(Subject.java:537)
            at java.lang.Thread.run(Thread.java:701)
    Caused by: java.security.NoSuchAlgorithmException: SunTlsRsaPremasterSecret KeyGenerator not available
            at javax.crypto.KeyGenerator.<init>(KeyGenerator.java:141)
            at javax.crypto.KeyGenerator.getInstance(KeyGenerator.java:191)
            ... 14 more

EDIT3:到目前为止,我假设 Java-class URL 用于访问资源的内容。但这是不正确的。它使用来自 Grails-Code 的 Groovy-URL-object 和 getText()-method:

new URL(params.url).text

此行发生错误。它是 Grails 版本 2.2.4.

发现所有必需权限的简单方法是 运行 使用参数

-Djava.security.debug=access,failure

然后您将获得有关每次失败的安全访问、生效的保护域等的完整信息。

几条评论和 OP 确认解决方案(摘要)后的解决方案

根本原因是在多个位置存在 sunjce_provider.jar。这是在被建议为许多可能的根本原因之一之后被 OP 发现的(请参阅此答案的最后和评论线索)。根据 OP 的评论:

I have the sunjce_provider.jar in multiple directories. I tried to give all three locations for Java 6 the rights, although clearly only one is JAVA_HOME - and it worked. Somehow one of the other locations is used, although it isn't in the java.ext.dirs-property

因此,本案例的解决方案是确保该应用有权访问 sunjce_provider.jar

的正确副本

我把我原来的回答的要点和有助于诊断的评论留在下面,供以后发现的人使用

导致解决方案的原始答案和评论

  1. http 不会发生这种情况,因为您的 Web 应用程序(即此连接的客户端,即使它在 tomcat 中是 运行)不需要在此配置中生成密钥。

  2. 它仅在启用 SecurityManager 时发生,但在禁用或使用全局 AllPermission 时不会发生,这表明它是文件权限错误。这表明这不是密钥长度的问题(例如 mentioned here

其他 similar reports on the web 表示可能的根本原因是缺少 jar(通常引用 sunjce_provider.jar)。堆栈跟踪确认根本原因异常是 NoSuchAlgorithmException,其中 KeyGenerator 正在寻找算法 SunTlsRsaPremasterSecret 但找不到它。在你的情况下,因为这只发生在特定的 SecurityManager 配置中,它可能是一个 inaccessible jar(由于安全权限) .

我的猜测是您没有启用对正确目录的 grant codeBase 权限,该目录包含您的 RSA 密钥生成算法所需的 jar。我建议的做法是检查您的 webapp 和 JRE 目录结构,以找到运行时 jar 的保存位置,并确保它们在 catalina.policy.

中具有 granted 权限

在默认配置中——例如——你应该在某处看到

// These permissions apply to all shared system extensions
grant codeBase "file:${java.home}/jre/lib/ext/-" {
        permission java.security.AllPermission;
};

有关这意味着什么的详细信息,请参阅 tomcat 安全管理器“How To”的 this section。您需要检查一些事项 - 确保 ${java.home}/jre/lib/ext/ 是您的运行时 jar 所在的位置。如果不是 - 更改路径以指向正确的位置(它 它们在我的 OpenJDK 6 版本 - build 27 上的位置。特别是你应该在那里看到 sunjce_provider.jarsunpkcs11.jar。确保以上部分存在于您的策略文件中。

代码可能取决于您的网络应用程序中的某些 jar - 例如在 ${catalina.base}/path/to/your/webapp/WEB-INF/classes/ 中 - 在这种情况下,您需要授予对该目录的权限。


导致相同或相似症状的其他问题

  1. App being unabled find or accesssunpkcs11.jar也会报同样的错误信息(在Ubuntu+openjdk6+tomcat6系统上验证)。该 jar 的副本很可能也会。

  2. 检查 /etc/java-6-openjdk/security/java.security。它应该在那里列出提供者 - 检查那里是否有类似 security.provider.n = sun.security.pkcs11.SunPKCS11 的行 - 如果缺少该行,你也会收到此错误(在同一系统上验证)

  3. 这个Debian bug report讨论了运行在SecurityManager

    下jar的位置问题

调试评论

根据其他答案,您可以尝试将 -Djava.security.debug=access,failure 添加到 CATALINA_OPTS 或 catalina.sh 中的 JAVA_OPTS 以启用调试 - 应记录到 catalina.out 默认情况下(或在 catalina.sh 中通过 CATALINA_OUT 设置日志记录的任何地方。您应该会看到 SecurityManager 的输出。

您也可以尝试 -Djava.security.debug=all. You will get a huge catalina.out`,但您可以 grep 查找可能有帮助的词(例如“fail”!!!)


遵循堆栈跟踪中的代码

您的异常被抛出 here. Looking at how that exception could be thrown - this method must return null. It swallows Exceptions - which isn't nice and makes it hard to diagnose exactly which part of that code is failing. My money would be on this line - where canUseProvider() 可能 return false。这一切都指向提供者 jar 由于某种原因无法访问。

我假设您在输出中没有看到任何访问冲突,即使 -Djava.security.debug=access,failure 也是如此。您可以尝试 -Djava.security.debug=all,尽管这很可能只会产生更多不相关的日志记录。如果没有访问冲突,你 可能 在你的类路径上有两个版本的那个 jar 并且运行时正在访问(或试图访问一个错误)。 Q/A.

中描述了一个类似的案例