This commit is contained in:
2026-11-04 20:35:46 +01:00
parent 5f4de5e60c
commit 86abc097f4
348 changed files with 10300 additions and 0 deletions
@@ -0,0 +1,67 @@
#!/bin/bash
#
# DNF Updater - Privileged Update Helper
#
# Restricts privileged execution strictly to system package upgrades
# with validated exclusions. Prevents arbitrary command execution or
# malicious package installations.
#
set -euo pipefail
# Help / usage
if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
echo "Usage: dnf-updater-helper upgrade [--exclude=<pkg1,pkg2,...>]"
exit 0
fi
# Ensure standard, safe environment
export PATH="/usr/bin:/bin:/usr/sbin:/sbin"
unset IFS
unset LD_PRELOAD LD_LIBRARY_PATH PYTHONPATH PYTHONHOME DNF5_PLUGINS
# Require root
if [[ "${EUID:-$(id -u)}" -ne 0 ]]; then
echo "Error: dnf-updater-helper must be run as root." >&2
exit 1
fi
ACTION="${1:-}"
if [[ "$ACTION" != "upgrade" ]]; then
echo "Error: unsupported action '${ACTION}'. Only 'upgrade' is allowed." >&2
echo "Usage: dnf-updater-helper upgrade [--exclude=<pkg1,pkg2,...>]" >&2
exit 1
fi
shift
# Validate any remaining arguments.
VALID_ARGS=()
for arg in "$@"; do
if [[ "$arg" =~ ^--exclude=[a-zA-Z0-9._+*:-][a-zA-Z0-9._+*:,-]*$ ]]; then
VALID_ARGS+=("$arg")
else
echo "Error: invalid argument rejected: '$arg'" >&2
exit 1
fi
done
# Resolve DNF binary
DNF_BIN=""
for bin in "/usr/bin/dnf5" "/usr/bin/dnf"; do
if [[ -x "$bin" ]]; then
DNF_BIN="$bin"
break
fi
done
if [[ -z "$DNF_BIN" ]]; then
echo "Error: neither /usr/bin/dnf5 nor /usr/bin/dnf was found." >&2
exit 1
fi
# Execute upgrade w/o interaction, inhibiting sleep/shutdown if systemd-inhibit is available
if command -v systemd-inhibit >/dev/null 2>&1; then
exec systemd-inhibit --what=shutdown:sleep:idle --who="dnf-updater" --why="Performing system package upgrade" "$DNF_BIN" upgrade -y "${VALID_ARGS[@]}"
else
exec "$DNF_BIN" upgrade -y "${VALID_ARGS[@]}"
fi
@@ -0,0 +1,119 @@
#!/bin/bash
#
# DNF Updater - Privileged Helper & Polkit Policy Installer
#
# Installs or uninstalls the privileged helper and Polkit rule.
# Supports both local repository invocation and remote execution via:
# curl -fsSL https://raw.githubusercontent.com/strob3/dnf-updater/main/scripts/install.sh | sudo bash
#
set -euo pipefail
DEST_BIN="/usr/local/bin/dnf-updater-helper"
DEST_POLKIT="/etc/polkit-1/rules.d/50-dnf-updater.rules"
REPO_RAW_URL="https://raw.githubusercontent.com/strob3/dnf-updater/main"
# Help / usage
if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
echo "Usage: $0 [install|--uninstall]"
echo ""
echo "Commands:"
echo " install Install helper to $DEST_BIN and rule to $DEST_POLKIT (default)"
echo " --uninstall Remove helper and Polkit rule from the system"
exit 0
fi
# Verify root privileges
if [[ "${EUID:-$(id -u)}" -ne 0 ]]; then
echo "Error: Installation requires root privileges. Please run with sudo:" >&2
echo " sudo $0 $@" >&2
exit 1
fi
ACTION="${1:-install}"
case "$ACTION" in
uninstall|--uninstall|-u)
echo "Removing DNF Updater privileged helper and Polkit rule..."
rm -f "$DEST_BIN" "$DEST_POLKIT"
echo "✓ Successfully removed:"
echo " - $DEST_BIN"
echo " - $DEST_POLKIT"
exit 0
;;
install|--install|-i)
;;
*)
echo "Error: unknown argument '$ACTION'" >&2
echo "Usage: $0 [install|--uninstall]" >&2
exit 1
;;
esac
echo "==> Installing DNF Updater privileged helper and Polkit rule..."
# Determine script location if running locally
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd || true)"
SRC_HELPER=""
SRC_POLKIT=""
CLEANUP_TMP=false
TMP_DIR=""
if [[ -n "$SCRIPT_DIR" && -f "${SCRIPT_DIR}/dnf-updater-helper.sh" && -f "${SCRIPT_DIR}/../polkit/50-dnf-updater.rules" ]]; then
echo " → Using local repository files..."
SRC_HELPER="${SCRIPT_DIR}/dnf-updater-helper.sh"
SRC_POLKIT="${SCRIPT_DIR}/../polkit/50-dnf-updater.rules"
elif [[ -n "$SCRIPT_DIR" && -f "${SCRIPT_DIR}/scripts/dnf-updater-helper.sh" && -f "${SCRIPT_DIR}/polkit/50-dnf-updater.rules" ]]; then
echo " → Using local repository files..."
SRC_HELPER="${SCRIPT_DIR}/scripts/dnf-updater-helper.sh"
SRC_POLKIT="${SCRIPT_DIR}/polkit/50-dnf-updater.rules"
else
echo " → Fetching latest files from GitHub ($REPO_RAW_URL)..."
TMP_DIR="$(mktemp -d)"
CLEANUP_TMP=true
trap 'rm -rf "$TMP_DIR"' EXIT
if command -v curl >/dev/null 2>&1; then
curl -fsSL "${REPO_RAW_URL}/scripts/dnf-updater-helper.sh" -o "${TMP_DIR}/dnf-updater-helper.sh"
curl -fsSL "${REPO_RAW_URL}/polkit/50-dnf-updater.rules" -o "${TMP_DIR}/50-dnf-updater.rules"
elif command -v wget >/dev/null 2>&1; then
wget -qO "${TMP_DIR}/dnf-updater-helper.sh" "${REPO_RAW_URL}/scripts/dnf-updater-helper.sh"
wget -qO "${TMP_DIR}/50-dnf-updater.rules" "${REPO_RAW_URL}/polkit/50-dnf-updater.rules"
else
echo "Error: neither curl nor wget was found to download required files." >&2
exit 1
fi
SRC_HELPER="${TMP_DIR}/dnf-updater-helper.sh"
SRC_POLKIT="${TMP_DIR}/50-dnf-updater.rules"
fi
# Install privileged helper
install -Dm755 "$SRC_HELPER" "$DEST_BIN"
echo " ✓ Installed privileged helper: $DEST_BIN (mode 0755)"
# Install Polkit rule
install -Dm644 "$SRC_POLKIT" "$DEST_POLKIT"
echo " ✓ Installed Polkit policy: $DEST_POLKIT (mode 0644)"
# Fix SELinux context if SELinux is available
if command -v restorecon >/dev/null 2>&1; then
restorecon -F "$DEST_BIN" "$DEST_POLKIT" 2>/dev/null || true
fi
# Check if target user belongs to wheel or sudo
INVOKER="${SUDO_USER:-$USER}"
if [[ -n "$INVOKER" && "$INVOKER" != "root" ]]; then
if ! id -nG "$INVOKER" 2>/dev/null | grep -Ewq "wheel|sudo"; then
echo ""
echo " ⚠ Warning: User '$INVOKER' is not in the 'wheel' or 'sudo' group."
echo " Polkit requires administrative group membership for passwordless updates."
echo " Add your user with: sudo usermod -aG wheel $INVOKER"
fi
fi
echo ""
echo "✓ Installation complete!"
echo "💡 Tip: To enable background updates without terminal popups, ensure 'Run Updates in Terminal'"
echo " is turned off in Noctalia Settings → Plugins → DNF Updater."