#!/usr/bin/env bash
# deadman.sh — Dead Man's Switch lab (ch.11)
# ---------------------------------------------------------------------------
# A real dead man's switch: arm an ENCRYPTED payload, 'check in' to push the
# deadline, and a systemd timer fires a one-time RELEASE of the ciphertext if
# you go silent past the TTL. Keys live OFF the box — recipients decrypt.
#   deadman.sh install                  set up state + an hourly systemd timer
#   deadman.sh arm <file> <age-recip>   encrypt <file> to the recipient, arm it
#   deadman.sh checkin                  reset the deadline (do this regularly)
#   deadman.sh check                    evaluate; fire if past TTL (timer runs this)
#   deadman.sh status | disarm
# TTL is hours; override with  TTL_HOURS=48 deadman.sh ...
# ---------------------------------------------------------------------------
set -uo pipefail
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; NC='\033[0m'
STATE="/var/lib/deadman"; TTL_HOURS="${TTL_HOURS:-72}"
SELF="$(readlink -f "$0")"
need_root(){ [[ ${EUID:-$(id -u)} -eq 0 ]] || { echo -e "${RED}run as root${NC}"; exit 1; }; }

install_timer() {
  need_root; install -d -m 0700 "$STATE"
  command -v age >/dev/null 2>&1 || { export DEBIAN_FRONTEND=noninteractive; apt-get update -qq && apt-get install -y age; }
  date +%s > "$STATE/last_checkin"
  cat > /etc/systemd/system/deadman.service <<EOF
[Unit]
Description=Dead man's switch check
[Service]
Type=oneshot
Environment=TTL_HOURS=${TTL_HOURS}
ExecStart=${SELF} check
EOF
  cat > /etc/systemd/system/deadman.timer <<'EOF'
[Unit]
Description=Run the dead man's switch check hourly
[Timer]
OnBootSec=15min
OnUnitActiveSec=1h
Persistent=true
[Install]
WantedBy=timers.target
EOF
  systemctl daemon-reload; systemctl enable --now deadman.timer
  echo -e "${GREEN}[+] Installed. TTL=${TTL_HOURS}h. Arm a payload, then check in regularly:${NC}"
  echo    "    ${SELF} arm /path/to/secret.txt age1yourrecipient...   ;   ${SELF} checkin"
}

arm() {
  need_root; local file="${1:-}" recip="${2:-}"
  [[ -f "$file" && -n "$recip" ]] || { echo "usage: $0 arm <file> <age-recipient (age1...)>"; exit 1; }
  command -v age >/dev/null 2>&1 || { apt-get update -qq && apt-get install -y age; }
  age -r "$recip" -o "$STATE/payload.age" "$file" || { echo -e "${RED}encryption failed${NC}"; exit 1; }
  chmod 600 "$STATE/payload.age"; rm -f "$STATE/fired"; date +%s > "$STATE/last_checkin"
  echo -e "${GREEN}[+] Armed. Ciphertext at $STATE/payload.age — plaintext NOT stored. Keep the age identity OFF this box.${NC}"
}

checkin(){ need_root; date +%s > "$STATE/last_checkin"; echo -e "${GREEN}[+] Checked in $(date -u). Deadline pushed ${TTL_HOURS}h.${NC}"; }

release() {
  echo -e "${RED}[!] DEAD MAN'S SWITCH FIRED $(date -u)${NC}"
  logger -t deadman "dead man's switch fired"
  # The payload is already ciphertext — dispatch it; recipients hold the key. Wire your channels:
  #   mail -s "release" recipient@example.org < "$STATE/payload.age"
  #   cp "$STATE/payload.age" /var/www/onion/      # publish to your .onion drop
  #   ... matrix / torrent magnet / etc.
}

check() {
  local last now age_h
  last="$(cat "$STATE/last_checkin" 2>/dev/null || echo 0)"
  now="$(date +%s)"; age_h=$(( (now - last) / 3600 ))
  if (( age_h >= TTL_HOURS )) && [ ! -f "$STATE/fired" ] && [ -f "$STATE/payload.age" ]; then
    : > "$STATE/fired"; release                  # idempotent: fire exactly once
  else
    echo "[i] ${age_h}h since check-in (TTL ${TTL_HOURS}h) · armed=$([ -f "$STATE/payload.age" ] && echo y || echo n) · fired=$([ -f "$STATE/fired" ] && echo y || echo n)"
  fi
}

status() {
  local last age_h; last="$(cat "$STATE/last_checkin" 2>/dev/null || echo 0)"
  age_h=$(( ($(date +%s) - last) / 3600 ))
  echo "TTL=${TTL_HOURS}h  last_checkin=$([ "$last" != 0 ] && date -u -d "@$last" || echo never)  age=${age_h}h"
  echo "armed=$([ -f "$STATE/payload.age" ] && echo yes || echo no)  fired=$([ -f "$STATE/fired" ] && echo yes || echo no)  timer=$(systemctl is-active deadman.timer 2>/dev/null || echo inactive)"
}

disarm(){ need_root; systemctl disable --now deadman.timer 2>/dev/null || true; rm -f "$STATE/fired"; echo -e "${GREEN}[+] Timer stopped.${NC}"; }

case "${1:-status}" in
  install) install_timer ;;
  arm)     shift; arm "$@" ;;
  checkin) checkin ;;
  check)   check ;;
  status)  status ;;
  disarm)  disarm ;;
  *) echo "usage: $0 {install|arm <file> <age-recip>|checkin|check|status|disarm}"; exit 1 ;;
esac
