mirror of
https://github.com/9001/copyparty.git
synced 2025-08-17 09:02:15 -06:00
smb: add better-than-nothing permission checks
This commit is contained in:
parent
75e5e53276
commit
5f60c509c6
|
@ -734,7 +734,8 @@ dependencies: `python3 -m pip install --user -U impacket==0.10.0`
|
||||||
some **BIG WARNINGS** specific to SMB/CIFS, in decreasing importance:
|
some **BIG WARNINGS** specific to SMB/CIFS, in decreasing importance:
|
||||||
* not entirely confident that read-only is read-only
|
* not entirely confident that read-only is read-only
|
||||||
* the smb backend is not fully integrated with vfs, meaning there could be security issues (path traversal). Please use `--smb-port` (see below) and [prisonparty](./bin/prisonparty.sh)
|
* the smb backend is not fully integrated with vfs, meaning there could be security issues (path traversal). Please use `--smb-port` (see below) and [prisonparty](./bin/prisonparty.sh)
|
||||||
* account passwords work per-volume as expected, but account permissions are ignored; all accounts have access to all volumes, and `--smbw` gives all accounts write-access everywhere
|
* account passwords work per-volume as expected, but account permissions are coalesced; all accounts have read-access to all volumes, and if a single account has write-access to some volume then all other accounts also do
|
||||||
|
* if no accounts have write-access to a specific volume, or if `--smbw` is not set, then writing to that volume from smb *should* be impossible
|
||||||
* [shadowing](#shadowing) probably works as expected but no guarantees
|
* [shadowing](#shadowing) probably works as expected but no guarantees
|
||||||
|
|
||||||
and some minor issues,
|
and some minor issues,
|
||||||
|
|
|
@ -155,14 +155,16 @@ class SMB(object):
|
||||||
if ANYWIN:
|
if ANYWIN:
|
||||||
f_ro |= os.O_BINARY
|
f_ro |= os.O_BINARY
|
||||||
|
|
||||||
readonly = flags == f_ro
|
wr = flags != f_ro
|
||||||
|
if wr and not self.args.smbw:
|
||||||
|
yeet("blocked write (no --smbw): " + vpath)
|
||||||
|
|
||||||
if not self.args.smbw and readonly:
|
vfs, ap = self._v2a("open", vpath, *a)
|
||||||
logging.info("blocked write to %s", vpath)
|
if wr and not vfs.axs.uwrite:
|
||||||
raise Exception("read-only")
|
yeet("blocked write (no-write-acc): " + vpath)
|
||||||
|
|
||||||
ret = bos.open(self._v2a("open", vpath, *a)[1], flags, chmod, *a, **ka)
|
ret = bos.open(ap, flags, chmod, *a, **ka)
|
||||||
if not readonly:
|
if wr:
|
||||||
now = time.time()
|
now = time.time()
|
||||||
nf = len(self.files)
|
nf = len(self.files)
|
||||||
if nf > 9000:
|
if nf > 9000:
|
||||||
|
@ -194,9 +196,20 @@ class SMB(object):
|
||||||
)
|
)
|
||||||
|
|
||||||
def _rename(self, vp1: str, vp2: str) -> None:
|
def _rename(self, vp1: str, vp2: str) -> None:
|
||||||
|
if not self.args.smbw:
|
||||||
|
yeet("blocked rename (no --smbw): " + vp1)
|
||||||
|
|
||||||
vp1 = vp1.lstrip("/")
|
vp1 = vp1.lstrip("/")
|
||||||
vp2 = vp2.lstrip("/")
|
vp2 = vp2.lstrip("/")
|
||||||
ap2 = self._v2a("rename", vp2, vp1)[1]
|
|
||||||
|
vfs2, ap2 = self._v2a("rename", vp2, vp1)
|
||||||
|
if not vfs2.axs.uwrite:
|
||||||
|
yeet("blocked rename (no-write-acc): " + vp2)
|
||||||
|
|
||||||
|
vfs1, _ = self.asrv.vfs.get(vp1, LEELOO_DALLAS, True, True)
|
||||||
|
if not vfs1.axs.umove:
|
||||||
|
yeet("blocked rename (no-move-acc): " + vp1)
|
||||||
|
|
||||||
self.hub.up2k.handle_mv(LEELOO_DALLAS, vp1, vp2)
|
self.hub.up2k.handle_mv(LEELOO_DALLAS, vp1, vp2)
|
||||||
try:
|
try:
|
||||||
bos.makedirs(ap2)
|
bos.makedirs(ap2)
|
||||||
|
@ -204,19 +217,39 @@ class SMB(object):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def _mkdir(self, vpath: str) -> None:
|
def _mkdir(self, vpath: str) -> None:
|
||||||
return bos.mkdir(self._v2a("mkdir", vpath)[1])
|
if not self.args.smbw:
|
||||||
|
yeet("blocked mkdir (no --smbw): " + vpath)
|
||||||
|
|
||||||
|
vfs, ap = self._v2a("mkdir", vpath)
|
||||||
|
if not vfs.axs.uwrite:
|
||||||
|
yeet("blocked mkdir (no-write-acc): " + vpath)
|
||||||
|
|
||||||
|
return bos.mkdir(ap)
|
||||||
|
|
||||||
def _stat(self, vpath: str, *a: Any, **ka: Any) -> os.stat_result:
|
def _stat(self, vpath: str, *a: Any, **ka: Any) -> os.stat_result:
|
||||||
return bos.stat(self._v2a("stat", vpath, *a)[1], *a, **ka)
|
return bos.stat(self._v2a("stat", vpath, *a)[1], *a, **ka)
|
||||||
|
|
||||||
def _unlink(self, vpath: str) -> None:
|
def _unlink(self, vpath: str) -> None:
|
||||||
|
if not self.args.smbw:
|
||||||
|
yeet("blocked delete (no --smbw): " + vpath)
|
||||||
|
|
||||||
# return bos.unlink(self._v2a("stat", vpath, *a)[1])
|
# return bos.unlink(self._v2a("stat", vpath, *a)[1])
|
||||||
logging.info("delete %s", vpath)
|
|
||||||
vp = vpath.lstrip("/")
|
vp = vpath.lstrip("/")
|
||||||
|
vfs, ap = self._v2a("delete", vpath)
|
||||||
|
if not vfs.axs.udel:
|
||||||
|
yeet("blocked delete (no-del-acc): " + vpath)
|
||||||
|
|
||||||
self.hub.up2k.handle_rm(LEELOO_DALLAS, "1.7.6.2", [vp], [])
|
self.hub.up2k.handle_rm(LEELOO_DALLAS, "1.7.6.2", [vp], [])
|
||||||
|
|
||||||
def _utime(self, vpath: str, times: tuple[float, float]) -> None:
|
def _utime(self, vpath: str, times: tuple[float, float]) -> None:
|
||||||
return bos.utime(self._v2a("stat", vpath)[1], times)
|
if not self.args.smbw:
|
||||||
|
yeet("blocked utime (no --smbw): " + vpath)
|
||||||
|
|
||||||
|
vfs, ap = self._v2a("utime", vpath)
|
||||||
|
if not vfs.axs.uwrite:
|
||||||
|
yeet("blocked utime (no-write-acc): " + vpath)
|
||||||
|
|
||||||
|
return bos.utime(ap, times)
|
||||||
|
|
||||||
def _p_exists(self, vpath: str) -> bool:
|
def _p_exists(self, vpath: str) -> bool:
|
||||||
try:
|
try:
|
||||||
|
@ -269,3 +302,8 @@ class SMB(object):
|
||||||
def _is_in_file_jail(self, *a: Any) -> bool:
|
def _is_in_file_jail(self, *a: Any) -> bool:
|
||||||
# handled by vfs
|
# handled by vfs
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def yeet(msg: str) -> None:
|
||||||
|
logging.info(msg)
|
||||||
|
raise Exception(msg)
|
||||||
|
|
Loading…
Reference in a new issue