views:

868

answers:

4

I'm using Tomcat 6.0.24, as packaged for Ubuntu Karmic. The default security policy of Ubuntu's Tomcat package is pretty stringent, but appears straightforward. In /var/lib/tomcat6/conf/policy.d, there are a variety of files that establish default policy.

Worth noting at the start:

  • I've not changed the stock tomcat install at all -- no new jars into its common lib directory(ies), no server.xml changes, etc. Putting the .war file in the webapps directory is the only deployment action.
  • the web application I'm deploying fails with thousands of access denials under this default policy (as reported to the log thanks to the -Djava.security.debug="access,stack,failure" system property).
  • turning off the security manager entirely results in no errors whatsoever, and proper app functionality

What I'd like to do is add an application-specific security policy file to the policy.d directory, which seems to be the recommended practice. I added this to policy.d/100myapp.policy (as a starting point -- I would like to eventually trim back the granted permissions to only what the app actually needs):

grant codeBase "file:${catalina.base}/webapps/ROOT.war" {
  permission java.security.AllPermission;
};

grant codeBase "file:${catalina.base}/webapps/ROOT/-" {
  permission java.security.AllPermission;
};

grant codeBase "file:${catalina.base}/webapps/ROOT/WEB-INF/-" {
  permission java.security.AllPermission;
};

grant codeBase "file:${catalina.base}/webapps/ROOT/WEB-INF/lib/-" {
  permission java.security.AllPermission;
};

grant codeBase "file:${catalina.base}/webapps/ROOT/WEB-INF/classes/-" {
  permission java.security.AllPermission;
};

Note the thrashing around attempting to find the right codeBase declaration. I think that's likely my fundamental problem.

Anyway, the above (really only the first two grants appear to have any effect) almost works: the thousands of access denials are gone, and I'm left with just one. Relevant stack trace:

java.security.AccessControlException: access denied (java.io.FilePermission /var/lib/tomcat6/webapps/ROOT/WEB-INF/classes/com/foo/some-file-here.txt read)
  java.security.AccessControlContext.checkPermission(AccessControlContext.java:323)
  java.security.AccessController.checkPermission(AccessController.java:546)
  java.lang.SecurityManager.checkPermission(SecurityManager.java:532)
  java.lang.SecurityManager.checkRead(SecurityManager.java:871)
  java.io.File.exists(File.java:731)
  org.apache.naming.resources.FileDirContext.file(FileDirContext.java:785)
  org.apache.naming.resources.FileDirContext.lookup(FileDirContext.java:206)
  org.apache.naming.resources.ProxyDirContext.lookup(ProxyDirContext.java:299)
  org.apache.catalina.loader.WebappClassLoader.findResourceInternal(WebappClassLoader.java:1937)
  org.apache.catalina.loader.WebappClassLoader.findResource(WebappClassLoader.java:973)
  org.apache.catalina.loader.WebappClassLoader.getResource(WebappClassLoader.java:1108)
  java.lang.ClassLoader.getResource(ClassLoader.java:973)

I'm pretty convinced that the actual file that's triggering the denial is irrelevant -- it's just some properties file that we check for optional configuration parameters. What's interesting is that:

  1. it doesn't exist in this context
  2. the fact that the file doesn't exist ends up throwing a security exception, rather than java.io.File.exists() simply returning false (although I suppose that's just a matter of the semantics of the read permission).

Another workaround (besides just disabling the security manager in tomcat) is to add an open-ended permission to my policy file:

grant {
  permission java.security.AllPermission;
};

I presume this is functionally equivalent to turning off the security manager.

I suppose I must be getting the codeBase declaration in my grants subtly wrong, but I'm not seeing it at the moment.

A: 

Tomcat runs with its own tomcat user. The war files need to be visible to that user - probably worth checking that first?

anger
Yes, all of the files in question (both .war files and the exploded app directories) are owned by tomcat6:tomcat6, the same user that the tomcat server is run as.
Chas Emerick
A: 

Are you directly deploying to the ROOT directory ?

Usually when you put a war in the webapps folder, say 100myapp.war, it unpacks to a folder named 100myapp itself. Shouldn't the grants then be done on this new folder rather than the ROOT folder ?

StudioEvoque
In general, we're deploying our app as `ROOT.war` so it will be unpacked to the `ROOT` directory. Just in case that was the source of the issue, I've also attempted a deployment to another path (`foo.war`), updating the grants as necessary (to refer to `foo.war` and the unpacked `foo` directory.
Chas Emerick
A: 

It's possible that you have to grant file access permissions separately. Try changing the grant for your app to:

grant codeBase "file:${catalina.base}/webapps/ROOT.war" {
  permission java.security.AllPermission;
  permission java.io.FilePermission "file:${catalina.base}/webapps/ROOT/-", "read, write";
}

If that doesn't work, then it could be that some code outside of what your existing grants cover is accessing those property files (e.g. servlet or other library code).

As a workaround, and to confirm if this is the case, you could do a straight grant on the .properties that are causing you the problem:

grant {
  permission java.io.FilePermission "file:${catalina.base}/webapps/ROOT/WEB-INF/classes/com/foo/some-file-here.txt", "read, write";
}

It seems in fact that the latter could be the case since the stack trace shows code in Tomcat's context loader. If the straight grant on the .properties works, you might want to lock the grant down to org.apache.naming.resources.FileDirContext.

Do you get any stack traces specific to your own code?

Alan Donnelly
Sorry, no dice: adding a FilePermission w/ "read, write" options to all of the grants I had in place changed nothing.However, I do think there's something to that theory: the default policy file that tomcat loads (located at `/var/lib/tomcat6/work/catalina.policy`), there are already grants specified for the codebases I had been using, but which include AllPermission and FilePermission. This despite a quick test showing that the former implies the latter.Unfortunately, the blanket grant on the specific file didn't change behaviour, either. And no, I see no stack traces from our codebase.
Chas Emerick
+2  A: 

Are you using Ubuntu's package-managed version? We had a nightmare recently with security stuff with it, but found that by downloading Tomcat separately and using that, the security issues went away.

Corroboration:

http://www.howtogeek.com/howto/linux/installing-tomcat-6-on-ubuntu/

If you are running Ubuntu and want to use the Tomcat servlet container, you should not use the version from the repositories as it just doesn’t work correctly. Instead you’ll need to use the manual installation process that I’m outlining here.

Brian
We've had no issues with tomcat outside of this security manager issue -- in what way(s) did it "just not work correctly" for you? FWIW, the linked article is ~3 years old, and comments refer to ubuntu 7.x. Nevertheless, I'll give a manual install a shot and see what happens.
Chas Emerick
It was all security manager-related, the issues we had. That said it was a colleague on my team who had the battle with it, he's now left the company so I can't give you any specifics. Seeing your question though, and having never heard of such problems outside of packaged-tomcat-on-ubuntu is what set off the big red siren for me, and using an independent install has been seamless.
Brian
Out of curiosity how did you get on with your manual install?
Brian