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

2

13

In a software for a customer we have to read given URLs to parse their content. Also the customer needs to activate Tomcat-Security-Manager to let Java-Policies control what the program does.

Now, with reading URLs the exception "javax.net.ssl.SSLKeyException: RSA premaster secret error" happens, but only under certain conditions:

  • if the URL is HTTPS but not for HTTP
  • if the Security-Manager is activated, not when it is deactivated or if in a global grant-Block the AllPermission is set
  • only with Java 6, not with Java 7 (the customer needs Java 6 currently)
  • only with Tomcat6, not with Tomcat 7 (the customer needs Tomcat 6 currently)

The Security-violation happens somewhere in Java-Code, an AllPermission restricted to our codebase doesn't prevent the error.

So, does someone has an idea, which permission to set for Java 6, so that it can process HTTPS?

Other information: It's running inside a tomcat, on a Debian-Linux with OpenJDK.

EDIT: I added the Java-Param "-Djava.security.debug=access,failure" to Tomcats /etc/default/tomcat6 in the variable JAVA_OPTS. But in the Logs I have no additional messages. Might it be possible the code asks the permissions before triggering them?

EDIT2: I found the correct place and got the full stacktrace (removed specific customer parts):

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: So far I was under the assumption that the Java-class URL was used to access the contents of the resource. But that is untrue. It is using from Grails-Code the Groovy-URL-object with the getText()-method:

new URL(params.url).text

The error is happening on this line. It's Grails-version 2.2.4.

Heterotypic answered 18/9, 2015 at 7:56 Comment(15)
Do you need to visit the https url and then do something with the page?Arrow
@AkashAggarwal: Yes, the content behind the URL is then parsed in the applciation. But it doesn't get to this point, as the URL can't be accessed.Heterotypic
Where does the URL open, in a desktop browser or inside an app?Arrow
It is parsed by the Java-program. If it would open in the browser it wouldn't bring a Java-error-message. Also it isn't open at all, the content behind the URL is read in and parsed and data extracted from it is saved to the DB. But getting the content from the net fails with the given exception.Heterotypic
Can you fix the grammar of your second last sentence?Arrow
I'm no native speaker, so my grammar might be off. Suggest an edit to fix it, I don't know what is wrong.Heterotypic
It is about your second last comment. Neither can I edit a comment nor I understand what you want to say in the second last line of that comment. I wouldn't have asked you to edit it if I understood it :)Arrow
Did you mean that- "Also it isn't opening at all. The content behind the URL is read in, parsed and data extracted from it is saved to the DB"?Arrow
@AkashAggarwal: I meant, that nothing is shown to the user at that point, no browser window or something (as you asked about it before). It is a server-app anyways.Heterotypic
I've never really fiddled with policy and security manager but I'd still like to help you since Java is my favorite language and I think I can help you get to somewhere. Could you post the code that I need to see?Arrow
Can you add full stack trace and full JDK version? You can read #19432551, may be it is your case.Ditch
You need to post the full stack trace. I strongly suspect the exception is a consequence, rather than the root cause. You probably have a jar missing - e.g. see this thread. You say you're on OpenJDK - I assume your client is too? Is it possible you're specifying a keyGenerator that is not present in OpenJDK (even if it is in Sun JRE). If it turns out that a missing keyGenerator is the root cause exception, I can maybe write up an answer.Seitz
Currently I haven't the Stacktrace available, I have to find the correct position it is catched. But shouldn't the missing library also be missing if the Security-Manager is disabled?Heterotypic
I get your point, but I can't make all the symptoms add up at the moment. Without extra diagnostic info, it's going to be hard to help, even though I'd like to. You could be seeing something similar to this. But the trail went cold there. Or this - again closed as non-reproducible. Note that down the stack trace, they're all root cause NoSuchAlgorithmException, which is down to something wrong with the classpath - often citing sunjce_provider.jar.Seitz
Have you tried running server with Oracle JDK?Commonwealth
S
9

Solution following several comments and OP confirmation of resolution (summary)

The root cause is the presence of sunjce_provider.jar in multiple locations. This was discovered by the OP after it was suggested as one of a number of possible root causes (see the very end of this answer and the comment trail). As per OP's comment:

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

Therefore the resolution in this case was to ensure that the app had rights to access the correct copy of sunjce_provider.jar

I've left the main points from my original answer and the comments that helped with diagnosis below for anyone who finds this later

