Two more runtime root file-primitive subsystems moved behind self-
validating root-owned helpers so the scoped sudoers needn't grant blanket
sudo sed/tee/cp on /etc (which is root-equivalent — sudo arg wildcards
match across '/', so even path-scoped entries are bypassable):
- scripts/system/libreportal-dns: {clear|add <ip>} — edits /etc/resolv.conf
only, validates the IP argument
- scripts/system/libreportal-ssh-access: authorized_keys + sshd
PasswordAuthentication management, with the lockout guards moved INTO the
helper (the trust boundary) so a compromised manager can't bypass them
- run_privileged: _runRootHelper dispatcher + runResolv / runSshAccess
(runOwnership now uses it too)
- init.sh: initRootHelpers installs all three helpers root:root 0755 with
the manager name baked in
- setup_dns -> runResolv (+ ping de-sudo'd, works unprivileged); host_access
+ webui_ssh_access -> runSshAccess
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
43 lines
1.3 KiB
Bash
43 lines
1.3 KiB
Bash
#!/bin/bash
|
|
# LibrePortal DNS helper — the only root-privileged edit of /etc/resolv.conf the
|
|
# manager may trigger. Installed root:root 0755 to /usr/local/sbin by init.sh.
|
|
# Self-contained (sources no manager code). Operates ONLY on /etc/resolv.conf and
|
|
# only with strictly-validated IP arguments, so the scoped sudoers can allow it
|
|
# wholesale instead of a blanket `sudo sed`/`sudo tee` (which would be root).
|
|
|
|
set -u
|
|
|
|
[[ $EUID -eq 0 ]] || { echo "libreportal-dns: must run as root" >&2; exit 1; }
|
|
|
|
RESOLV="/etc/resolv.conf"
|
|
|
|
_is_ip() {
|
|
local ip="$1"
|
|
# IPv4
|
|
if [[ "$ip" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]; then
|
|
local o; for o in ${ip//./ }; do (( o <= 255 )) || return 1; done
|
|
return 0
|
|
fi
|
|
# IPv6 (loose but safe — only hex/colon, no shell metachars)
|
|
[[ "$ip" =~ ^[0-9A-Fa-f:]+$ ]] && return 0
|
|
return 1
|
|
}
|
|
|
|
clear_ns() {
|
|
[[ -f "$RESOLV" ]] || return 0
|
|
sed -i '/^nameserver/d' "$RESOLV"
|
|
}
|
|
|
|
add_ns() {
|
|
local ip="$1"
|
|
_is_ip "$ip" || { echo "libreportal-dns: invalid IP '$ip'" >&2; return 1; }
|
|
printf 'nameserver %s\n' "$ip" >> "$RESOLV"
|
|
}
|
|
|
|
action="${1:-}"; shift 2>/dev/null || true
|
|
case "$action" in
|
|
clear) clear_ns ;;
|
|
add) add_ns "${1:-}" ;;
|
|
*) echo "usage: libreportal-dns {clear|add <ip>}" >&2; exit 2 ;;
|
|
esac
|