LibrePortal/scripts/system/libreportal-dns
librelad d17e8814d0 feat(desudo): root-owned DNS + host-SSH-access helpers
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>
2026-05-24 18:21:46 +01:00

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