SMB shares and NFS exports may now point to any existing directory (USB disks under /mnt or /media, /srv, home folders...) instead of only ZFS dataset mountpoints. System trees (/etc, /usr, /var, /boot, /proc, /root, ...) are refused, also after resolving symlinks. The path suggestions list mounted data filesystems from /proc/self/mounts in addition to ZFS mountpoints. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -68,7 +68,7 @@ func TestSharesSMBFlow(t *testing.T) {
|
||||
|
||||
// page lists users and mountpoints, prefills from ?path=
|
||||
body := get(srv, "/shares?path=/tank/data").Body.String()
|
||||
for _, want := range []string{`value="/tank/data"`, `value="data"`, `value="alice"`, "No SMB shares yet"} {
|
||||
for _, want := range []string{`value="/tank/data"`, `value="data"`, `value="alice"`, "No SMB shares yet", `<option value="/mnt/usb">`} {
|
||||
if !strings.Contains(body, want) {
|
||||
t.Errorf("shares page missing %q", want)
|
||||
}
|
||||
@@ -96,10 +96,14 @@ func TestSharesSMBFlow(t *testing.T) {
|
||||
t.Errorf("share not listed")
|
||||
}
|
||||
|
||||
// refused: duplicate name, path outside pools, non-guest without users, reserved name, unclean path
|
||||
// refused: duplicate name, system dirs, symlink into a system dir, missing dir,
|
||||
// non-guest without users, reserved name, unclean path
|
||||
for _, form := range []url.Values{
|
||||
{"name": {"data"}, "path": {"/tank/data"}, "guest": {"1"}},
|
||||
{"name": {"etc"}, "path": {"/etc"}, "guest": {"1"}},
|
||||
{"name": {"logs"}, "path": {"/var/log"}, "guest": {"1"}},
|
||||
{"name": {"evil"}, "path": {"/srv/evil"}, "guest": {"1"}},
|
||||
{"name": {"nowhere"}, "path": {"/opt/nowhere"}, "guest": {"1"}},
|
||||
{"name": {"priv"}, "path": {"/tank/data"}},
|
||||
{"name": {"global"}, "path": {"/tank/data"}, "guest": {"1"}},
|
||||
{"name": {"gone"}, "path": {"/tank/nope/.."}, "guest": {"1"}},
|
||||
@@ -125,6 +129,12 @@ func TestSharesSMBFlow(t *testing.T) {
|
||||
if !strings.Contains(f.written(shares.DefaultSMBConf), "valid users = alice") {
|
||||
t.Errorf("smb.conf not regenerated after edit")
|
||||
}
|
||||
// a plain folder outside any ZFS dataset
|
||||
rec = postForm(srv, "/shares/smb/save", url.Values{"name": {"media"}, "path": {"/srv/media"}, "guest": {"1"}, "browseable": {"1"}})
|
||||
if rec.Code != http.StatusSeeOther || !strings.Contains(f.written(shares.DefaultSMBConf), "path = /srv/media") {
|
||||
t.Fatalf("non-ZFS share: %d %s", rec.Code, rec.Body.String())
|
||||
}
|
||||
postForm(srv, "/shares/smb/delete", url.Values{"name": {"media"}})
|
||||
// a user still referenced by a share cannot be deleted
|
||||
rec = postForm(srv, "/shares/users/delete", url.Values{"name": {"alice"}})
|
||||
if rec.Code != 200 || !strings.Contains(rec.Body.String(), "still allowed on share private") || f.has("smbpasswd -x") {
|
||||
@@ -192,11 +202,17 @@ func TestSharesNFSFlow(t *testing.T) {
|
||||
{"path": {"/tank/data2"}, "clients": {""}, "squash": {"root"}}, // no clients
|
||||
{"path": {"/tank/data2"}, "clients": {"10.0.0.0/33"}, "squash": {"root"}}, // bad cidr
|
||||
{"path": {"/tank/data2"}, "clients": {"*"}, "squash": {"weird"}}, // bad squash
|
||||
{"path": {"/etc"}, "clients": {"*"}, "squash": {"root"}}, // system dir
|
||||
} {
|
||||
if rec := postForm(srv, "/shares/nfs/save", form); rec.Code != 200 || !strings.Contains(rec.Body.String(), "Not saved") {
|
||||
t.Errorf("form %v accepted", form)
|
||||
}
|
||||
}
|
||||
if rec := postForm(srv, "/shares/nfs/save", url.Values{"path": {"/srv/media"}, "clients": {"*"}, "squash": {"root"}}); rec.Code != http.StatusSeeOther ||
|
||||
!strings.Contains(f.written(shares.DefaultExports), `"/srv/media" *(`) {
|
||||
t.Fatalf("non-ZFS export: %d %s", rec.Code, rec.Body.String())
|
||||
}
|
||||
postForm(srv, "/shares/nfs/delete", url.Values{"path": {"/srv/media"}})
|
||||
body := get(srv, "/shares").Body.String()
|
||||
if !strings.Contains(body, "192.168.101.0/24, pc.lan") || !strings.Contains(body, ":/tank/data") {
|
||||
t.Errorf("export not listed")
|
||||
|
||||
Reference in New Issue
Block a user