From 9d769027108bb47fa32f3c32b3497b1c8cc8301b Mon Sep 17 00:00:00 2001 From: ed Date: Tue, 11 Feb 2025 23:32:44 +0000 Subject: [PATCH] WebDAV: adjust 401-mask for GETs (#136) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit some clients, including KDE Dolphin (kioworker/6.10) keeps sending requests without the basic-auth header, expecting the server to respond with a 401 before it does most clients only do this for the initial request, which is usually a PROPFIND, which makes this nice and simple -- but turns out we need to consider this for GET as well... this is tricky because a graphical webbrowser must never receive a 401 lest it becomes near-impossible to deauth, and that's exactly what Dolphin pretends to be in its UA man ( ´_ゝ`) note: `KIO/` hits konqueror so don't --- copyparty/__main__.py | 1 + copyparty/httpcli.py | 9 ++++++--- copyparty/svchub.py | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/copyparty/__main__.py b/copyparty/__main__.py index f6a4a60e..ff7c75ca 100644 --- a/copyparty/__main__.py +++ b/copyparty/__main__.py @@ -1183,6 +1183,7 @@ def add_webdav(ap): ap2.add_argument("--dav-mac", action="store_true", help="disable apple-garbage filter -- allow macos to create junk files (._* and .DS_Store, .Spotlight-*, .fseventsd, .Trashes, .AppleDouble, __MACOS)") ap2.add_argument("--dav-rt", action="store_true", help="show symlink-destination's lastmodified instead of the link itself; always enabled for recursive listings (volflag=davrt)") ap2.add_argument("--dav-auth", action="store_true", help="force auth for all folders (required by davfs2 when only some folders are world-readable) (volflag=davauth)") + ap2.add_argument("--dav-ua1", metavar="PTN", type=u, default=r" kioworker/", help="regex of tricky user-agents which expect 401 from GET requests; disable with [\033[32mno\033[0m] or blank") def add_tftp(ap): diff --git a/copyparty/httpcli.py b/copyparty/httpcli.py index 2fee6b80..c8209717 100644 --- a/copyparty/httpcli.py +++ b/copyparty/httpcli.py @@ -1794,7 +1794,7 @@ class HttpCli(object): def handle_cpmv(self) -> bool: dst = self.headers["destination"] - # dolphin (KIO/6.10) "webdav://127.0.0.1:3923/a/b.txt" + # dolphin (kioworker/6.10) "webdav://127.0.0.1:3923/a/b.txt" dst = re.sub("^[a-zA-Z]+://[^/]+", "", dst).lstrip() if self.is_vproxied and dst.startswith(self.args.SRS): @@ -4836,9 +4836,12 @@ class HttpCli(object): # that the client is not a graphical browser if ( rc == 403 - and not self.pw - and not self.ua.startswith("Mozilla/") + and self.uname == "*" and "sec-fetch-site" not in self.headers + and ( + not self.ua.startswith("Mozilla/") + or (self.args.dav_ua1 and self.args.dav_ua1.search(self.ua)) + ) ): rc = 401 self.out_headers["WWW-Authenticate"] = 'Basic realm="a"' diff --git a/copyparty/svchub.py b/copyparty/svchub.py index 3be52ce7..560355f2 100644 --- a/copyparty/svchub.py +++ b/copyparty/svchub.py @@ -769,7 +769,7 @@ class SvcHub(object): vs = os.path.expandvars(os.path.expanduser(vs)) setattr(al, k, vs) - for k in "sus_urls nonsus_urls".split(" "): + for k in "dav_ua1 sus_urls nonsus_urls".split(" "): vs = getattr(al, k) if not vs or vs == "no": setattr(al, k, None)