Original answer and comments that led to solution

  1. This will not happen with http because your web app (that is the client for this connection, even though it's running in tomcat), does not need to generate a key in this configuration.

  2. The fact it only occurs when SecurityManager is enabled, but not if disabled or with global AllPermission suggests its a file permission error. It suggests that it is not a problem with the key length (e.g. the one mentioned here)

Other similar reports on the web indicate that the likely root cause is a missing jar (usually sunjce_provider.jar is cited). The stack trace confirms that the root cause exception is a NoSuchAlgorithmException where the KeyGenerator is looking for algorithm SunTlsRsaPremasterSecret and can't find it. In your case, as this only occurs with a particular SecurityManager configuration, it could be an inaccessible jar (due to security permissions).

My guess would be that you have not enabled grant codeBase permissions to the correct directory that contains the jar needed for your RSA keygen algorithm. My suggested course of action would be to go through your webapp and JRE directory structure to find where runtime jars are kept and ensure that they have permissions granted in catalina.policy.

In the default configuration - for instance - you should see somewhere

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

For details of what this means exactly see this section of the tomcat security manager "How To". You need to check a few things - make sure that ${java.home}/jre/lib/ext/ is where your runtime jars are. If not - alter the path to point to the right place (it is where they are on my version of OpenJDK 6 - build 27). In particular you should see sunjce_provider.jar and sunpkcs11.jar in there. Make sure the above section exists in your policy file.

It may be that the code is depending on some jars that are within your webapp - e.g. in ${catalina.base}/path/to/your/webapp/WEB-INF/classes/ - in which case you need to grant permissions to that directory.


Other problems that cause same or similar symptoms

  1. The app being unable to find or accesssunpkcs11.jar will give the same error message (verified on Ubuntu+openjdk6+tomcat6 system). It is likely that duplicate copies of that jar will, too.

  2. check /etc/java-6-openjdk/security/java.security. It should list providers in there - check there's a line something like security.provider.n = sun.security.pkcs11.SunPKCS11 in there - if that line is missing you also get this error (verified on same system)

  3. This Debian bug report talks about problems with the location of jars when running under a SecurityManager


Debugging comment

As per the other answer, you might try adding -Djava.security.debug=access,failure to CATALINA_OPTS or JAVA_OPTS in your catalina.sh to enable debugging - which should log to catalina.out by default (or wherever you have set your logging to via CATALINA_OUT in catalina.sh. You should see output from the SecurityManager there.

You can also try -Djava.security.debug=all. You will get a huge catalina.out`, but you can grep for words that might help (like "fail"!!!)


Follow the code from the stack trace

Your exception is being thrown 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() might return false. This all points back to the provider jar being incaccessible for some reason.

I'm assuming you didn't see any access violations in the output, even with -Djava.security.debug=access,failure. You could try -Djava.security.debug=all, although that may well simply produce more irrelevant logging. If there is no access violation, you may have two versions of that jar on your classpath somehow and the runtime is accessing (or trying to access the wrong one). A case similar to this is described in this Q/A.

Seitz answered 27/9, 2015 at 20:52 Comment(10)
The sunjce_provider.jar has granted already AllPermissions (exactly like your example for jre/lib/ext/-). I gave it anyways again, but it didn't change anything.Heterotypic
@Heterotypic well - with the stack at least we have a confirmation of the root cause. There is another option. You may have two versions of that jar on your classpath somehow (in this configuration - like this). If you start Tomcat from Eclipse - that happens often (just a guess). I'm assuming you didn't see any access violations in the output, even with -Djava.security.debug=access,failure. Your exception is being thrown hereSeitz
Looking at how that exception could be thrown - this method must return null. It swallows Exceptions - which isn't nice. My current thoughts are that this bug report might provide a minimal repro - I'm going to try it tonight.Seitz
@mnemeth OK - so curiosity got the better of me. I set up a fresh install with tomcat6 and openjdk6 on an ubuntu virtual box. I added the retrieval of https://google.co.uk to one of the tomcat servlet examples. I can replicate your error by removing access to the sunpkcs11.jar (not the sunjce_provider.jar). Without detailed access to your .policy file(s) and directory structure, I don't know whether I can help with more diagnosis, but I'm pretty sure that the access to this jar is the problem. It "just worked" out of the box for my fresh install, though.Seitz
If you try with -Djava.security.debug=all you will get a huge catalina.out, but if you grep it for "fail", that should give you some clues if it is a securitymanager access issue. I'll keep thinking about a definitive solution.Seitz
You could also check for multiple copies of sunpkcs by running a find / -iname sunpkcs11.jar to eliminate running against the wrong copy as an option. I have only one copy on my installation (and one symbolic link to it). And a final thought - check /etc/java-6-openjdk/security/java.security. It should list providers in there - check there's a line something like security.provider.n = sun.security.pkcs11.SunPKCS11 in there. I've verified that a missing provider in there will also replicate your error.Seitz
Check this bug report on debian with OpenJDK6 too - maybe you are suffering from a similar thing relating to exact location of /jre/lib/ext bugs.debian.org/cgi-bin/bugreport.cgi?bug=649046Seitz
Oh. 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. Don't now how that happens. As you put a lot of effort into researching and your hints were most helpful to solve the problem I'll grant you the bounty. But you should edit the solution into your answer for future reference.Heterotypic
Brilliant - glad to hear you found it !!! I'll definitely edit that into the main solution. just to be clear then (so i edit in the right bit from my comments above) - the root cause was multiple versions of sunjce_provider.jar ?Seitz
@mnementh Edited - please feel free to read over it and check it matches your situation. Obviously if you want to make minor edits to the answer, that's fine too.Seitz
S
8

The easy way to discover all required permissions is to run with the argument

-Djava.security.debug=access,failure

You will then be given complete information on every failed security access, the protection domain that was in force, etc.

Sibbie answered 18/9, 2015 at 9:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.