#!/usr/bin/env bash # ============================================================================ # BastionGuard - Riavvio dei servizi --user per TUTTI gli utenti # ---------------------------------------------------------------------------- # Pensato per essere chiamato dal pacchetto Debian (postinst, triggers, # o un dpkg trigger su /usr/lib/systemd/user/) dopo un upgrade dei binari # o delle unit user-level di BastionGuard. # # Lo script gira SEMPRE come root e: # 1. Fa "systemctl --global daemon-reload" così le unit installate in # /usr/lib/systemd/user/ vengono ripescate dai futuri manager utente. # 2. Trova TUTTI gli utenti con un user-manager systemd attivo: # - sessioni attive (loginctl list-users) # - utenti lingering (loginctl show-user --property=Linger) # - utenti con /run/user/ esistente # 3. Per ognuno fa: # - daemon-reload sul SUO bus (--global non aggiorna i manager già vivi) # - try-restart di tutte le unit BastionGuard-*.service realmente # installate per quell'utente # 4. Salta utenti di sistema (UID < 1000) e utenti senza /run/user/. # # Exit code: sempre 0 (non blocca dpkg --configure). # # Posizione: /usr/share/BastionGuard/data/scripts/ # Esempio di chiamata da debian/postinst: # # if [ "$1" = "configure" ] || [ "$1" = "triggered" ]; then # /usr/share/BastionGuard/data/scripts/BastionGuard-restart-user-services.sh || true # fi # ============================================================================ set -u # ---------------------------------------------------------------------------- # Lista delle unit --user di BastionGuard. # Tieni allineato con i .service spediti in /usr/lib/systemd/user/. # ---------------------------------------------------------------------------- ALL_SERVICES=( "BastionGuard-cef.service" "BastionGuard-mailproxy.service" "BastionGuard-pacd.service" "BastionGuard-phishing-scanner.service" "BastionGuard-phishing-updater.service" "BastionGuard-privacyd.service" "BastionGuard-ransomware-alert.service" "BastionGuard-ransomware-realtime-alert.service" "BastionGuard-ransomware-realtime.service" "BastionGuard-ransomware-scanner.service" "BastionGuard-usbd.service" "BastionGuard-useragent.service" ) # ---------------------------------------------------------------------------- # Logging (stderr, prefissato, no colori per non sporcare apt) # ---------------------------------------------------------------------------- log() { printf '[BastionGuard] %s\n' "$*" >&2; } warn() { printf '[BastionGuard] WARN: %s\n' "$*" >&2; } err() { printf '[BastionGuard] ERR : %s\n' "$*" >&2; } # ---------------------------------------------------------------------------- # Prerequisiti # ---------------------------------------------------------------------------- if ! command -v systemctl >/dev/null 2>&1; then log "systemctl non presente, salto il riavvio dei servizi user." exit 0 fi # In chroot/container /run/systemd/system non esiste: niente da fare. if [[ ! -d /run/systemd/system ]]; then log "systemd non in esecuzione (chroot/container?), salto." exit 0 fi if [[ "$EUID" -ne 0 ]]; then err "Questo script va eseguito come root (chiamato dal package manager)." exit 0 fi # UID minimo "umano". Standard è 1000 su Debian/Ubuntu/Fedora/openSUSE/Arch, # ma rispettiamo /etc/login.defs se diverso. UID_MIN=1000 if [[ -r /etc/login.defs ]]; then _u="$(awk '/^[[:space:]]*UID_MIN/ {print $2; exit}' /etc/login.defs 2>/dev/null || true)" [[ "$_u" =~ ^[0-9]+$ ]] && UID_MIN="$_u" fi # ---------------------------------------------------------------------------- # Step 1: daemon-reload globale (futuri manager utente). # ---------------------------------------------------------------------------- log "systemctl daemon-reload" systemctl daemon-reload >/dev/null 2>&1 || \ warn "daemon-reload fallito (best-effort)" # ---------------------------------------------------------------------------- # Step 2: enumerazione utenti con user-manager attivo. # ---------------------------------------------------------------------------- declare -A USERS_SET=() if command -v loginctl >/dev/null 2>&1; then # Tutti gli utenti noti a logind while IFS= read -r _user; do [[ -z "$_user" ]] && continue USERS_SET["$_user"]=1 done < <(loginctl list-users --no-legend 2>/dev/null | awk '{print $2}') fi # Utenti con /run/user/: cattura sia logged-in sia lingering. for d in /run/user/*; do [[ -d "$d" ]] || continue uid="$(basename "$d")" [[ "$uid" =~ ^[0-9]+$ ]] || continue [[ "$uid" -lt $UID_MIN ]] && continue user="$(getent passwd "$uid" | cut -d: -f1)" [[ -n "$user" ]] && USERS_SET["$user"]=1 done if [[ ${#USERS_SET[@]} -eq 0 ]]; then log "Nessun utente con sessione/linger attivo: niente da riavviare." exit 0 fi # ---------------------------------------------------------------------------- # run_as_user # # Esegue "systemctl --user " nel contesto del manager utente di . # Stesso pattern di src/Backend.cpp (runuser ... systemctl --user) e # src/wizard/wizard_setup.cpp (export XDG_RUNTIME_DIR/DBUS_SESSION_BUS_ADDRESS). # ---------------------------------------------------------------------------- run_as_user() { local user="$1"; shift local uid uid="$(id -u "$user" 2>/dev/null)" || return 2 [[ "$uid" -lt $UID_MIN ]] && return 3 [[ -d "/run/user/$uid" ]] || return 4 runuser -u "$user" -- env \ XDG_RUNTIME_DIR="/run/user/$uid" \ DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/$uid/bus" \ systemctl --user "$@" } # ---------------------------------------------------------------------------- # Step 3: per ogni utente, daemon-reload + try-restart delle unit installate. # ---------------------------------------------------------------------------- total_users=0 ok_users=0 for user in "${!USERS_SET[@]}"; do uid="$(id -u "$user" 2>/dev/null || true)" if [[ -z "$uid" || "$uid" -lt $UID_MIN ]]; then continue fi if [[ ! -d "/run/user/$uid" ]]; then warn "Utente '$user' (uid=$uid) senza /run/user/$uid, salto." continue fi total_users=$((total_users + 1)) log "→ Utente '$user' (uid=$uid)" # daemon-reload del manager utente vivo run_as_user "$user" daemon-reload >/dev/null 2>&1 || \ warn " daemon-reload utente fallito" user_fail=0 user_done=0 for svc in "${ALL_SERVICES[@]}"; do # L'unit è installata per questo utente? if ! run_as_user "$user" list-unit-files "$svc" >/dev/null 2>&1; then continue fi # try-restart: riavvia solo se è già in esecuzione. Più sicuro in # postinst: non riaccende servizi che l'utente aveva fermato. # Cambia in "restart" se vuoi forzare l'avvio. if run_as_user "$user" try-restart "$svc" >/dev/null 2>&1; then log " ✔ try-restart $svc" user_done=$((user_done + 1)) else warn " ✘ try-restart $svc fallito" user_fail=$((user_fail + 1)) fi done if [[ $user_fail -eq 0 ]]; then ok_users=$((ok_users + 1)) log " utente '$user': $user_done unit riavviate." else log " utente '$user': $user_done OK, $user_fail errori." fi done log "Riepilogo: $ok_users/$total_users utenti gestiti senza errori." exit 0