#!/bin/bash
# SPDX-License-Identifier: GPL-3.0-or-later
# Copyright (C) 2015-2016, 2026 InterGenJLU
#
# intergen-welcome-privhelper — privileged "Enable Services" actions for the
# Welcomer. Invoked ONLY via pkexec, which authenticates the caller as an
# administrator (prompts for the password) and runs this as root.
#
# SECURITY MODEL (HOLY GRAIL):
#   * pkexec's built-in org.freedesktop.policykit.exec action is auth_admin —
#     it ALWAYS prompts for the administrator password. We deliberately do NOT
#     ship a custom polkit rule that could weaken that to allow_active=yes; the
#     default is the safe one, so no .rules / .policy file is needed.
#   * This helper accepts EXACTLY ONE verb from the fixed whitelist below and
#     nothing else. No caller-supplied paths, names, or service strings are
#     ever interpolated into a command — so there is no injection surface.
#   * The user added to `lpadmin` is derived from $PKEXEC_UID (pkexec sets it
#     to the calling uid; it is not attacker-controlled), never from an arg.
#   * Every action is fully reversible by its `disable-` counterpart: the
#     service is disabled and any firewall drop-in this helper wrote is removed.
#
# Firewall: the discovery/ssh verbs drop a removable fragment into
# /etc/nftables.d/ (which intergenos-firewall-defaults' nftables.conf includes)
# and reload nftables. The shipped default-deny ruleset is never edited in
# place; toggling a service off deletes its fragment. This is the "drop-in
# rule / GUI control panel" path D-011 explicitly anticipates.
set -euo pipefail

NFTD=/etc/nftables.d
MDNS_DROPIN="$NFTD/50-intergen-mdns.conf"
SSH_DROPIN="$NFTD/40-intergen-ssh.conf"

reload_firewall() {
    mkdir -p "$NFTD"
    systemctl reload nftables 2>/dev/null \
        || systemctl restart nftables 2>/dev/null \
        || nft -f /etc/nftables.conf
}

caller_user() {
    local uid="${PKEXEC_UID:-}"
    if [ -n "$uid" ]; then
        getent passwd "$uid" | cut -d: -f1
    fi
}

case "${1:-}" in
    enable-printing)
        systemctl enable --now cups.socket
        u="$(caller_user)"
        if [ -n "$u" ]; then
            usermod -aG lpadmin "$u"
        fi
        ;;
    disable-printing)
        systemctl disable --now cups.socket cups.service cups.path 2>/dev/null || true
        ;;
    enable-discovery)
        systemctl enable --now avahi-daemon.service
        mkdir -p "$NFTD"
        cat > "$MDNS_DROPIN" <<'NFT'
#!/usr/sbin/nft -f
# Added by the InterGenOS Welcomer "Enable Network Discovery" toggle.
# mDNS / DNS-SD (Avahi) — link-local multicast DNS on udp/5353. Delete this
# file (or toggle Network Discovery off in the Welcomer) to revert.
table inet filter {
    chain input {
        udp dport 5353 accept
    }
}
NFT
        reload_firewall
        ;;
    disable-discovery)
        systemctl disable --now avahi-daemon.service avahi-daemon.socket 2>/dev/null || true
        rm -f "$MDNS_DROPIN"
        reload_firewall
        ;;
    enable-ssh)
        systemctl enable --now sshd.service
        mkdir -p "$NFTD"
        cat > "$SSH_DROPIN" <<'NFT'
#!/usr/sbin/nft -f
# Added by the InterGenOS Welcomer "Enable SSH Server" toggle.
# OpenSSH inbound on tcp/22 (key-only authentication per D-007). Delete this
# file (or toggle SSH off in the Welcomer) to revert.
table inet filter {
    chain input {
        tcp dport 22 accept
    }
}
NFT
        reload_firewall
        ;;
    disable-ssh)
        systemctl disable --now sshd.service 2>/dev/null || true
        rm -f "$SSH_DROPIN"
        reload_firewall
        ;;
    *)
        echo "usage: intergen-welcome-privhelper {enable|disable}-{printing|discovery|ssh}" >&2
        exit 2
        ;;
esac
