Symptoms: If catalina.policy is changed to include grants that have any principals specified (including wildcard principals "* *") then any web application that is protected with a security constraint will cause a java.lang.ClassCircularityError to be thrown when an attempt is made to log into it. How to reproduce: 1. In the jsp-examples web application edit web.xml and comment out or delete the following lines: <servlet> <servlet-name>org.apache.jsp.security.protected_.index_jsp</servlet-name> <servlet-class>org.apache.jsp.security.protected_.index_jsp</servlet-class> </servlet> <servlet-mapping> <servlet-name>org.apache.jsp.security.protected_.index_jsp</servlet-name> <url-pattern>/security/protected/index.jsp</url-pattern> </servlet-mapping> 2. Add the following grant to catalina.policy: grant principal * * { permission java.util.PropertyPermission "*", "read"; }; 3. Start tomcat with the security manager enabled (-security). 4. Attempt to log into the jsp-examples protected application with the following URL (modified to suit of course) http://<ip address>:<port>/jsp-examples/security/protected/index.jsp You should then see the following exception: java.lang.ClassCircularityError: WILDCARD_PRINCIPAL_CLASS java.lang.Class.forName0(Native Method) java.lang.Class.forName(Class.java:242) sun.security.provider.PolicyFile.addPermissions(PolicyFile.java:1403) sun.security.provider.PolicyFile.getPermissions(PolicyFile.java:1307) sun.security.provider.PolicyFile.getPermissions(PolicyFile.java:1270) sun.security.provider.PolicyFile.getPermissions(PolicyFile.java:1211) sun.security.provider.PolicyFile.implies(PolicyFile.java:1166) java.security.ProtectionDomain.implies(ProtectionDomain.java:195) java.security.AccessControlContext.checkPermission(AccessControlContext.java:249) java.security.AccessController.checkPermission(AccessController.java:427) java.lang.SecurityManager.checkPermission(SecurityManager.java:532) java.lang.SecurityManager.checkRead(SecurityManager.java:871) java.io.File.exists(File.java:700) org.apache.naming.resources.FileDirContext.file(FileDirContext.java:826) org.apache.naming.resources.FileDirContext.lookup(FileDirContext.java:210) org.apache.naming.resources.ProxyDirContext.lookup(ProxyDirContext.java:293) org.apache.catalina.loader.WebappClassLoader.findResourceInternal(WebappClassLoader.java:1851) org.apache.catalina.loader.WebappClassLoader.findClassInternal(WebappClassLoader.java:1716) org.apache.catalina.loader.WebappClassLoader.findClass(WebappClassLoader.java:866) org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1319) org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1198) java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319) java.lang.Class.forName0(Native Method) java.lang.Class.forName(Class.java:242) sun.security.provider.PolicyFile.addPermissions(PolicyFile.java:1403) sun.security.provider.PolicyFile.getPermissions(PolicyFile.java:1307) sun.security.provider.PolicyFile.getPermissions(PolicyFile.java:1270) sun.security.provider.PolicyFile.getPermissions(PolicyFile.java:1211) sun.security.provider.PolicyFile.implies(PolicyFile.java:1166) java.security.ProtectionDomain.implies(ProtectionDomain.java:195) java.security.AccessControlContext.checkPermission(AccessControlContext.java:249) java.security.AccessController.checkPermission(AccessController.java:427) java.lang.SecurityManager.checkPermission(SecurityManager.java:532) java.lang.SecurityManager.checkPackageAccess(SecurityManager.java:1512) sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:265) java.lang.ClassLoader.loadClass(ClassLoader.java:299) java.lang.ClassLoader.loadClass(ClassLoader.java:251) java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319) org.apache.jasper.servlet.JspServletWrapper.<init>(JspServletWrapper.java:101) org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:307) org.apache.jasper.servlet.JspServlet.service(JspServlet.java:264) javax.servlet.http.HttpServlet.service(HttpServlet.java:802) sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) java.lang.reflect.Method.invoke(Method.java:585) org.apache.catalina.security.SecurityUtil$1.run(SecurityUtil.java:243) java.security.AccessController.doPrivileged(Native Method) javax.security.auth.Subject.doAsPrivileged(Subject.java:517) org.apache.catalina.security.SecurityUtil.execute(SecurityUtil.java:275) org.apache.catalina.security.SecurityUtil.doAsPrivilege(SecurityUtil.java:161) Notes: The same error will occur no matter what principal class you try. It looks like the code is trying to load the principal class when refreshing the policy but then checks its permission to load the class and trys to refresh the policy to do that and then gets the ClassCircularityError. Note that the error will not occur if you leave web.xml as it is. This is obviously a point of some importance but the error was originally seen with our web application that has all of its JSP's mapped to servlets in web.xml using similar declarations created by JSPC so it doesn't appear that modifying web.xml is going to help us in this regard. This problem has been seen by other people. One of them proposed moving all classes to the shared directory but this had no effect in our case. Here are some references: http://marc.theaimsgroup.com/?l=tomcat-user&m=108497966630946&w=2 http://mail-archives.apache.org/mod_mbox/jakarta-tomcat-user/200408.mbox/%3CBC6E0186-E532-11D8-B5E8-000A95B26EEC@suranyami.com%3E Finally, as noted in the second reference, the problem doesn't seem to happen in tomcat 5.0.19 (but then we have other problems, as well as having to go backwards in tomcat revisions)
After comparing SecurityUtil.java in 5.0.19 to 5.0.28 it can be seen that in 5.0.19 the principal was not being associated with the subject. It seems likely then that the reason that the ClassCircularityError did not appear under 5.0.19 was simply because the security check failed because the subject had no principals and it was looking at a grant that had principals specified. In turn this avoided the security code needing to load the principal class and hence no ClassCircularityError.
In further investigation we built the 5.5.14 source and ran that instead. We found that in this case that all secured applications (including the management application) were affected by this error.
Suggested patch?
(In reply to comment #3) > Suggested patch? We've since written our own policy implementation that bypasses the Sun implementation (we were going to do this anyway as we wanted to use a database as our policy repository). Our hack to get around the ClassCircularityError is to always grant java.io.FilePermission, java.lang.RuntimePermission "accessClassInPackage", and java.lang.RuntimePermission "defineClassInPackage" when the file or class in question relates to our Principal class. Not very elegant I know but it works for us. If we could get access to the Sun policy implementation source code we might be able to work out why the error occurred in the first place.
any updates on this bug ... any patch rleased
maris, I would use James' workaround for now. As he said, it might not be the prettiest, but it works. Since the bug appears to be in Sun's policy implementation, you might want to check out their BugParade.