-
Notifications
You must be signed in to change notification settings - Fork 17.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
x/net/webdav: moving a locked file fails unless destination is locked #43556
Comments
Some follow up thoughts/comments: My findings imply that you can only move a source to a locked destination, which is not correct. The locked resource should simply be renamed, with the lock discarded as per the webdav RFC:
From inspecting the code, it looks like the lock subsystem takes an optional src/dst parameter. If both are set, it tries to take locks on both resources. If only one is set, it takes only that one. In none are set, it takes temporary locks to maintain locking consistency with other clients. In the move handler, since there is a src and dst, it looks for locks in both places, even if dst is not present or unlocked:
So, even though we've only locked src, and dst doesn't exist, the request will fail because we don't have a valid lock on dst. Really, the check should be "if there is no condition for a given resource, take a temporary lock on it", rather than "if there are no conditions, take a temporary lock on all". If there's interest, I can look at implementing something to fix this (as well as #42839). Both issues are currently blocking us, so we need a solution soon (i.e. the next few weeks). I can look at putting up a PR with the fix. I wouldn't mind some guidance from those experienced with this codebase, particularly for this issue, since I think the fix may not be as simple as #42839. |
/cc @bradfitz |
The WebDAV RFC is pretty clear that if the source and destination of a MOVE request are locked, then the request must include lock tokens for both. It doesn't explicitly state that if only one is locked, the request need only include a token for the one, but that seems fairly obvious: if the destination of an operation is not locked, a client should be able to copy or move a locked resource over top of it, particularly if it doesn't exist in the first place. Prior to this commit, the lock validation logic required that both the source and destination of an operation hold a lock if any locks were presented. Consequently, binary operations where only one of the resources were locked would always fail. For example, the following sequence of events would fail with a 412 Precondition Failed: - LOCK /foo - MOVE /foo (Destination: /bar) This commit changes the lock validation to only require locks for resources which are actually locked. It takes some care to ensure that invalid lock tokens will cause a failure, even if the resources did not require locks, since both the litmus test and RFC imply that if there are any conditions, and all conditions fail, the request should fail. Fixes golang/go#43556
I have a potential fix for this. Going to wait for my CLA to go through, but feel free to take a look. |
Change https://golang.org/cl/285754 mentions this issue: |
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
Haven't tried, but it doesn't look like the code in question has changed.
What operating system and processor architecture are you using (
go env
)?go env
OutputWhat did you do?
While running a webdav server using x/net/webdav, I found that any operations which tried to rename a locked file failed unless the client held a lock on the destination file. This seems wrong.
Reproduction steps:
Compile https://github.com/hacdias/webdav (this uses x/net/webdav as its server).
Run the following:
Download/build/install/etc cadaver (a simple tool for running webdav commands)
Run
cadaver http://localhost:8080
In its command prompt, run the following commands:
A
Then run:
B
What did you expect to see?
A should have succeeded --
foo.yaml
shoud be renamed tofoo.yaml.2
:What did you see instead?
A fails, but B succeeds:
The text was updated successfully, but these errors were encountered: