From: timw Date: Mon, 4 Oct 2010 20:33:57 +0000 (+0000) Subject: Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=50026 for WebdavServlet X-Git-Url: https://git.internetallee.de/?a=commitdiff_plain;h=a657c08b40fe952577abdd9096e61a4f9427adf1;p=tomcat7.0 Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=50026 for WebdavServlet Factored checking of special WEB-INF and META-INF paths into service to trap requests for GET methods handled by DefaultServlet (which does not check access). Retained checking of special paths in handlers for copy, delete, move (copy + delete), and in enumeration of resources (propfind). git-svn-id: https://svn.apache.org/repos/asf/tomcat/trunk@1004409 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/java/org/apache/catalina/servlets/WebdavServlet.java b/java/org/apache/catalina/servlets/WebdavServlet.java index 403be89ad..fb4054ca8 100644 --- a/java/org/apache/catalina/servlets/WebdavServlet.java +++ b/java/org/apache/catalina/servlets/WebdavServlet.java @@ -71,42 +71,46 @@ import org.xml.sax.SAXException; * Servlet which adds support for WebDAV level 2. All the basic HTTP requests * are handled by the DefaultServlet. The WebDAVServlet must not be used as the * default servlet (ie mapped to '/') as it will not work in this configuration. - * To enable WebDAV for a context add the following to web.xml:
- * <servlet>
- * <servlet-name>webdav</servlet-name>
- * <servlet-class>org.apache.catalina.servlets.WebdavServlet</servlet-class>
- * <init-param>
- * <param-name>debug</param-name>
- * <param-value>0</param-value>
- * </init-param>
- * <init-param>
- * <param-name>listings</param-name>
- * <param-value>true</param-value>
- * </init-param>
- * </servlet>
- * <servlet-mapping>
- * <servlet-name>webdav</servlet-name>
- * <url-pattern>/*</url-pattern>
- * </servlet-mapping> - *
*

- * This will enable read only access. To enable read-write access add:
- * - * <init-param>
- * <param-name>readonly</param-name>
- * <param-value>false</param-value>
- * </init-param>
- *
+ * Mapping a subpath (e.g. /webdav/* to this servlet has the effect + * of re-mounting the entire web application under that sub-path, with WebDAV + * access to all the resources. This WEB-INF and META-INF + * directories are protected in this re-mounted resource tree. *

- * To make the content editable via a different URL, using the following - * mapping:
- * - * <servlet-mapping>
- * <servlet-name>webdav</servlet-name>
- * <url-pattern>/webdavedit/*</url-pattern>
+ * To enable WebDAV for a context add the following to web.xml: + *

+ * <servlet>
+ *  <servlet-name>webdav</servlet-name>
+ *  <servlet-class>org.apache.catalina.servlets.WebdavServlet</servlet-class>
+ *    <init-param>
+ *      <param-name>debug</param-name>
+ *      <param-value>0</param-value>
+ *    </init-param>
+ *    <init-param>
+ *      <param-name>listings</param-name>
+ *      <param-value>false</param-value>
+ *    </init-param>
+ *  </servlet>
+ *  <servlet-mapping>
+ *    <servlet-name>webdav</servlet-name>
+ *    <url-pattern>/*</url-pattern>
  *  </servlet-mapping>
- * 
- * 

+ *

+ * This will enable read only access. To enable read-write access add: + *
+ *  <init-param>
+ *    <param-name>readonly</param-name>
+ *    <param-value>false</param-value>
+ *  </init-param>
+ * 
+ * To make the content editable via a different URL, use the following + * mapping: + *
+ *  <servlet-mapping>
+ *    <servlet-name>webdav</servlet-name>
+ *    <url-pattern>/webdavedit/*</url-pattern>
+ *  </servlet-mapping>
+ * 
* Don't forget to secure access appropriately to the editing URLs. With this * configuration the context will be accessible to normal users as before. Those * users with the necessary access will be able to edit content available via @@ -315,10 +319,21 @@ public class WebdavServlet protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - String method = req.getMethod(); + final String path = getRelativePath(req); + + // Block access to special subdirectories. + // DefaultServlet assumes it services resources from the root of the web app + // and doesn't add any special path protection + // WebdavServlet remounts the webapp under a new path, so this check is + // necessary on all methods (including GET). + if (isSpecialPath(path)) { + resp.sendError(WebdavStatus.SC_NOT_FOUND); + return; + } + + final String method = req.getMethod(); if (debug > 0) { - String path = getRelativePath(req); log("[" + method + "] " + path); } @@ -345,6 +360,19 @@ public class WebdavServlet /** + * Checks whether a given path refers to a resource under + * WEB-INF or META-INF. + * @param path the full path of the resource being accessed + * @return true if the resource specified is under a special path + */ + private static final boolean isSpecialPath(final String path) { + // FIXME: why isn't this just equalsIgnoreCase? + return path.toUpperCase(Locale.ENGLISH).startsWith("/WEB-INF") + || path.toUpperCase(Locale.ENGLISH).startsWith("/META-INF"); + } + + + /** * Check if the conditions specified in the optional If headers are * satisfied. * @@ -442,12 +470,6 @@ public class WebdavServlet if (path.endsWith("/")) path = path.substring(0, path.length() - 1); - if ((path.toUpperCase(Locale.ENGLISH).startsWith("/WEB-INF")) || - (path.toUpperCase(Locale.ENGLISH).startsWith("/META-INF"))) { - resp.sendError(WebdavStatus.SC_FORBIDDEN); - return; - } - // Properties which are to be displayed. Vector properties = null; // Propfind depth @@ -719,12 +741,6 @@ public class WebdavServlet String path = getRelativePath(req); - if ((path.toUpperCase(Locale.ENGLISH).startsWith("/WEB-INF")) || - (path.toUpperCase(Locale.ENGLISH).startsWith("/META-INF"))) { - resp.sendError(WebdavStatus.SC_FORBIDDEN); - return; - } - boolean exists = true; try { resources.lookup(path); @@ -1601,20 +1617,14 @@ public class WebdavServlet if (debug > 0) log("Dest path :" + destinationPath); - if ((destinationPath.toUpperCase(Locale.ENGLISH).startsWith("/WEB-INF")) || - (destinationPath.toUpperCase(Locale.ENGLISH).startsWith("/META-INF"))) { + // Check destination path to protect special subdirectories + if (isSpecialPath(destinationPath)) { resp.sendError(WebdavStatus.SC_FORBIDDEN); return false; } String path = getRelativePath(req); - if ((path.toUpperCase(Locale.ENGLISH).startsWith("/WEB-INF")) || - (path.toUpperCase(Locale.ENGLISH).startsWith("/META-INF"))) { - resp.sendError(WebdavStatus.SC_FORBIDDEN); - return false; - } - if (destinationPath.equals(path)) { resp.sendError(WebdavStatus.SC_FORBIDDEN); return false; @@ -1810,12 +1820,6 @@ public class WebdavServlet HttpServletResponse resp, boolean setStatus) throws IOException { - if ((path.toUpperCase(Locale.ENGLISH).startsWith("/WEB-INF")) || - (path.toUpperCase(Locale.ENGLISH).startsWith("/META-INF"))) { - resp.sendError(WebdavStatus.SC_FORBIDDEN); - return false; - } - String ifHeader = req.getHeader("If"); if (ifHeader == null) ifHeader = ""; @@ -1895,8 +1899,8 @@ public class WebdavServlet if (debug > 1) log("Delete:" + path); - if ((path.toUpperCase(Locale.ENGLISH).startsWith("/WEB-INF")) || - (path.toUpperCase(Locale.ENGLISH).startsWith("/META-INF"))) { + // Prevent deletion of special subdirectories + if (isSpecialPath(path)) { errorList.put(path, new Integer(WebdavStatus.SC_FORBIDDEN)); return; } @@ -2034,9 +2038,7 @@ public class WebdavServlet Vector propertiesVector) { // Exclude any resource in the /WEB-INF and /META-INF subdirectories - // (the "toUpperCase()" avoids problems on Windows systems) - if (path.toUpperCase(Locale.ENGLISH).startsWith("/WEB-INF") || - path.toUpperCase(Locale.ENGLISH).startsWith("/META-INF")) + if (isSpecialPath(path)) return; CacheEntry cacheEntry = resources.lookupCache(path); @@ -2327,9 +2329,7 @@ public class WebdavServlet Vector propertiesVector) { // Exclude any resource in the /WEB-INF and /META-INF subdirectories - // (the "toUpperCase()" avoids problems on Windows systems) - if (path.toUpperCase(Locale.ENGLISH).startsWith("/WEB-INF") || - path.toUpperCase(Locale.ENGLISH).startsWith("/META-INF")) + if (isSpecialPath(path)) return; // Retrieving the lock associated with the lock-null resource