DO NOT REPLY TO THIS EMAIL, BUT PLEASE POST YOUR BUG RELATED COMMENTS THROUGH THE WEB INTERFACE AVAILABLE AT <http://nagoya.apache.org/bugzilla/show_bug.cgi?id=7052>. ANY REPLY MADE TO THIS MESSAGE WILL NOT BE COLLECTED AND INSERTED IN THE BUG DATABASE.
http://nagoya.apache.org/bugzilla/show_bug.cgi?id=7052 Security manager not initialised or accessed properly Summary: Security manager not initialised or accessed properly Product: Tomcat 4 Version: 4.0.3 Final Platform: PC OS/Version: Windows NT/2K Status: NEW Severity: Blocker Priority: Other Component: Jasper AssignedTo: [EMAIL PROTECTED] ReportedBy: [EMAIL PROTECTED] OS: Win2K JDK: 1.3.1_02 Stack Trace: java.lang.NullPointerException at org.apache.jasper.servlet.JasperLoader.loadClass(JasperLoader.java:180) at org.apache.jasper.servlet.JasperLoader.loadClass(JasperLoader.java:132) at java.lang.ClassLoader.loadClassInternal(Unknown Source) at org.apache.jsp.RMStartRim$jsp._jspService(RMStartRim$jsp.java:114) at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:107) at javax.servlet.http.HttpServlet.service(HttpServlet.java:853) at org.apache.jasper.servlet.JspServlet$JspServletWrapper.service(JspServlet.java:202) at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:382) at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:474) at javax.servlet.http.HttpServlet.service(HttpServlet.java:853) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:247) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:243) at org.apache.catalina.core.StandardPipeline.invokeNext(StandardPipeline.java:566) at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:472) at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:943) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:190) at org.apache.catalina.core.StandardPipeline.invokeNext(StandardPipeline.java:566) at org.apache.catalina.valves.CertificatesValve.invoke(CertificatesValve.java:246) at org.apache.catalina.core.StandardPipeline.invokeNext(StandardPipeline.java:564) at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:472) at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:943) at org.apache.catalina.core.StandardContext.invoke(StandardContext.java:2343) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:180) at org.apache.catalina.core.StandardPipeline.invokeNext(StandardPipeline.java:566) at org.apache.catalina.valves.ErrorDispatcherValve.invoke(ErrorDispatcherValve.java:170) at org.apache.catalina.core.StandardPipeline.invokeNext(StandardPipeline.java:564) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:170) at org.apache.catalina.core.StandardPipeline.invokeNext(StandardPipeline.java:564) at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:472) at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:943) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:174) at org.apache.catalina.core.StandardPipeline.invokeNext(StandardPipeline.java:566) at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:472) at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:943) at org.apache.catalina.connector.http.HttpProcessor.process(HttpProcessor.java:1012) at org.apache.catalina.connector.http.HttpProcessor.run(HttpProcessor.java:1107) at java.lang.Thread.run(Unknown Source) -------------------------------------------------------------------------------- Investigation: I have had a problem running JSPs under Tomcat 4.x embedded in JBoss 2.4.4, which I believe stems from the initialisation of the "java.security.manager" system property. When running Tomcat inside JBoss, the security manager property does not seem to be automatically initialised, perhaps because JBoss uses a different security model. If you try to initialise the system property value yourself by specifying a security manager class name in the JBoss startup file command line, you get a weird error, which I have not been able to debug since it crashes the JBoss VM entirely. Anyway, this would perhaps not matter to some people, who can get away without specifying a security manager directly in their own code. However, I need to set one for the RMI calls in Jini, since I persist data via a JavaSpace. Hence a part of my application initialisation is to set the system security manager. Now, the Tomcat class loader object (an instance of org.apache.jasper.servlet.JasperLoader) is created before any web apps are loaded, and there seems to be a bug in this class. The class loader object sets its security manager as a private variable "securityManager" in the constructor from the System property. This is before I get a chance inside my app to set the property, so the securityManager variable is null in the Tomcat class loader object. During a JSP, Tomcat then decides whether to do security checks by checking whether or not the system property is null. If you have set it to a value, as I do, Tomcat will try and do security checks. But it doesn't use the system property to actually do the security check - it uses the private variable, which is still null! Hence, whenever I try to use Java code in a JSP, Tomcat crashes with a NullPointerException, which is not caught. See attached stack trace. To get my JSPs running, I have patched org.apache.jasper.servlet.JasperLoader to set the private variable "securityManager" if it is null when about to do a security check, using the system property value. It was necessary to do this in 3 places inside the class (see listing below). I put my version in a jar and placed it in the folder %CATALINA_HOME%\common\lib. Since this is earlier on the classpath than the jar from which the class is normally loaded, my version is used instead of the normal one, and the JSPs now run OK. If there is a better way to initialise the security manager in Tomcat4.x when embedded in JBoss I would be very interested to hear of it, since it is obviously not ideal to be patching Tomcat in order to get an app to run! Best wishes Keith Harrison- Broninski [EMAIL PROTECTED] /* * ==================================================================== * * The Apache Software License, Version 1.1 * * Copyright (c) 1999 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. * */ package org.apache.jasper.servlet; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.io.IOException; import java.net.URL; import java.net.URLClassLoader; import java.security.AccessController; import java.security.CodeSource; import java.security.PermissionCollection; import java.security.PrivilegedAction; import java.security.ProtectionDomain; import org.apache.jasper.JasperException; import org.apache.jasper.Constants; import org.apache.jasper.JspCompilationContext; import org.apache.jasper.JspEngineContext; import org.apache.jasper.Options; import org.apache.jasper.compiler.Compiler; import org.apache.jasper.logging.Logger; import javax.servlet.http.*; /** * This is a class loader that loads JSP files as though they were * Java classes. It calls the compiler to compile the JSP file into a * servlet and then loads the generated class. * * @author Anil K. Vijendran * @author Harish Prabandham */ public class JasperLoader extends URLClassLoader { protected class PrivilegedLoadClass implements PrivilegedAction { PrivilegedLoadClass() { } public Object run() { return Thread.currentThread().getContextClassLoader(); } } private PermissionCollection permissionCollection = null; private CodeSource codeSource = null; private String className = null; private ClassLoader parent = null; private SecurityManager securityManager = null; private PrivilegedLoadClass privLoadClass = null; JasperLoader(URL [] urls, String className, ClassLoader parent, PermissionCollection permissionCollection, CodeSource codeSource) { super(urls,parent); this.permissionCollection = permissionCollection; this.codeSource = codeSource; this.className = className; this.parent = parent; this.privLoadClass = new PrivilegedLoadClass(); this.securityManager = System.getSecurityManager(); } /** * Load the class with the specified name. This method searches for * classes in the same manner as <code>loadClass(String, boolean)</code> * with <code>false</code> as the second argument. * * @param name Name of the class to be loaded * * @exception ClassNotFoundException if the class was not found */ public Class loadClass(String name) throws ClassNotFoundException { return (loadClass(name, false)); } /** * Load the class with the specified name, searching using the following * algorithm until it finds and returns the class. If the class cannot * be found, returns <code>ClassNotFoundException</code>. * <ul> * <li>Call <code>findLoadedClass(String)</code> to check if the * class has already been loaded. If it has, the same * <code>Class</code> object is returned.</li> * <li>If the <code>delegate</code> property is set to <code>true</code>, * call the <code>loadClass()</code> method of the parent class * loader, if any.</li> * <li>Call <code>findClass()</code> to find this class in our locally * defined repositories.</li> * <li>Call the <code>loadClass()</code> method of our parent * class loader, if any.</li> * </ul> * If the class was found using the above steps, and the * <code>resolve</code> flag is <code>true</code>, this method will then * call <code>resolveClass(Class)</code> on the resulting Class object. * * @param name Name of the class to be loaded * @param resolve If <code>true</code> then resolve the class * * @exception ClassNotFoundException if the class was not found */ public Class loadClass(String name, boolean resolve) throws ClassNotFoundException { Class clazz = null; // (0) Check our previously loaded class cache clazz = findLoadedClass(name); if (clazz != null) { if (resolve) resolveClass(clazz); return (clazz); } // (.5) Permission to access this class when using a SecurityManager int dot = name.lastIndexOf('.'); if (System.getSecurityManager() != null) { // Start of patch 1/3 by Keith Harrison- Broninski if( securityManager == null ) { securityManager = System.getSecurityManager(); } // End of patch 1/3 by Keith Harrison-Broninski if (dot >= 0) { try { securityManager.checkPackageAccess(name.substring(0,dot)); } catch (SecurityException se) { String error = "Security Violation, attempt to use " + "Restricted Class: " + name; System.out.println(error); throw new ClassNotFoundException(error); } } } // Class is in a package, delegate to thread context class loader if( !name.startsWith(Constants.JSP_PACKAGE_NAME) ) { ClassLoader classLoader = null; if (System.getSecurityManager() != null) { // Start of patch 2/3 by Keith Harrison-Broninski if( securityManager == null ) { securityManager = System.getSecurityManager(); } // End of patch 2/3 by Keith Harrison-Broninski classLoader = (ClassLoader) AccessController.doPrivileged(privLoadClass); } else { classLoader = Thread.currentThread().getContextClassLoader(); } clazz = classLoader.loadClass(name); if( resolve ) resolveClass(clazz); return clazz; } // Only load classes for this JSP page if( name.startsWith(Constants.JSP_PACKAGE_NAME + "." + className) ) { String classFile = name.substring(Constants.JSP_PACKAGE_NAME.length()+1) + ".class"; byte [] cdata = loadClassDataFromFile(classFile); if( cdata == null ) throw new ClassNotFoundException(name); if( System.getSecurityManager() != null ) { // Start of patch 3/3 by Keith Harrison-Broninski if( securityManager == null ) { securityManager = System.getSecurityManager(); } // End of patch 3/3 by Keith Harrison-Broninski ProtectionDomain pd = new ProtectionDomain( codeSource, permissionCollection); clazz = defineClass(name,cdata,0,cdata.length,pd); } else { clazz = defineClass(name,cdata,0,cdata.length); } if( clazz != null ) { if( resolve ) resolveClass(clazz); return clazz; } } throw new ClassNotFoundException(name); } /** * Get the Permissions for a CodeSource. * * Since this ClassLoader is only used for a JSP page in * a web application context, we just return our preset * PermissionCollection for the web app context. * * @param CodeSource where the code was loaded from * @return PermissionCollection for CodeSource */ protected final PermissionCollection getPermissions(CodeSource codeSource) { return permissionCollection; } /** * Load JSP class data from file. */ protected byte[] loadClassDataFromFile(String fileName) { byte[] classBytes = null; try { InputStream in = getResourceAsStream(fileName); if (in == null) { return null; } ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte buf[] = new byte[1024]; for(int i = 0; (i = in.read(buf)) != -1; ) baos.write(buf, 0, i); in.close(); baos.close(); classBytes = baos.toByteArray(); } catch(Exception ex) { ex.printStackTrace(); return null; } return classBytes; } } -- To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]> For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>