You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2025/01/21 07:53:05 UTC
(tomcat) branch 9.0.x updated (31a75f5ec2 -> 4bbc4c2b05)
This is an automated email from the ASF dual-hosted git repository.
markt pushed a change to branch 9.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
from 31a75f5ec2 Use correct log
new 603a959d18 serveSubpathOnly should apply to destinations as well
new 34679ae8aa Expand the WebDAV Javadoc
new 4bbc4c2b05 Add a note about WebDAV
The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
.../apache/catalina/servlets/WebdavServlet.java | 37 ++++++++---
.../catalina/servlets/TestWebdavServlet.java | 77 +++++++++++++++++++++-
webapps/docs/changelog.xml | 5 ++
webapps/docs/security-howto.xml | 4 ++
4 files changed, 113 insertions(+), 10 deletions(-)
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org
(tomcat) 02/03: Expand the WebDAV Javadoc
Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
markt pushed a commit to branch 9.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit 34679ae8aab2f0899ede2867cad49ccf4e9a20da
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Mon Jan 20 17:12:41 2025 +0000
Expand the WebDAV Javadoc
---
.../apache/catalina/servlets/WebdavServlet.java | 30 ++++++++++++++++------
1 file changed, 22 insertions(+), 8 deletions(-)
diff --git a/java/org/apache/catalina/servlets/WebdavServlet.java b/java/org/apache/catalina/servlets/WebdavServlet.java
index a1af063378..4db0720702 100644
--- a/java/org/apache/catalina/servlets/WebdavServlet.java
+++ b/java/org/apache/catalina/servlets/WebdavServlet.java
@@ -73,15 +73,29 @@ import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
/**
- * Servlet which adds support for <a href="https://tools.ietf.org/html/rfc4918">WebDAV</a>
+ * This servlet adds support for <a href="https://tools.ietf.org/html/rfc4918">WebDAV</a>
* <a href="https://tools.ietf.org/html/rfc4918#section-18">level 3</a>. 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.
+ * DefaultServlet.
* <p>
- * 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. To restore the DefaultServlet behavior set
- * <code>serveSubpathOnly</code> to <code>true</code>. The <code>WEB-INF</code> and <code>META-INF</code> directories
- * are protected in this re-mounted resource tree.
+ * The WebDAV servlet is only designed for use with path mapping. The WebdavServlet must not be used as the default
+ * servlet (i.e. mapped to '/') or with any other mapping types as it will not work in those configurations.
+ * <p>
+ * By default, the entire web application is exposed via the WebDAV servlet. Mapping the WebDAV servlet to
+ * <code>/*</code> provides WebDAV access to all the resources within the web application. To aid separation of normal
+ * users and WebDAV users, the WebDAV servlet may be mounted at a sub-path (e.g. <code>/webdav/*</code>) which creates
+ * an additional mapping for the entire web application under that sub-path, with WebDAV access to all the resources.
+ * <p>
+ * By default, the <code>WEB-INF</code> and <code>META-INF</code> directories are not accessible via WebDAV. This may
+ * be changed by setting the <code>allowSpecialPaths</code> initialisation parameter to <code>true</code>.
+ * <p>
+ * It is also possible to enable WebDAV access to a sub-set of the standard web application URL space rather than
+ * creating an additional, WebDAV specific mapping. To do this, map the WebDAV servlet to the desired sub-path and set
+ * the <code>serveSubpathOnly</code> initialisation parameter to <code>true</code>.
+ * <p>
+ * Security constraints using the same URL pattern as the mapping (e.g. <code>/webdav/*</code>) can be used to limit the
+ * users with access to WebDAV functionality. Care is required if using security constraints to further limit WebDAV
+ * functionality. In particular, administrators should be aware that security constraints apply only to the request URL.
+ * Security constraints do not apply to any destination URL associated with the WebDAV operation (such as COPY or MOVE).
* <p>
* To enable WebDAV for a context add the following to web.xml:
*
@@ -140,7 +154,7 @@ import org.xml.sax.SAXException;
* values are not protected by the server, such as the content length of a resource). By default the Servlet will use
* non persistent memory storage for them. Persistence can be achieved by implementing the <code>PropertyStore</code>
* interface and configuring the Servlet to use that store. The <code>propertyStore</code> init-param allows configuring
- * the classname of the store to use, while the parameters in the form of <code>store.xxx</code> will be set on the
+ * the class name of the store to use, while the parameters in the form of <code>store.xxx</code> will be set on the
* store object as bean properties. For example, this would configure a store with class
* <code>com.MyPropertyStore</code>, and set its property <code>myName</code> to value <code>myValue</code>:
*
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org
(tomcat) 03/03: Add a note about WebDAV
Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
markt pushed a commit to branch 9.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit 4bbc4c2b053fa44b49173c1386b49842de5950c5
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Mon Jan 20 17:12:56 2025 +0000
Add a note about WebDAV
---
webapps/docs/security-howto.xml | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/webapps/docs/security-howto.xml b/webapps/docs/security-howto.xml
index bcd90f07bf..1747984313 100644
--- a/webapps/docs/security-howto.xml
+++ b/webapps/docs/security-howto.xml
@@ -579,6 +579,10 @@
headers it sets unless your application is already setting them. If Tomcat
is accessed via a reverse proxy, then the configuration of this filter needs
to be co-ordinated with any headers that the reverse proxy sets.</p>
+
+ <p>The WebDAV servlet enables edit functionality for web application
+ content. If the WebDAV servlet is enabled, the WebDAV functionality should
+ be appropriately secured.</p>
</section>
<section name="Embedded Tomcat">
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org
(tomcat) 01/03: serveSubpathOnly should apply to destinations as well
Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
markt pushed a commit to branch 9.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit 603a959d18cf2e05f00956e4d91de7a49b99a674
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Mon Jan 20 16:40:44 2025 +0000
serveSubpathOnly should apply to destinations as well
When using the WebDAV servlet with serveSubpathOnly set to true, ensure
that the destination for any requested WebDAV operation is also
restricted to the sub-path.
---
.../apache/catalina/servlets/WebdavServlet.java | 7 +-
.../catalina/servlets/TestWebdavServlet.java | 77 +++++++++++++++++++++-
webapps/docs/changelog.xml | 5 ++
3 files changed, 87 insertions(+), 2 deletions(-)
diff --git a/java/org/apache/catalina/servlets/WebdavServlet.java b/java/org/apache/catalina/servlets/WebdavServlet.java
index 98737e0329..a1af063378 100644
--- a/java/org/apache/catalina/servlets/WebdavServlet.java
+++ b/java/org/apache/catalina/servlets/WebdavServlet.java
@@ -2085,7 +2085,12 @@ public class WebdavServlet extends DefaultServlet implements PeriodicEventListen
// Cross-context operations aren't supported
String reqContextPath = getPathPrefix(req);
- if (!destinationPath.startsWith(reqContextPath + "/")) {
+ String expectedTargetPath = reqContextPath;
+ // Also ensure copy (and move) operations do not escape the configured sub-path when limited to the sub-path
+ if (serveSubpathOnly && req.getServletPath() != null) {
+ expectedTargetPath = expectedTargetPath + req.getServletPath();
+ }
+ if (!destinationPath.startsWith(expectedTargetPath + "/")) {
resp.sendError(WebdavStatus.SC_FORBIDDEN);
return false;
}
diff --git a/test/org/apache/catalina/servlets/TestWebdavServlet.java b/test/org/apache/catalina/servlets/TestWebdavServlet.java
index 084cfcdf74..1c1bd53e3c 100644
--- a/test/org/apache/catalina/servlets/TestWebdavServlet.java
+++ b/test/org/apache/catalina/servlets/TestWebdavServlet.java
@@ -689,9 +689,84 @@ public class TestWebdavServlet extends TomcatBaseTest {
Assert.assertEquals(WebdavStatus.SC_MULTI_STATUS, client.getStatusCode());
Assert.assertFalse(client.getResponseBody().contains("/myfolder"));
validateXml(client.getResponseBody());
-
}
+
+ @Test
+ public void testCopyOutsideSubpath() throws Exception {
+ Tomcat tomcat = getTomcatInstance();
+
+ // Create a temp webapp that can be safely written to
+ File tempWebapp = new File(getTemporaryDirectory(), "webdav-subpath");
+ File subPath = new File(tempWebapp, "aaa");
+ Assert.assertTrue(subPath.mkdirs());
+
+ Context ctxt = tomcat.addContext("", tempWebapp.getAbsolutePath());
+ Wrapper webdavServlet = Tomcat.addServlet(ctxt, "webdav", new WebdavServlet());
+ webdavServlet.addInitParameter("listings", "true");
+ webdavServlet.addInitParameter("readonly", "false");
+ webdavServlet.addInitParameter("serveSubpathOnly", "true");
+ ctxt.addServletMappingDecoded("/aaa/*", "webdav");
+ tomcat.start();
+
+ ctxt.getResources().setCacheMaxSize(10);
+ ctxt.getResources().setCacheObjectMaxSize(1);
+
+ Client client = new Client();
+ client.setPort(getPort());
+
+ // Create a file
+ client.setRequest(new String[] { "PUT /aaa/file1.txt HTTP/1.1" + SimpleHttpClient.CRLF +
+ "Host: localhost:" + getPort() + SimpleHttpClient.CRLF +
+ "Content-Length: 6" + SimpleHttpClient.CRLF +
+ "Connection: Close" + SimpleHttpClient.CRLF +
+ SimpleHttpClient.CRLF + CONTENT });
+ client.connect();
+ client.processRequest(true);
+ Assert.assertEquals(HttpServletResponse.SC_CREATED, client.getStatusCode());
+
+ // Copy file1.txt to file2.txt
+ client.setRequest(new String[] { "COPY /aaa/file1.txt HTTP/1.1" + SimpleHttpClient.CRLF +
+ "Host: localhost:" + getPort() + SimpleHttpClient.CRLF +
+ "Destination: http://localhost:" + getPort() + "/aaa/file2.txt" + SimpleHttpClient.CRLF +
+ "Connection: Close" + SimpleHttpClient.CRLF +
+ SimpleHttpClient.CRLF });
+ client.connect();
+ client.processRequest(true);
+ Assert.assertEquals(HttpServletResponse.SC_CREATED, client.getStatusCode());
+
+ // Move file2.txt to file3.txt
+ client.setRequest(new String[] { "MOVE /aaa/file2.txt HTTP/1.1" + SimpleHttpClient.CRLF +
+ "Host: localhost:" + getPort() + SimpleHttpClient.CRLF +
+ "Destination: http://localhost:" + getPort() + "/aaa/file3.txt" + SimpleHttpClient.CRLF +
+ "Connection: Close" + SimpleHttpClient.CRLF +
+ SimpleHttpClient.CRLF });
+ client.connect();
+ client.processRequest(true);
+ Assert.assertEquals(HttpServletResponse.SC_CREATED, client.getStatusCode());
+
+ // Copy file1.txt outside sub-path
+ client.setRequest(new String[] { "COPY /aaa/file1.txt HTTP/1.1" + SimpleHttpClient.CRLF +
+ "Host: localhost:" + getPort() + SimpleHttpClient.CRLF +
+ "Destination: http://localhost:" + getPort() + "/file1.txt" + SimpleHttpClient.CRLF +
+ "Connection: Close" + SimpleHttpClient.CRLF +
+ SimpleHttpClient.CRLF });
+ client.connect();
+ client.processRequest(true);
+ Assert.assertEquals(HttpServletResponse.SC_FORBIDDEN, client.getStatusCode());
+
+ // Move file1.txt outside sub-path
+ client.setRequest(new String[] { "MOVE /aaa/file1.txt HTTP/1.1" + SimpleHttpClient.CRLF +
+ "Host: localhost:" + getPort() + SimpleHttpClient.CRLF +
+ "Destination: http://localhost:" + getPort() + "/file1.txt" + SimpleHttpClient.CRLF +
+ "Connection: Close" + SimpleHttpClient.CRLF +
+ SimpleHttpClient.CRLF });
+ client.connect();
+ client.processRequest(true);
+ Assert.assertEquals(HttpServletResponse.SC_FORBIDDEN, client.getStatusCode());
+}
+
+
@Test
public void testSharedLocks() throws Exception {
Tomcat tomcat = getTomcatInstance();
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index b757d2b441..2ad10b243c 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -154,6 +154,11 @@
<code>CrawlerSessionManagerValve</code>. Submitted by Brian Matzon.
(remm)
</fix>
+ <fix>
+ When using the WebDAV servlet with <code>serveSubpathOnly</code> set to
+ <code>true</code>, ensure that the destination for any requested WebDAV
+ operation is also restricted to the sub-path. (markt)
+ </fix>
</changelog>
</subsection>
<subsection name="Coyote">
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org