fix(webdav): require credentials and apply the property permission result - #37179
fix(webdav): require credentials and apply the property permission result#37179swicken wants to merge 2 commits into
Conversation
|
Claude finished @swicken's task in 3m 45s —— View job Code Review — WebDAV credentials requirement + property permission fix
I reviewed both guards against the codebase, not just the diff. The design is sound and the two premises hold up:
New IssuesNone blocking. Notes (non-blocking)
Test coverageThe 11 unit tests are focused and cover the meaningful branches (challenge + header, every method, blank/whitespace header, non-HTTP pass-through, credentialed pass-through; no-property / null-set / per-property / allowed / correct-delegation for the authoriser). Overall: clean, well-documented, and the reasoning in the class Javadocs matches what the code actually does. No changes required to merge (the merge-order note vs #37167 in the description still stands). |
…rmission answer The WebDAV endpoints are served by a third-party library whose method handlers do not all consult Resource.authorise(). Two consequences, both measured against a running instance: A request carrying no Authorization header was handled by the handlers that run their own sequence rather than the shared one. Anonymous PROPPATCH answered 207, anonymous OPTIONS answered 200 on every /webdav/ mount, and anonymous LOCK on a legacy language path answered 500. WebDavAuthenticationFilter answers those with the RFC 7235 challenge instead, for every method and whatever the body. The status is set rather than raised as a container error, because web.xml maps 401 to an error page that redirects and a WebDAV client cannot act on a 302. Refusals go to the security log alongside comparable events. PROPPATCH's permission check reported one problem per property named in the request, so a body naming none reported an empty list of problems, which the caller reads as no problem: the resource's answer was obtained and then discarded. WebdavPropertyAuthoriser reports the refusal either way, and DotWebdavServlet installs it, which reaches both handlers that check property permissions. Closes dotCMS/private-issues#672
The filter decides on one header, so the three bodies were three identical runs of the test above it, and the name pointed the reader at the authoriser's behaviour rather than the filter's. WebdavPropertyAuthoriserTest covers the case a body naming no property actually exercises.
8d9545e to
4d8550d
Compare
Summary
The WebDAV endpoints are served by a third-party library whose method handlers do not all
consult
Resource.authorise(...). Two things follow from that, both measured against a runninginstance.
A request carrying no
Authorizationheader is handled by the handlers that run their ownsequence instead of the shared one. Anonymous
PROPPATCHanswered207, anonymousOPTIONSanswered
200on every/webdav/mount point, and anonymousLOCKon a legacy language pathanswered
500. WebDAV in dotCMS resolves every resource against a user, so there is nothing onthese endpoints to serve a caller who has not identified themselves. This adds a filter on
/webdav/*that answers those with the RFC 7235 challenge instead.Separately, the permission check for
PROPPATCHreports one problem per property named in therequest, so a body naming none reports an empty list of problems, which the caller reads as no
problem: the resource's answer is obtained and then discarded.
WebdavPropertyAuthoriserreportsthe refusal either way, and
DotWebdavServletinstalls it through the library's own extensionpoint, which reaches both handlers that check property permissions.
Behaviour
/webdav/*with noAuthorizationheader, or a blank one, gets401withWWW-Authenticate: Basic. Every method, whatever the body.web.xmlmaps401to/html/error/custom-error-page.jsp, which redirects, and a WebDAV client has nothing it can dowith a
302to a login page.OPTIONSis not exempt. Being challenged on the first request is how a WebDAV client learns tosend credentials at all.
without a session.
PROPFINDwith and without a body,OPTIONS,MKCOL,PUT,GET,PROPPATCH,LOCKandDELETEall behave as they did before.PROPPATCHwhose body names no property is now refused for a caller holding no permission onthe resource, instead of answering
207.Merge order with #37167
Both branches add a
<filter>and a<filter-mapping>immediately afterNormalizationFilter,so
web.xmlwill conflict. #37167 should land first. When this branch is rebased, keep bothfilters and map
WebDavAuthenticationFilterbeforeWebDavXmlValidationFilter: there is noreason to buffer and parse a body for a caller who is about to be refused. The
<servlet-class>change here is in a part of the file #37167 does not touch and merges cleanly.
Two filters on the same path is deliberate. One asks whether there is a caller at all, by reading
a single header; the other asks whether the body is shaped the way RFC 4918 says, and has to
buffer and parse to answer. Merging them would put an XML parse behind a credentials check in one
class for no gain.
Testing
11 unit tests.
WebDavAuthenticationFilterTest(6) covers the challenge and its header, everyWebDAV method, a blank
Authorizationheader, non-HTTP pass-through, and pass-through for arequest that does carry credentials.
WebdavPropertyAuthoriserTest(5) covers refusal when noproperty was named, when the name set is null, one refusal per named property, and the allowed
case reporting nothing.
Against a running instance, before and after the change: anonymous
PROPPATCHon three mountpoints with three different no-property bodies went
207→401, anonymousOPTIONS200→401, anonymousLOCKon the legacy language path500→401, and nine functional checkscovering the traffic a real client sends are unchanged. Each guard was also verified by reverting
it and confirming the tests fail.
Not covered: no real desktop client was tested. Finder, Explorer and Office now meet a challenge
on
OPTIONSwhere they previously got a200. That is the standard handshake and every clientimplements it, but it is reasoning rather than a measurement. There is also no CI coverage for
these methods — the
WebDavPostman collection sends Basic auth on every request, so itexercises the authenticated path only.
Closes dotCMS/private-issues#672