#!/bin/bash
# UGREEN — local privilege-boundary hardening (reversible)
# Strips elevated bits from selected system helpers; restores from on-disk snapshot.
set -euo pipefail

readonly UG_VENDOR="ugreen"
readonly UG_STORE="/var/lib/${UG_VENDOR}/hardening"
readonly UG_SNAP="${UG_STORE}/privbound.snapshot"

# tag|bit_to_clear|candidate paths (space-separated in field 3+)
readonly -a UG_REGISTRY=(
  "openssh_signer|u|/usr/libexec/ssh-keysign /usr/libexec/openssh/ssh-keysign /usr/lib/ssh/ssh-keysign /usr/lib/openssh/ssh-keysign"
  "shadow_chfn|g|/usr/bin/chage /bin/chage /usr/sbin/chage /sbin/chage"
)

ug_root() {
  if [ "$(id -u)" -ne 0 ]; then
    exec sudo -E bash "$0" "$@"
  fi
}

ug_ensure_store() {
  install -d -m 0750 "${UG_STORE}"
}

ug_resolve() {
  local -a candidates=()
  local token
  for token in $*; do
    candidates+=("${token}")
  done
  local c
  for c in "${candidates[@]}"; do
    if [ -e "${c}" ]; then
      printf '%s\n' "${c}"
      return 0
    fi
  done
  return 1
}

ug_perm_oct() {
  stat -c '%a' "$1" 2>/dev/null || true
}

ug_clear_bit() {
  local bit="$1"
  local path="$2"
  case "${bit}" in
    u) chmod u-s "${path}" ;;
    g) chmod g-s "${path}" ;;
    *) return 1 ;;
  esac
}

ug_snap_get() {
  local tag="$1" field="$2"
  local key="${tag}.${field}"
  [ -f "${UG_SNAP}" ] || return 1
  awk -F= -v k="${key}" '$1==k {print $2; exit}' "${UG_SNAP}" 2>/dev/null
}

ug_snap_set() {
  local tag="$1" path="$2" mode="$3"
  local tmp
  tmp="$(mktemp "${UG_STORE}/.snap.XXXXXX")"
  if [ -f "${UG_SNAP}" ]; then
    awk -F= -v t="${tag}" '$1 != t".path" && $1 != t".mode"' "${UG_SNAP}" >"${tmp}" || true
  fi
  {
    [ -s "${tmp}" ] && cat "${tmp}"
    printf '%s.path=%s\n' "${tag}" "${path}"
    printf '%s.mode=%s\n' "${tag}" "${mode}"
  } >"${UG_SNAP}"
  rm -f "${tmp}"
  chmod 0640 "${UG_SNAP}"
}

ug_apply_entry() {
  local spec="$1"
  local tag bit paths path mode
  tag="${spec%%|*}"
  spec="${spec#*|}"
  bit="${spec%%|*}"
  paths="${spec#*|}"

  path="$(ug_resolve ${paths})" || return 0
  mode="$(ug_perm_oct "${path}")"
  [ -n "${mode}" ] || return 0

  ug_clear_bit "${bit}" "${path}"
  ug_snap_set "${tag}" "${path}" "${mode}"
  echo "[UGREEN] hardened ${path} (saved mode ${mode})"
}

ug_revert_entry() {
  local tag="$1"
  local path mode
  path="$(ug_snap_get "${tag}" path)" || return 0
  mode="$(ug_snap_get "${tag}" mode)" || return 0
  [ -n "${path}" ] && [ -n "${mode}" ] && [ -e "${path}" ] || return 0
  chmod "${mode}" "${path}"
  echo "[UGREEN] reverted ${path} -> ${mode}"
}

ug_report_entry() {
  local spec="$1"
  local tag bit paths path saved live
  tag="${spec%%|*}"
  spec="${spec#*|}"
  bit="${spec%%|*}"
  paths="${spec#*|}"

  saved="$(ug_snap_get "${tag}" path)" || true
  if [ -n "${saved:-}" ]; then
    echo "[UGREEN] ${tag}: recorded ${saved} (mode $(ug_snap_get "${tag}" mode))"
  else
    echo "[UGREEN] ${tag}: no recorded path"
  fi

  path="$(ug_resolve ${paths})" || {
    echo "[UGREEN] ${tag}: not present on system"
    return 0
  }
  live="$(ug_perm_oct "${path}")"
  echo "[UGREEN] ${tag}: live ${path} mode ${live} (clear-${bit} target)"
}

ug_cmd_apply() {
  local row
  for row in "${UG_REGISTRY[@]}"; do
    ug_apply_entry "${row}"
  done
  echo "[UGREEN] hardening active — revert with: $0 enable"
}

ug_cmd_revert() {
  local row tag
  for row in "${UG_REGISTRY[@]}"; do
    tag="${row%%|*}"
    ug_revert_entry "${tag}"
  done
  echo "[UGREEN] revert finished"
}

ug_cmd_inspect() {
  echo "[UGREEN] snapshot: ${UG_SNAP}"
  local row
  for row in "${UG_REGISTRY[@]}"; do
    ug_report_entry "${row}"
  done
}

ug_usage() {
  cat <<EOF
UGREEN privilege-boundary helper

  $0 disable   apply hardening (strip setuid/setgid on registered binaries)
  $0 enable    restore permissions from snapshot
  $0 status    show snapshot and current modes

EOF
}

main() {
  ug_root "$@"
  ug_ensure_store

  case "${1:-}" in
    disable) ug_cmd_apply ;;
    enable)  ug_cmd_revert ;;
    status)  ug_cmd_inspect ;;
    *)       ug_usage; exit 1 ;;
  esac
}

main "$@"
