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=8092>. 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=8092 Exposure of JSP source code to clients in some cases Summary: Exposure of JSP source code to clients in some cases Product: Tomcat 4 Version: 4.0.3 Final Platform: Other OS/Version: Other Status: NEW Severity: Major Priority: Other Component: Catalina AssignedTo: [EMAIL PROTECTED] ReportedBy: [EMAIL PROTECTED] The Bug ======= To reproduce the bug, deploy the attached war file and request "/jsp/including.jsp". What you get is the JSP source code of the file "test.jsp". This behaviour is due to problems with chained includes and forwards (detailed explanation below). The Analysis ============ I'll first explain the problem with a more simple test case than that described above (I'll come back to the other one later): A servlet ("BugtestServlet") includes another servlet ("IncludedServlet") using ServletContext.getRequestDispatcher. Now IncludedServlet forwards to "/jsp/forwarded.jsp". So in summary we have: "/BugtestServlet" --- includes ---> "/IncludedServlet" --- forwards to ---> "/jsp/forwarded.jsp" Now if you request "/BugtestServlet", Tomcat returns an exception message saying the file "/IncludedServlet" cannot be found. Note that this problem does not occur when using Orion or Resin servlet engines. The problem originates from chapter 8 of the Servlet 2.3 spec. In short, it says that - in case of a forward, the resource that is forwarded to sees the servlet path (via getServletPath) used in the request dispatcher - in case of an include, the included resource sees the original servlet path (e.g. "/BugtestServlet") and can retrieve the path used in the request dispatcher (e.g. "/IncludedServlet") via special request attributes The problem starts when Jasper's JspServlet tries to determine which page to deliver. It cannot simply use getServletPath() since this will return the original path when doing an include. Thus, it checks if "javax.servlet.include.servlet_path" is present as a request attribute. If it is, JspServlet uses it instead of getServletPath(). This works in simple cases (e.g. a Servlet including a JSP), but fails for the bugtest webapp. Explanation: - in IncludedServlet, getServletPath() returns "/BugtestServlet" and the "javax.servlet.include.servlet_path" attribute is "/IncludedServlet" - in JspServlet (indirectly invoked by forwarding to "/jsp/forwarded.jsp"), getServletPath() returns "/jsp/forwarded.jsp" and the "javax.servlet.include.servlet_path" attribute is "/IncludedServlet" - since the additional request attribute is present, JspServlet thinks it has to use it instead of getServletPath() - processing "/IncludedServlet" as a JSP fails with a FileNotFoundException This is only the harmless case. If you replace the servlets with JSPs, you can easily produce endless forwarding loops or make Tomcat serve JSP source code (see test case mentioned at the beginning). The latter occurs if you forward to an HTML page (or another resource of type text/*) because the default servlet is invoked (since we have a static resource) but the file send to the client is the JSP from which the forward originates. Proposed Solution ================= I would suggest to add a request attribute "org.apache.catalina.actual_servlet_path" that _always_ contains the path used when retrieving a request dispatcher. This way, the correct path could be determined no matter whether include or forward is used: - check if "org.apache.catalina.actual_servlet_path" is present; if so, use it as the path for accessing resources etc. - if the attribute is not present, fall back to the standard behaviour (i.e. check for "javax.servlet.include.servlet_path" and use getServletPath if this is not present) I've already tested this with JspServlet, and it works fine. However, to be consistent, several source files would have to be changed, for example: - DefaultServlet.java (necessary to solve the "forward to html" problem described above) - HttpRequestBase.java since it uses "javax.servlet.include.servlet_path" to convert a request-relative path to a context-relative one (currently, this probably failes within include/forward chains) - a bunch of other files (basically all that deal with the case of an include specifically) Also, the problem is not limited to "javax.servlet.include.servlet_path" but applies to all request attributes set in an include. For all of these, counterparts that reflect the correct path should be introduced. The best solution would be if the spec mandated such attributes, e.g. "javax.servlet.actual_path.servlet_path" etc. Should I write to servletapi- [EMAIL PROTECTED] about it or is there a better place? Or maybe I'm missing something and the issue can be solved more elegantly? Final remarks ============= If I receive positive feedback on this, I'll happily send a comprehensive patch. Until now, I've only added an attribute for the servlet path (and not path info etc.) and a check for it in JspServlet. Thanks for your time PS Maybe this bug is also present in Tomcat 3.3 (haven't tested that). -- To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]> For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>