diff --git a/DOC/howto/share.md b/DOC/howto/share.md index 5a49242..85d4437 100644 --- a/DOC/howto/share.md +++ b/DOC/howto/share.md @@ -179,6 +179,11 @@ can then access them; print the restricted form with `--users`. SMB shares need Samba accounts, not just system users: `adduser ` (prompts for the password via `smbpasswd -a`) after the system user exists. +`share --users u1,u2` checks the list against the Samba passdb and warns about +any missing account (pointing at `adduser`) — plus it walks the path's parent +dirs and warns when one lacks `other:+x` traversal (e.g. a `700` home dir +blocks Samba clients with `NT_STATUS_ACCESS_DENIED`; fix with `chmod o+x`). +Both are warnings only — the share is still written. **Recipes:** - **Share the media drive to the tailnet (users bob + alice):** @@ -196,6 +201,10 @@ SMB shares need Samba accounts, not just system users: `adduser ` - "smbd not found" → `samba` isn't installed; `sudo apt install samba` - Windows can't connect → check the client is in `--users` / has a Samba password (`adduser`), and that `smbd` is running (`status`) +- `NT_STATUS_ACCESS_DENIED` → two causes, `share` warns about both at share + time: the user is not in the Samba passdb (`pos share smb-server adduser `), + or a parent dir of the share path lacks `other:+x` traversal (`chmod o+x ` + — typical for `700` home dirs) - `valid users` users can't log in → their Samba password differs from the system one; re-run `pos share smb server adduser ` - After editing `/etc/samba/smb.conf` by hand, run `pos share smb server reload` diff --git a/bin/pos-share-smb-server b/bin/pos-share-smb-server index 14f525d..610eaff 100755 --- a/bin/pos-share-smb-server +++ b/bin/pos-share-smb-server @@ -67,6 +67,31 @@ validate_share_name() { esac } +# Warn when any ancestor of the share path lacks other:+x — Samba clients +# traverse as the authenticated user, so a 700 home dir yields +# NT_STATUS_ACCESS_DENIED no matter what smb.conf says. (Sticky dirs like +# /tmp show 't' in the other-execute slot — still traversable.) +check_traversal() { + local p="$1" blocked="" m + while [ "$p" != "/" ]; do + m="$(stat -c '%A' "$p" 2>/dev/null | cut -c10)" + [ "$m" = "x" ] || [ "$m" = "t" ] || blocked="${blocked:+$blocked, }$p" + p="$(dirname "$p")" + done + [ -z "$blocked" ] || warn "Samba can't traverse: $blocked (missing other:+x) — clients get NT_STATUS_ACCESS_DENIED. Fix: chmod o+x " +} + +# Warn for --users entries missing from the Samba passdb (pdbedit/smbpasswd). +check_samba_users() { + local list="$1" sdb u missing="" + if sdb="$(sudo pdbedit -L 2>/dev/null | cut -d: -f1)"; then + for u in ${list//,/ }; do + grep -qxF "$u" <<<"$sdb" || missing="${missing:+$missing, }$u" + done + fi + [ -z "$missing" ] || warn "user(s) not in the Samba passdb: $missing — clients get NT_STATUS_ACCESS_DENIED. Add them: pos share smb-server adduser (needs a system user)" +} + # Validate smb.conf with testparm, then hot-reload smbd if it is running. reload_config() { testparm -s "$SMB_CONF" >/dev/null || err "smb.conf is invalid — changes not loaded (fix with 'pos share smb-server reload')" @@ -110,6 +135,7 @@ case "$cmd" in -*) err "Usage: pos share smb-server share [name] [--read-only|--guest|--users u1,u2]" ;; esac require_root_dir "$path" + check_traversal "$path" [ -f "$SMB_CONF" ] || err "No smb.conf at $SMB_CONF (is samba installed?)" shift 2 @@ -131,6 +157,7 @@ case "$cmd" in elif [ -z "$users" ]; then warn "No valid users — any Samba account can access $path. Restrict with --users u1,u2." fi + [ -n "$users" ] && check_samba_users "$users" ro_val=no; [ "$ro" -eq 1 ] && ro_val=yes guest_val=no; [ "$guest" -eq 1 ] && guest_val=yes diff --git a/reports/bug-report-smb-server-access-denied.md b/reports/bug-report-smb-server-access-denied.md new file mode 100644 index 0000000..9c256a8 --- /dev/null +++ b/reports/bug-report-smb-server-access-denied.md @@ -0,0 +1,65 @@ +Here is a concise bug report you can hand off to the developers of `pos` (or use to fix the script if you maintain it yourself). + +--- + +## 🐛 Bug Report: `pos share smb-server` Creates Inaccessible Shares + +### **Issue Description** + +When adding a share with `pos share smb-server share --users `, the command successfully adds the share to `/etc/samba/smb.conf` and reloads `smbd`. However, clients receive `NT_STATUS_ACCESS_DENIED` upon connecting. + +--- + +### **Root Causes** + +1. **Missing Samba User Credentials (`smbpasswd`)** +* **Problem:** `pos` configures `valid users = ` in `smb.conf`, but fails to initialize or sync the user in Samba's passdb (`passdb.tdb`). Standard Linux account credentials in `/etc/shadow` are not recognized by Samba without `smbpasswd`. +* **Result:** Samba rejects authentication or tree connection requests. + + +2. **Parent Directory Permission Lockdown** +* **Problem:** When sharing a path inside a user's home directory (e.g., `/home/username/shared`), default Linux home permissions are set to `700` (`drwx------`). Samba cannot traverse `/home/username` to reach `/home/username/shared`. +* **Result:** `NT_STATUS_ACCESS_DENIED` due to missing `+x` (traversal) permission on parent directories. + + + +--- + +### **Proposed Fixes for `pos` CLI** + +#### **Fix 1: Register User in Samba Database** + +When `--users ` is passed, check if the user exists in `pdbedit -L`. If missing, prompt for a Samba password or run: + +```bash +sudo smbpasswd -a +sudo smbpasswd -e + +``` + +#### **Fix 2: Automate Parent Directory Traversal Sanity Check** + +Before adding a share path (e.g., `/home/user/share`), inspect parent directory permissions. If `others` lack execution rights (`+x`), automatically run or prompt: + +```bash +chmod o+x /home/ + +``` + +--- + +### **Workaround (Manual Fix)** + +To fix the share created by `pos` right now, run: + +```bash +# 1. Set traversal rights on home directory +chmod o+x /home/unknown + +# 2. Add user to Samba database +sudo smbpasswd -a unknown + +# 3. Restart Samba daemon +sudo systemctl restart smbd + +```