craigmcc 00/11/30 18:11:23 Modified: catalina/src/share/org/apache/catalina/connector HttpResponseBase.java ResponseBase.java catalina/src/share/org/apache/catalina/core LocalStrings.properties StandardContextValve.java Log: Fix a potential security problem in Tomcat 4.0. The servlet specification prohibits servlet containers from serving "files" in the WEB-INF directory of a web application. Tomcat 4.0 currently enforces this restriction on static resources (like /WEB-INF/web.xml), but allowed access to JSP pages stored there (/WEB-INF/index.jsp). This access is now longer allowed. Submitted by: David Aiken <[EMAIL PROTECTED]> Revision Changes Path 1.18 +16 -11 jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/connector/HttpResponseBase.java Index: HttpResponseBase.java =================================================================== RCS file: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/connector/HttpResponseBase.java,v retrieving revision 1.17 retrieving revision 1.18 diff -u -r1.17 -r1.18 --- HttpResponseBase.java 2000/11/21 00:00:39 1.17 +++ HttpResponseBase.java 2000/12/01 02:11:20 1.18 @@ -1,7 +1,7 @@ /* - * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/connector/HttpResponseBase.java,v 1.17 2000/11/21 00:00:39 craigmcc Exp $ - * $Revision: 1.17 $ - * $Date: 2000/11/21 00:00:39 $ + * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/connector/HttpResponseBase.java,v 1.18 2000/12/01 02:11:20 craigmcc Exp $ + * $Revision: 1.18 $ + * $Date: 2000/12/01 02:11:20 $ * * ==================================================================== * @@ -96,7 +96,7 @@ * methods need to be implemented. * * @author Craig R. McClanahan - * @version $Revision: 1.17 $ $Date: 2000/11/21 00:00:39 $ + * @version $Revision: 1.18 $ $Date: 2000/12/01 02:11:20 $ */ public class HttpResponseBase @@ -482,17 +482,19 @@ outputWriter.print(message); } outputWriter.print("\r\n"); - // log(request.getRequest().getProtocol() + " " + status + " " + message); + // System.out.println("sendHeaders: " + + // request.getRequest().getProtocol() + + // " " + status + " " + message); // Send the content-length and content-type headers (if any) if (getContentType() != null) { outputWriter.print("Content-Type: " + getContentType() + "\r\n"); - // log(" Content-Type: " + getContentType()); + // System.out.println(" Content-Type: " + getContentType()); } - if (getContentLength() >= 0) { + if (getContentLength() > 0) { outputWriter.print("Content-Length: " + getContentLength() + "\r\n"); - // log(" Content-Length: " + getContentLength()); + // System.out.println(" Content-Length: " + getContentLength()); } // Send all specified headers (if any) @@ -508,7 +510,7 @@ outputWriter.print(": "); outputWriter.print(value); outputWriter.print("\r\n"); - // log(" " + name + ": " + value); + // System.out.println(" " + name + ": " + value); } } } @@ -543,14 +545,17 @@ outputWriter.print(": "); outputWriter.print(CookieTools.getCookieHeaderValue(cookie)); outputWriter.print("\r\n"); - // log(" " + CookieTools.getCookieHeaderName(cookie) + ": " + - // CookieTools.getCookieHeaderValue(cookie)); + // System.out.println(" " + + // CookieTools.getCookieHeaderName(cookie) + + // ": " + + // CookieTools.getCookieHeaderValue(cookie)); } } // Send a terminating blank line to mark the end of the headers outputWriter.print("\r\n"); outputWriter.flush(); + // System.out.println("----------"); // The response is now committed committed = true; 1.7 +5 -4 jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/connector/ResponseBase.java Index: ResponseBase.java =================================================================== RCS file: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/connector/ResponseBase.java,v retrieving revision 1.6 retrieving revision 1.7 diff -u -r1.6 -r1.7 --- ResponseBase.java 2000/10/28 19:02:56 1.6 +++ ResponseBase.java 2000/12/01 02:11:21 1.7 @@ -1,7 +1,7 @@ /* - * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/connector/ResponseBase.java,v 1.6 2000/10/28 19:02:56 craigmcc Exp $ - * $Revision: 1.6 $ - * $Date: 2000/10/28 19:02:56 $ + * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/connector/ResponseBase.java,v 1.7 2000/12/01 02:11:21 craigmcc Exp $ + * $Revision: 1.7 $ + * $Date: 2000/12/01 02:11:21 $ * * ==================================================================== * @@ -88,7 +88,7 @@ * the connector-specific methods need to be implemented. * * @author Craig R. McClanahan - * @version $Revision: 1.6 $ $Date: 2000/10/28 19:02:56 $ + * @version $Revision: 1.7 $ $Date: 2000/12/01 02:11:21 $ */ public abstract class ResponseBase @@ -380,6 +380,7 @@ // flush the necessary headers if (this.stream == null) { ServletOutputStream sos = getOutputStream(); + sos.flush(); sos.close(); return; } 1.20 +1 -0 jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/core/LocalStrings.properties Index: LocalStrings.properties =================================================================== RCS file: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/core/LocalStrings.properties,v retrieving revision 1.19 retrieving revision 1.20 diff -u -r1.19 -r1.20 --- LocalStrings.properties 2000/11/25 00:57:24 1.19 +++ LocalStrings.properties 2000/12/01 02:11:22 1.20 @@ -43,6 +43,7 @@ standardContext.managerLoad=Exception loading sessions from persistent storage standardContext.managerUnload=Exception unloading sessions to persistent storage standardContext.mappingError=MAPPING configuration error for relative URI {0} +standardContext.notFound=The requested resource ({0}) is not available. standardContext.notReloadable=Reloading is disabled on this Context standardContext.notStarted=Context has not yet been started standardContext.notWrapper=Child of a Context must be a Wrapper 1.5 +65 -7 jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/core/StandardContextValve.java Index: StandardContextValve.java =================================================================== RCS file: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/core/StandardContextValve.java,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- StandardContextValve.java 2000/11/02 06:14:09 1.4 +++ StandardContextValve.java 2000/12/01 02:11:22 1.5 @@ -1,7 +1,7 @@ /* - * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/core/StandardContextValve.java,v 1.4 2000/11/02 06:14:09 remm Exp $ - * $Revision: 1.4 $ - * $Date: 2000/11/02 06:14:09 $ + * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/core/StandardContextValve.java,v 1.5 2000/12/01 02:11:22 craigmcc Exp $ + * $Revision: 1.5 $ + * $Date: 2000/12/01 02:11:22 $ * * ==================================================================== * @@ -66,6 +66,7 @@ import java.io.IOException; +import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -87,7 +88,7 @@ * when processing HTTP requests. * * @author Craig R. McClanahan - * @version $Revision: 1.4 $ $Date: 2000/11/02 06:14:09 $ + * @version $Revision: 1.5 $ $Date: 2000/12/01 02:11:22 $ */ final class StandardContextValve @@ -147,13 +148,31 @@ return; // NOTE - Not much else we can do generically } + // Disallow any direct access to resources under WEB-INF or META-INF + String contextPath = + ((HttpServletRequest) request.getRequest()).getContextPath(); + String requestURI = + ((HttpServletRequest) request.getRequest()).getRequestURI(); + String relativeURI = + requestURI.substring(contextPath.length()).toUpperCase(); + if (relativeURI.equals("/META-INF") || + relativeURI.equals("/WEB-INF") || + relativeURI.startsWith("/META-INF/") || + relativeURI.startsWith("/WEB-INF/")) { + notFound(requestURI, (HttpServletResponse) response.getResponse()); + try { + response.finishResponse(); + } catch (IOException e) { + ; + } + return; + } + // Select the Wrapper to be used for this Request StandardContext context = (StandardContext) getContainer(); Wrapper wrapper = (Wrapper) context.map(request, true); if (wrapper == null) { - ((HttpServletResponse) response.getResponse()).sendError - (HttpServletResponse.SC_NOT_FOUND, - sm.getString("standardContext.notFound")); + notFound(requestURI, (HttpServletResponse) response.getResponse()); try { response.finishResponse(); } catch (IOException e) { @@ -179,6 +198,45 @@ if (context.isUseNaming()) { // Unbind the thread to the context ContextBindings.unbindThread(context.getName(), context); + } + + } + + + // -------------------------------------------------------- Private Methods + + + /** + * Report a "not found" error for the specified resource. FIXME: We + * should really be using the error reporting settings for this web + * application, but currently that code runs at the wrapper level rather + * than the context level. + * + * @param requestURI The request URI for the requested resource + * @param response The response we are creating + */ + private void notFound(String requestURI, HttpServletResponse response) { + + try { + response.setStatus(HttpServletResponse.SC_NOT_FOUND); + // response.setMessage(requestURI); + response.setContentType("text/html"); + PrintWriter writer = response.getWriter(); + writer.println("<html>"); + writer.println("<head>"); + writer.println("<title>Tomcat Error Report</title>"); + writer.println("<body bgcolor=\"white\">"); + writer.println("<br><br>"); + writer.println("<h1>HTTP Status 404 - " + requestURI + "</h1>"); + writer.println(sm.getString("standardContext.notFound", + requestURI)); + writer.println("</body>"); + writer.println("</html>"); + writer.flush(); + } catch (IllegalStateException e) { + ; + } catch (IOException e) { + ; } }