[GH-ISSUE #536] dufs lists by webdav contents to which the user does not have access #312

Closed
opened 2026-04-08 16:51:54 +03:00 by zhus · 4 comments
Owner

Originally created by @ogarcia on GitHub (Feb 1, 2025).
Original GitHub issue: https://github.com/sigoden/dufs/issues/536

Problem

If you simply launch dufs with this @/public ACL, users can list (via WebDav) the contents of /. They cannot open the files nor can they access other subdirectories of /.

Configuration

cargo run -- stuff -A -a 'admin:admin@/:rw' -a '@/public'

Log

Listening on:
  http://127.0.0.1:5000/
  http://192.168.1.66:5000/
  http://192.168.122.1:5000/
  http://[::1]:5000/
  http://[fd48:e1a9:db6f::66]:5000/
  http://[fd48:e1a9:db6f:0:f058:97ec:3d65:e7da]:5000/

2025-02-01T13:39:09+01:00 INFO - 127.0.0.1 "GET /" 200
2025-02-01T13:39:39+01:00 INFO - 192.168.122.127 "OPTIONS /" 200
2025-02-01T13:39:39+01:00 INFO - 192.168.122.127 "PROPFIND /" 207
2025-02-01T13:39:39+01:00 INFO - 192.168.122.127 "PROPFIND /" 207
2025-02-01T13:39:39+01:00 INFO - 192.168.122.127 "PROPFIND /" 207
2025-02-01T13:39:39+01:00 INFO - 192.168.122.127 "PROPFIND /" 207
2025-02-01T13:39:41+01:00 INFO - 192.168.122.127 "PROPFIND /somefile.txt" 401
2025-02-01T13:39:44+01:00 INFO - 192.168.122.127 "PROPFIND /somedir" 401

Environment Information

  • Dufs version: Git version
  • Browser/Webdav info: GNOME Nautilus
  • OS info: Arch Linux
Originally created by @ogarcia on GitHub (Feb 1, 2025). Original GitHub issue: https://github.com/sigoden/dufs/issues/536 **Problem** If you simply launch dufs with this `@/public` ACL, users can list (via WebDav) the contents of `/`. They cannot open the files nor can they access other subdirectories of `/`. **Configuration** ``` cargo run -- stuff -A -a 'admin:admin@/:rw' -a '@/public' ``` **Log** ``` Listening on: http://127.0.0.1:5000/ http://192.168.1.66:5000/ http://192.168.122.1:5000/ http://[::1]:5000/ http://[fd48:e1a9:db6f::66]:5000/ http://[fd48:e1a9:db6f:0:f058:97ec:3d65:e7da]:5000/ 2025-02-01T13:39:09+01:00 INFO - 127.0.0.1 "GET /" 200 2025-02-01T13:39:39+01:00 INFO - 192.168.122.127 "OPTIONS /" 200 2025-02-01T13:39:39+01:00 INFO - 192.168.122.127 "PROPFIND /" 207 2025-02-01T13:39:39+01:00 INFO - 192.168.122.127 "PROPFIND /" 207 2025-02-01T13:39:39+01:00 INFO - 192.168.122.127 "PROPFIND /" 207 2025-02-01T13:39:39+01:00 INFO - 192.168.122.127 "PROPFIND /" 207 2025-02-01T13:39:41+01:00 INFO - 192.168.122.127 "PROPFIND /somefile.txt" 401 2025-02-01T13:39:44+01:00 INFO - 192.168.122.127 "PROPFIND /somedir" 401 ``` **Environment Information** - Dufs version: Git version - Browser/Webdav info: GNOME Nautilus - OS info: Arch Linux
zhus closed this issue 2026-04-08 16:51:55 +03:00
Author
Owner

@sigoden commented on GitHub (Feb 1, 2025):

similar to #263

Webdav must be designed like this.

This is because some webdav clients do not carry the Authorization header when listing files.

<!-- gh-comment-id:2628976544 --> @sigoden commented on GitHub (Feb 1, 2025): similar to #263 Webdav must be designed like this. This is because some webdav clients do not carry the Authorization header when listing files.
Author
Owner

@ogarcia commented on GitHub (Feb 2, 2025):

You have to forgive me but it's to get it right. You say that the webdav client does not send the authorization header, but in this case it does not have to send it since it is making a completely anonymous request.

As far as I know, the client makes a PROPFIND request indicating what information it wants to receive and with what depth (0, 1 or infinite) and with the response it gets is what builds what it shows to the user. Basically this curl:

curl -XPROPFIND \
  -H 'Content-Type: text/xml' -H 'depth: 1' \
  -d '<?xml version="1.0" encoding="utf-8" ?><D:propfind xmlns:D="DAV:"><D:displayname/></D:allprop>' \
  http://127.0.0.1:5000

As side note, in terms of properties, it can change and go for a fixed shot, asking mainly for these:

<D:prop>
    <D:creationdate/>
    <D:displayname/>
    <D:getcontentlength/>
    <D:getcontenttype/>
    <D:getetag/>
    <D:getlastmodified/>
    <D:resourcetype/>
</D:prop>

From there the server returns the list which, as I see it, should not include what it does not have access to, but it does:

<?xml version="1.0" encoding="utf-8" ?>
<D:multistatus xmlns:D="DAV:">
<D:response>
<D:href>/</D:href>
<D:propstat>
<D:prop>
<D:displayname></D:displayname>
<D:getlastmodified>Sun, 02 Feb 2025 10:09:10 GMT</D:getlastmodified>
<D:resourcetype><D:collection/></D:resourcetype>
</D:prop>
<D:status>HTTP/1.1 200 OK</D:status>
</D:propstat>
</D:response><D:response>
<D:href>/public/</D:href>
<D:propstat>
<D:prop>
<D:displayname>public</D:displayname>
<D:getlastmodified>Sat, 01 Feb 2025 12:36:42 GMT</D:getlastmodified>
<D:resourcetype><D:collection/></D:resourcetype>
</D:prop>
<D:status>HTTP/1.1 200 OK</D:status>
</D:propstat>
</D:response><D:response>
<D:href>/somefile.txt</D:href>
<D:propstat>
<D:prop>
<D:displayname>somefile.txt</D:displayname>
<D:getcontentlength>101</D:getcontentlength>
<D:getlastmodified>Sun, 02 Feb 2025 10:09:10 GMT</D:getlastmodified>
<D:resourcetype></D:resourcetype>
</D:prop>
<D:status>HTTP/1.1 200 OK</D:status>
</D:propstat>
</D:response><D:response>
<D:href>/somedir/</D:href>
<D:propstat>
<D:prop>
<D:displayname>somedir</D:displayname>
<D:getlastmodified>Sun, 02 Feb 2025 10:08:55 GMT</D:getlastmodified>
<D:resourcetype><D:collection/></D:resourcetype>
</D:prop>
<D:status>HTTP/1.1 200 OK</D:status>
</D:propstat>
</D:response>
</D:multistatus>

The truth is that I don't understand where the client is going wrong here or what is missing.

<!-- gh-comment-id:2629342856 --> @ogarcia commented on GitHub (Feb 2, 2025): You have to forgive me but it's to get it right. You say that the webdav client does not send the authorization header, but in this case it does not have to send it since it is making a completely anonymous request. As far as I know, the client makes a PROPFIND request indicating what information it wants to receive and with what depth (0, 1 or infinite) and with the response it gets is what builds what it shows to the user. Basically this curl: ``` curl -XPROPFIND \ -H 'Content-Type: text/xml' -H 'depth: 1' \ -d '<?xml version="1.0" encoding="utf-8" ?><D:propfind xmlns:D="DAV:"><D:displayname/></D:allprop>' \ http://127.0.0.1:5000 ``` As side note, in terms of properties, it can change and go for a _fixed shot_, asking mainly for these: ``` <D:prop> <D:creationdate/> <D:displayname/> <D:getcontentlength/> <D:getcontenttype/> <D:getetag/> <D:getlastmodified/> <D:resourcetype/> </D:prop> ``` From there the server returns the list which, as I see it, should not include what it does not have access to, but it does: ``` <?xml version="1.0" encoding="utf-8" ?> <D:multistatus xmlns:D="DAV:"> <D:response> <D:href>/</D:href> <D:propstat> <D:prop> <D:displayname></D:displayname> <D:getlastmodified>Sun, 02 Feb 2025 10:09:10 GMT</D:getlastmodified> <D:resourcetype><D:collection/></D:resourcetype> </D:prop> <D:status>HTTP/1.1 200 OK</D:status> </D:propstat> </D:response><D:response> <D:href>/public/</D:href> <D:propstat> <D:prop> <D:displayname>public</D:displayname> <D:getlastmodified>Sat, 01 Feb 2025 12:36:42 GMT</D:getlastmodified> <D:resourcetype><D:collection/></D:resourcetype> </D:prop> <D:status>HTTP/1.1 200 OK</D:status> </D:propstat> </D:response><D:response> <D:href>/somefile.txt</D:href> <D:propstat> <D:prop> <D:displayname>somefile.txt</D:displayname> <D:getcontentlength>101</D:getcontentlength> <D:getlastmodified>Sun, 02 Feb 2025 10:09:10 GMT</D:getlastmodified> <D:resourcetype></D:resourcetype> </D:prop> <D:status>HTTP/1.1 200 OK</D:status> </D:propstat> </D:response><D:response> <D:href>/somedir/</D:href> <D:propstat> <D:prop> <D:displayname>somedir</D:displayname> <D:getlastmodified>Sun, 02 Feb 2025 10:08:55 GMT</D:getlastmodified> <D:resourcetype><D:collection/></D:resourcetype> </D:prop> <D:status>HTTP/1.1 200 OK</D:status> </D:propstat> </D:response> </D:multistatus> ``` The truth is that I don't understand where the client is going wrong here or what is missing.
Author
Owner

@sigoden commented on GitHub (Feb 2, 2025):

For some webdav clients, even if you enter username/password, it will not automatically carry authorization information by default, which means you can only see the public directory but not other directories. Even if you are an admin account.

<!-- gh-comment-id:2629346482 --> @sigoden commented on GitHub (Feb 2, 2025): For some webdav clients, even if you enter username/password, it will not automatically carry authorization information by default, which means you can only see the public directory but not other directories. Even if you are an admin account.
Author
Owner

@ogarcia commented on GitHub (Feb 2, 2025):

Ah. Ok. It's a workaround for certain webdav clients that should make the authenticated request and don't do it. Understood.

Thanks!! ☺️

<!-- gh-comment-id:2629351761 --> @ogarcia commented on GitHub (Feb 2, 2025): Ah. Ok. It's a workaround for certain webdav clients that should make the authenticated request and don't do it. Understood. Thanks!! ☺️
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sigoden/dufs#312