Feature #1818
closedadd RFC-compliant LOCK support to mod_webdav
Description
The Litmus WebDAV test suite issues certain PUT requests, which is seemed to not processed by Lighty at all. A wireshark dump (see attachement) shows that the request is send, but Lighty does not respond (neither with mod_dav, nor plainly) in any way. Switching all request/response debugging on did not show any log messages.
The issue was tested and occurs with Litmus 0.11 and 0.12.1. The attached file shows an extract of the Wireshark dump of a Litmus 0.11 session. The LOCK request before the PUT works fine. No response to the PUT request is issued.
Files
Updated by gstrauss over 8 years ago
- Priority changed from High to Low
Lighttpd 1.4.x mod_webdav does not properly support LOCK -- it fakes it. This is documented in mod_webdav.c. Not supporting LOCK is definitely a bug because lighttpd advertises "DAV: 1,2" in response to an OPTIONS request, and Class 2 is LOCK support. lighttpd is lying when it advertises that it supports LOCK. Attempting to fake LOCK support was apparently(?) done as a minimal effort to support webdav requests from Microsoft Windows XP as webdav client. (Can anyone confirm that?) Changing lighttpd to advertise only "DAV: 1" might break some client (unverified). On the other hand, implementing proper LOCK support in mod_webdav.c is a lot more than a bug fix. Moving this ticket to Low priority.
FYI: most (not all) other Litmus 0.13 tests pass, excepting the LOCK tests, where most of the tests fail.
(BTW, the segmentation fault in /usr/bin/litmus is a bug in /usr/bin/litmus. I'll be submitting a patch upstream to fix that.)
$ /usr/bin/litmus -k http://127.0.0.1:8080/ -d /home/lighttpd/opt/srv/www -> running `basic': 0. init.................. pass 1. begin................. pass 2. options............... pass 3. put_get............... pass 4. put_get_utf8_segment.. pass 5. put_no_parent......... pass 6. mkcol_over_plain...... pass 7. delete................ pass 8. delete_null........... pass 9. delete_fragment....... WARNING: DELETE removed collection resource with Request-URI including fragment; unsafe ...................... pass (with 1 warning) 10. mkcol................. pass 11. mkcol_again........... pass 12. delete_coll........... pass 13. mkcol_no_parent....... pass 14. mkcol_with_body....... pass 15. finish................ pass <- summary for `basic': of 16 tests run: 16 passed, 0 failed. 100.0% -> 1 warning was issued. -> running `copymove': 0. init.................. pass 1. begin................. pass 2. copy_init............. pass 3. copy_simple........... pass 4. copy_overwrite........ WARNING: COPY to existing resource should give 204 (RFC2518:S8.8.5), got 201 Created ...................... pass (with 1 warning) 5. copy_nodestcoll....... pass 6. copy_cleanup.......... pass 7. copy_coll............. pass 8. copy_shallow.......... pass 9. move.................. WARNING: MOVE to existing collection resource didn't give 204 ...................... pass (with 1 warning) 10. move_coll............. pass 11. move_cleanup.......... pass 12. finish................ pass <- summary for `copymove': of 13 tests run: 13 passed, 0 failed. 100.0% -> 2 warnings were issued. -> running `props': 0. init.................. pass 1. begin................. pass 2. propfind_invalid...... pass 3. propfind_invalid2..... FAIL (PROPFIND with invalid namespace declaration in body (see FAQ) got 207 response not 400) 4. propfind_d0........... pass 5. propinit.............. pass 6. propset............... pass 7. propget............... pass 8. propextended.......... pass 9. propmove.............. pass 10. propget............... FAIL (No value given for property {http://example.com/neon/litmus/}prop9) 11. propdeletes........... pass 12. propget............... pass 13. propreplace........... pass 14. propget............... pass 15. propnullns............ pass 16. propget............... pass 17. prophighunicode....... pass 18. propget............... pass 19. propremoveset......... pass 20. propget............... pass 21. propsetremove......... pass 22. propget............... pass 23. propvalnspace......... pass 24. propwformed........... pass 25. propinit.............. pass 26. propmanyns............ pass 27. propget............... pass 28. propcleanup........... pass 29. finish................ pass <- summary for `props': of 30 tests run: 28 passed, 2 failed. 93.3% -> running `locks': 0. init.................. pass 1. begin................. pass 2. options............... pass 3. precond............... pass 4. init_locks............ pass 5. put................... pass 6. lock_excl............. pass 7. discover.............. pass 8. refresh............... pass 9. notowner_modify....... FAIL (DELETE of locked resource should fail) 10. notowner_lock......... FAIL (LOCK on locked resource) 11. owner_modify.......... pass 12. notowner_modify....... FAIL (DELETE of locked resource should fail) 13. notowner_lock......... FAIL (LOCK on locked resource) 14. copy.................. FAIL (could not COPY locked resource: 404 Not Found) 15. cond_put.............. SKIPPED 16. fail_cond_put......... SKIPPED 17. cond_put_with_not..... pass 18. cond_put_corrupt_token FAIL (conditional PUT with invalid lock-token should fail: 200 OK) 19. complex_cond_put...... SKIPPED 20. fail_complex_cond_put. SKIPPED 21. unlock................ FAIL (UNLOCK on `/litmus/lockme': 401 Unauthorized) 22. fail_cond_put_unlocked FAIL (conditional PUT with invalid lock-token should fail: 200 OK) 23. lock_shared........... pass 24. notowner_modify....... FAIL (DELETE of locked resource should fail) 25. notowner_lock......... FAIL (LOCK on locked resource) 26. owner_modify.......... pass 27. double_sharedlock..... FAIL (unlock of second shared lock: 401 Unauthorized) 28. notowner_modify....... FAIL (DELETE of locked resource should fail) 29. notowner_lock......... FAIL (LOCK on locked resource) 30. unlock................ FAIL (UNLOCK on `/litmus/lockme': 401 Unauthorized) 31. prep_collection....... FAILED - segmentation fault /usr/bin/litmus: line 47: 18368 Segmentation fault (core dumped) ${tprog} --htdocs ${HTDOCS} "$@" -> running `http': 0. init.................. pass 1. begin................. pass 2. expect100............. pass 3. finish................ pass <- summary for `http': of 4 tests run: 4 passed, 0 failed. 100.0%
Updated by gstrauss over 8 years ago
- Tracker changed from Bug to Feature
- Subject changed from A certain PUT request not handled at all to add RFC-compliant LOCK support to mod_webdav
changed ticket to feature request and updated title
The mod_webdav DAV: 1,2 advertisement was added to minimally support some clients, so removing it risks breaking existing installations.
Updated by gstrauss over 8 years ago
$ /usr/bin/litmus -k http://127.0.0.1:8080/ -d /home/lighttpd/opt/srv/www -> running `basic': 0. init.................. pass 1. begin................. pass 2. options............... pass 3. put_get............... pass 4. put_get_utf8_segment.. pass 5. put_no_parent......... pass 6. mkcol_over_plain...... pass 7. delete................ pass 8. delete_null........... pass 9. delete_fragment....... WARNING: DELETE removed collection resource with Request-URI including fragment; unsafe ...................... pass (with 1 warning) 10. mkcol................. pass 11. mkcol_again........... pass 12. delete_coll........... pass 13. mkcol_no_parent....... pass 14. mkcol_with_body....... pass 15. finish................ pass <- summary for `basic': of 16 tests run: 16 passed, 0 failed. 100.0% -> 1 warning was issued. -> running `copymove': 0. init.................. pass 1. begin................. pass 2. copy_init............. pass 3. copy_simple........... pass 4. copy_overwrite........ WARNING: COPY to existing resource should give 204 (RFC2518:S8.8.5), got 201 Created ...................... pass (with 1 warning) 5. copy_nodestcoll....... pass 6. copy_cleanup.......... pass 7. copy_coll............. pass 8. copy_shallow.......... pass 9. move.................. WARNING: MOVE to existing collection resource didn't give 204 WARNING: Could not clean up `/litmus/movecoll' ...................... pass (with 2 warnings) 10. move_coll............. pass 11. move_cleanup.......... pass 12. finish................ pass <- summary for `copymove': of 13 tests run: 13 passed, 0 failed. 100.0% -> 3 warnings were issued. -> running `props': 0. init.................. pass 1. begin................. pass 2. propfind_invalid...... pass 3. propfind_invalid2..... FAIL (PROPFIND with invalid namespace declaration in body (see FAQ) got 207 response not 400) 4. propfind_d0........... pass 5. propinit.............. pass 6. propset............... pass 7. propget............... pass 8. propextended.......... pass 9. propmove.............. pass 10. propget............... pass 11. propdeletes........... pass 12. propget............... pass 13. propreplace........... pass 14. propget............... pass 15. propnullns............ pass 16. propget............... pass 17. prophighunicode....... pass 18. propget............... pass 19. propremoveset......... pass 20. propget............... pass 21. propsetremove......... pass 22. propget............... pass 23. propvalnspace......... pass 24. propwformed........... pass 25. propinit.............. pass 26. propmanyns............ pass 27. propget............... pass 28. propcleanup........... pass 29. finish................ pass <- summary for `props': of 30 tests run: 29 passed, 1 failed. 96.7% -> running `locks': 0. init.................. pass 1. begin................. pass 2. options............... pass 3. precond............... pass 4. init_locks............ pass 5. put................... pass 6. lock_excl............. pass 7. discover.............. pass 8. refresh............... pass 9. notowner_modify....... pass 10. notowner_lock......... pass 11. owner_modify.......... pass 12. notowner_modify....... pass 13. notowner_lock......... pass 14. copy.................. pass 15. cond_put.............. SKIPPED 16. fail_cond_put......... SKIPPED 17. cond_put_with_not..... pass 18. cond_put_corrupt_token FAIL (conditional PUT with invalid lock-token should fail: 200 OK) 19. complex_cond_put...... SKIPPED 20. fail_complex_cond_put. SKIPPED 21. unlock................ pass 22. fail_cond_put_unlocked FAIL (conditional PUT with invalid lock-token should fail: 200 OK) 23. lock_shared........... pass 24. notowner_modify....... pass 25. notowner_lock......... pass 26. owner_modify.......... pass 27. double_sharedlock..... FAIL (shared LOCK on locked resource: 423 Locked) 28. notowner_modify....... pass 29. notowner_lock......... pass 30. unlock................ pass 31. prep_collection....... pass 32. lock_collection....... FAIL (LOCK on `/litmus/lockcoll/': 409 Conflict) 33. owner_modify.......... SKIPPED 34. notowner_modify....... SKIPPED 35. refresh............... SKIPPED 36. indirect_refresh...... SKIPPED 37. unlock................ SKIPPED 38. unmapped_lock......... pass 39. unlock................ pass 40. finish................ pass -> 9 tests were skipped. <- summary for `locks': of 32 tests run: 28 passed, 4 failed. 87.5% -> running `http': 0. init.................. pass 1. begin................. pass 2. expect100............. pass 3. finish................ pass <- summary for `http': of 4 tests run: 4 passed, 0 failed. 100.0%
Updated by gstrauss over 5 years ago
- Status changed from New to Patch Pending
- Target version set to 1.4.54
Patches pending on development branch. 'litmus' tests are not perfect and still have some bugs of their own, but are a useful set of tests nonetheless. The only remaining 'litmus' test that fails is something that could probably be caught be a strictly-validating XML parser, and does not affect well-behaved webdav clients.
$ /usr/bin/litmus -k http://127.0.0.1:8080/ -d /home/lighttpd/opt/srv/www -> running `basic': 0. init.................. pass 1. begin................. pass 2. options............... pass 3. put_get............... pass 4. put_get_utf8_segment.. pass 5. put_no_parent......... pass 6. mkcol_over_plain...... pass 7. delete................ pass 8. delete_null........... pass 9. delete_fragment....... pass 10. mkcol................. pass 11. mkcol_again........... pass 12. delete_coll........... pass 13. mkcol_no_parent....... pass 14. mkcol_with_body....... pass 15. finish................ pass <- summary for `basic': of 16 tests run: 16 passed, 0 failed. 100.0% -> running `copymove': 0. init.................. pass 1. begin................. pass 2. copy_init............. pass 3. copy_simple........... pass 4. copy_overwrite........ pass 5. copy_nodestcoll....... pass 6. copy_cleanup.......... pass 7. copy_coll............. pass 8. copy_shallow.......... pass 9. move.................. pass 10. move_coll............. pass 11. move_cleanup.......... pass 12. finish................ pass <- summary for `copymove': of 13 tests run: 13 passed, 0 failed. 100.0% -> running `props': 0. init.................. pass 1. begin................. pass 2. propfind_invalid...... pass 3. propfind_invalid2..... FAIL (PROPFIND with invalid namespace declaration in body (see FAQ) got 207 response not 400) 4. propfind_d0........... pass 5. propinit.............. pass 6. propset............... pass 7. propget............... pass 8. propextended.......... pass 9. propmove.............. pass 10. propget............... pass 11. propdeletes........... pass 12. propget............... pass 13. propreplace........... pass 14. propget............... pass 15. propnullns............ pass 16. propget............... pass 17. prophighunicode....... pass 18. propget............... pass 19. propremoveset......... pass 20. propget............... pass 21. propsetremove......... pass 22. propget............... pass 23. propvalnspace......... pass 24. propwformed........... pass 25. propinit.............. pass 26. propmanyns............ pass 27. propget............... pass 28. propcleanup........... pass 29. finish................ pass <- summary for `props': of 30 tests run: 29 passed, 1 failed. 96.7% -> running `locks': 0. init.................. pass 1. begin................. pass 2. options............... pass 3. precond............... pass 4. init_locks............ pass 5. put................... pass 6. lock_excl............. pass 7. discover.............. pass 8. refresh............... pass 9. notowner_modify....... pass 10. notowner_lock......... pass 11. owner_modify.......... pass 12. notowner_modify....... pass 13. notowner_lock......... pass 14. copy.................. pass 15. cond_put.............. pass 16. fail_cond_put......... pass 17. cond_put_with_not..... pass 18. cond_put_corrupt_token pass 19. complex_cond_put...... pass 20. fail_complex_cond_put. pass 21. unlock................ pass 22. fail_cond_put_unlocked pass 23. lock_shared........... pass 24. notowner_modify....... pass 25. notowner_lock......... pass 26. owner_modify.......... pass 27. double_sharedlock..... pass 28. notowner_modify....... pass 29. notowner_lock......... pass 30. unlock................ pass 31. prep_collection....... pass 32. lock_collection....... pass 33. owner_modify.......... pass 34. notowner_modify....... pass 35. refresh............... pass 36. indirect_refresh...... pass 37. unlock................ pass 38. unmapped_lock......... pass 39. unlock................ pass 40. finish................ pass <- summary for `locks': of 41 tests run: 41 passed, 0 failed. 100.0% -> running `http': 0. init.................. pass 1. begin................. pass 2. expect100............. pass 3. finish................ pass <- summary for `http': of 4 tests run: 4 passed, 0 failed. 100.0%
Updated by gstrauss over 5 years ago
For posterity: running the 'litmus' tests requires a little bit of setup. Directory locations for webdav files and webdav db must be writable by the user under which lighttpd will be run, and must be at least readable by the user under which 'litmus' will be run.
.
webdav_dir=/home/lighttpd/opt/srv/www mkdir -p $webdav_dir cp /usr/share/litmus/htdocs/foo $webdav_dir/ # directory for webdav db must also exist (wherever you like) mkdir /home/lighttpd/opt/var/db/ : /usr/bin/litmus -k http://127.0.0.1:8080/ -d $webdav_dir
lighttpd needs to be running. ETags have to be enabled (default), and there must be a mimetype.assign entry for "" (e.g. "" => "application/octet-stream")
server.document-root = "/home/lighttpd/opt/srv/www" server.modules += ( "mod_webdav" ) webdav.activate = "enable" webdav.sqlite-db-name = "/home/lighttpd/opt/var/db/webdav.db" #mimetype.assign = ( "" => "application/octet-stream" )
Updated by gstrauss over 5 years ago
- Status changed from Patch Pending to Fixed
- % Done changed from 0 to 100
Applied in changeset 50aae03c31f9dddb489092c050f9dbec21281118.
Also available in: Atom