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]>

Reply via email to