Bug 60087 - Bouncy Castle in WEB-INF/lib not working on Tomcat 8 when unpackWars=false
Summary: Bouncy Castle in WEB-INF/lib not working on Tomcat 8 when unpackWars=false
Status: RESOLVED FIXED
Alias: None
Product: Tomcat 8
Classification: Unclassified
Component: Catalina (show other bugs)
Version: 8.0.37
Hardware: PC All
: P2 normal (vote)
Target Milestone: ----
Assignee: Tomcat Developers Mailing List
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2016-09-06 12:35 UTC by Shamil Bahirov
Modified: 2016-11-21 21:00 UTC (History)
1 user (show)



Attachments
test war zip part 1 (976.56 KB, application/zip)
2016-09-06 12:38 UTC, Shamil Bahirov
Details
test war zip part 2 (613.54 KB, application/octet-stream)
2016-09-06 12:39 UTC, Shamil Bahirov
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Shamil Bahirov 2016-09-06 12:35:56 UTC
This is basically same issue but with a test project provided that you can debug
https://bz.apache.org/bugzilla/show_bug.cgi?id=57736

What happens is javax.crypto.JarVerifier.verifySingleJar complains about unsigned content which in fact there's not such content in the jar but for some reason all WAR resources appear as jar's content

java.util.jar.JarException: jar:file:/C:/Users/bahisha/work/apache-tomcat-8.0.36/webapps/test.war!/WEB-INF/lib/bcprov-jdk16-1.46.jar has unsigned entries - WEB-INF/lib/bcprov-jdk16-1.46.jar
Comment 1 Shamil Bahirov 2016-09-06 12:38:55 UTC
Created attachment 34206 [details]
test war zip part 1
Comment 2 Shamil Bahirov 2016-09-06 12:39:21 UTC
Created attachment 34207 [details]
test war zip part 2
Comment 3 rpc1 2016-09-29 11:35:51 UTC
I reproduced error on Tomcat 8.0.x with unpackWARs="false".
Error because of the getLocation(), which returns codeBaseURL for resource file.
Location URL is 
jar:file:/some_path/webapps/test.war!/WEB-INF/lib/bcprov-jdk16-1.46.jar, but
((JarURLConnection)url.openConnection()).getJarFile() connects to the test.war instead bcprov-jdk16-1.46.jar, because the test.war before separator '!/'.
We need jar:war: path to access resource inside of test.war file (because it doesn't unpack). This is example of the URL which have to be used in given test:
jar:war:file:/some_path/webapps/test.war*/WEB-INF/lib/bcprov-jdk16-1.46.jar!/

I looked at sources and notice that getLocation() returns AbstractArchiveResource.codeBaseUrl field, for war resources this field generates in constructor JarWarResource, I changed constructor of JarWarResource for codeBaseUrl:
before codeBaseUrl="jar:" + baseUrl + "!/" + archivePath
after  codeBaseUrl="jar:war:" + baseUrl + "*/" + archivePath+"!/"

I rebuilt tomcat and tried attached test, everything works fine, 
But I have doubts in solution correctness, because codeBaseUrl uses in WebappClassLoaderBase.getPermissions() function, which gets permissions for codeSource. In current version, for codeSource /some_path/webapps/test.war!/WEB-INF/lib/bcprov-jdk16-1.46.jar, getPermissions returns permission collection for test.war,  but after changes of codeBaseURL getPermissions() returns permissions for bcprov-jdk16-1.46.jar which
located in war archive.

Could somebody confirm that changing JarWarResource's constructor is a right solution?
Comment 4 Mark Thomas 2016-09-30 11:48:46 UTC
Unfortunately, it doesn't appear to be as clear cut as I would like.

If we look at how the JRE constructs a code path for a JAR, it returns a "file:" URL to the JAR, not a "jar:" URL. Therefore, if Tomcat is to be consistent with that, the current behavior is correct.

However, the JarVerifier accepts either a "file:" or "jar:" URL for a JAR and ignores the possibility of JARs in WARs etc entirely.

Returning "jar:" URLs and "jar:war:" URLs would fix JarVerifier but might break other functionality. I need to do some more testing with the security manager.
Comment 5 Mark Thomas 2016-10-05 10:58:11 UTC
This has been fixed in the following branches:
- 9.0.x for 9.0.0.M11 onwards
- 8.5.x for 8.5.6 onwards
- 8.0.x for 8.0.38 onwards

7.0.x and earlier versions were not affected.

Fixing this required refactoring of the web resources handling to use the Tomcat specific 'war:file:...' URL protocol to refer to WAR files and their contents rather than the standard 'jar:file:...' form. A side-effect of the refactoring is that when using packed WARs, it is now possible to reference a WAR and/or specific JARs within a WAR in the security policy file used when running under a SecurityManager.
Comment 6 Diego Díez Ricondo 2016-11-19 15:43:12 UTC
This solution has introduced a new issue resolving resources url.
I've made a project to test this behaviour https://github.com/didiez/tomcat-bug-60087

Run the main-app to see the problem. If built changing tomcat.version to 8.5.5 everything works as expected.
Comment 7 Violeta Georgieva 2016-11-21 21:00:02 UTC
(In reply to Diego Díez Ricondo from comment #6)
> This solution has introduced a new issue resolving resources url.
> I've made a project to test this behaviour
> https://github.com/didiez/tomcat-bug-60087
> 
> Run the main-app to see the problem. If built changing tomcat.version to
> 8.5.5 everything works as expected.

Update the status in favor to the archives.
This has been fixed:
https://bz.apache.org/bugzilla/show_bug.cgi?id=60391