mirror of
https://github.com/9001/copyparty.git
synced 2026-03-22 16:13:11 +10:00
shr_files fence ftp/sftp;
this fixes GHSA-67rw-2x62-mqqm which is the 2nd season of
e0a92ba72d / CVE-2025-58753
since that only fixed the http / https endpoints
This commit is contained in:
@@ -705,18 +705,22 @@ class VFS(object):
|
||||
if rem:
|
||||
ap += "/" + rem
|
||||
|
||||
rap = absreal(ap)
|
||||
rap = ""
|
||||
if self.shr_files:
|
||||
assert self.shr_src # !rm
|
||||
vn, rem = self.shr_src
|
||||
chk = absreal(os.path.join(vn.realpath, rem))
|
||||
if chk != rap:
|
||||
# not the dir itself; assert file allowed
|
||||
ad, fn = os.path.split(rap)
|
||||
if chk != ad or fn not in self.shr_files:
|
||||
return "\n\n"
|
||||
if rem and rem not in self.shr_files:
|
||||
return "\n\n"
|
||||
if resolve:
|
||||
rap = absreal(ap)
|
||||
vn, rem = self.shr_src
|
||||
chk = absreal(os.path.join(vn.realpath, rem))
|
||||
if chk != rap:
|
||||
# not the dir itself; assert file allowed
|
||||
ad, fn = os.path.split(rap)
|
||||
if chk != ad or fn not in self.shr_files:
|
||||
return "\n\n"
|
||||
|
||||
return rap if resolve else ap
|
||||
return (rap or absreal(ap)) if resolve else ap
|
||||
|
||||
def _dcanonical_shr(self, rem: str) -> str:
|
||||
"""resolves until the final component (filename)"""
|
||||
|
||||
@@ -200,11 +200,13 @@ class FtpFs(AbstractedFS):
|
||||
cr, cw, cm, cd, _, _, _, _, _ = avfs.uaxs[self.h.uname]
|
||||
if r and not cr or w and not cw or m and not cm or d and not cd:
|
||||
raise FSE(t.format(vpath), 1)
|
||||
else:
|
||||
ap = vfs.canonical(rem, False)
|
||||
|
||||
if "bcasechk" in vfs.flags and not vfs.casechk(rem, True):
|
||||
raise FSE("No such file or directory", 1)
|
||||
|
||||
return os.path.join(vfs.realpath, rem), vfs, rem
|
||||
return ap, vfs, rem
|
||||
except Pebkac as ex:
|
||||
raise FSE(str(ex))
|
||||
|
||||
|
||||
@@ -349,11 +349,13 @@ class SFTP_Srv(paramiko.SFTPServerInterface):
|
||||
cr, cw, cm, cd, _, _, _, _, _ = avn.uaxs[self.uname]
|
||||
if r and not cr or w and not cw or m and not cm or d and not cd:
|
||||
raise OSError(errno.EPERM, "permission denied in [/%s]" % (vpath,))
|
||||
else:
|
||||
ap = vn.canonical(rem, False)
|
||||
|
||||
if "bcasechk" in vn.flags and not vn.casechk(rem, True):
|
||||
raise OSError(errno.ENOENT, "file does not exist case-sensitively")
|
||||
|
||||
return os.path.join(vn.realpath, rem), vn, rem
|
||||
return ap, vn, rem
|
||||
|
||||
def list_folder(self, path: str) -> list[SATTR] | int:
|
||||
try:
|
||||
@@ -484,7 +486,7 @@ class SFTP_Srv(paramiko.SFTPServerInterface):
|
||||
|
||||
try:
|
||||
vn, rem = self.asrv.vfs.get(vp, self.uname, rd, wr)
|
||||
ap = os.path.join(vn.realpath, rem)
|
||||
ap = vn.canonical(rem, False)
|
||||
vf = vn.flags
|
||||
except Pebkac as ex:
|
||||
t = "denied open file [%s], iflag=%s, read=%s, write=%s: %s"
|
||||
|
||||
@@ -191,7 +191,7 @@ class SMB(object):
|
||||
vfs, rem = self.asrv.vfs.get(vpath, uname, *perms)
|
||||
if not vfs.realpath:
|
||||
raise Exception("unmapped vfs")
|
||||
return vfs, vjoin(vfs.realpath, rem)
|
||||
return vfs, vfs.canonical(rem, False)
|
||||
|
||||
def _listdir(self, vpath: str, *a: Any, **ka: Any) -> list[str]:
|
||||
vpath = vpath.replace("\\", "/").lstrip("/")
|
||||
|
||||
Reference in New Issue
Block a user