Author: timw Date: Mon Oct 4 20:33:57 2010 New Revision: 1004409 URL: http://svn.apache.org/viewvc?rev=1004409&view=rev Log: 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).
Modified: tomcat/trunk/java/org/apache/catalina/servlets/WebdavServlet.java Modified: tomcat/trunk/java/org/apache/catalina/servlets/WebdavServlet.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/servlets/WebdavServlet.java?rev=1004409&r1=1004408&r2=1004409&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/servlets/WebdavServlet.java (original) +++ tomcat/trunk/java/org/apache/catalina/servlets/WebdavServlet.java Mon Oct 4 20:33:57 2010 @@ -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:<br/><code> - * <servlet><br/> - * <servlet-name>webdav</servlet-name><br/> - * <servlet-class>org.apache.catalina.servlets.WebdavServlet</servlet-class><br/> - * <init-param><br/> - * <param-name>debug</param-name><br/> - * <param-value>0</param-value><br/> - * </init-param><br/> - * <init-param><br/> - * <param-name>listings</param-name><br/> - * <param-value>true</param-value><br/> - * </init-param><br/> - * </servlet><br/> - * <servlet-mapping><br/> - * <servlet-name>webdav</servlet-name><br/> - * <url-pattern>/*</url-pattern><br/> - * </servlet-mapping> - * </code> * <p/> - * This will enable read only access. To enable read-write access add:<br/> - * <code> - * <init-param><br/> - * <param-name>readonly</param-name><br/> - * <param-value>false</param-value><br/> - * </init-param><br/> - * </code> + * Mapping a subpath (e.g. <code>/webdav/*</code> 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 <code>WEB-INF</code> and <code>META-INF</code> + * directories are protected in this re-mounted resource tree. * <p/> - * To make the content editable via a different URL, using the following - * mapping:<br/> - * <code> - * <servlet-mapping><br/> - * <servlet-name>webdav</servlet-name><br/> - * <url-pattern>/webdavedit/*</url-pattern><br/> + * To enable WebDAV for a context add the following to web.xml: + * <pre> + * <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> - * </code> - * <p/> + * </pre> + * This will enable read only access. To enable read-write access add: + * <pre> + * <init-param> + * <param-name>readonly</param-name> + * <param-value>false</param-value> + * </init-param> + * </pre> + * To make the content editable via a different URL, use the following + * mapping: + * <pre> + * <servlet-mapping> + * <servlet-name>webdav</servlet-name> + * <url-pattern>/webdavedit/*</url-pattern> + * </servlet-mapping> + * </pre> * 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 + * <code>WEB-INF</code> or <code>META-INF</code>. + * @param path the full path of the resource being accessed + * @return <code>true</code> 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<String> 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<String> 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<String> 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 --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org