#!/bin/sh
# mspcorex-capability-probe (Track C §3.4) — D2 at the HOST level: report which
# privilege-drop / cgroup / systemd-hardening features the running host actually
# supports, so an operator (and the backend) can see what is enforced vs silently
# ignored on legacy distros (Debian 8/9, EL7) instead of guessing.
#
# CONTRACT: POSIX sh (/bin/sh is dash on jessie), 100% read-only except for the
# one JSON it writes, and ALWAYS exits 0 (D2: report, never refuse to start).
# Shipped by BOTH lanes (.deb here, .rpm via the spec). Run by postinst and as an
# `ExecStartPre=-` hook.
#
# ⚠️ The cgroup half reads the RUNNING kernel's hierarchy — inside a container it
# reports the HOST kernel's, so it is only authoritative on a real host, not in a
# build container.
set -u

# The unit manages RuntimeDirectory=mspcorex (= /run/mspcorex). postinst runs
# this BEFORE any RuntimeDirectory exists, so create it defensively.
OUT_DIR="${MSPCOREX_RUNTIME_DIR:-/run/mspcorex}"
OUT="${OUT_DIR}/capabilities.json"
HARDENING_TABLE="/usr/share/doc/mspcorex-agent-server/systemd-hardening-floors.txt"
mkdir -p "$OUT_DIR" 2>/dev/null || OUT="/tmp/mspcorex-capabilities.json"

jstr() { printf '%s' "$1" | sed 's/\\/\\\\/g; s/"/\\"/g'; }

# ── setpriv mode ─────────────────────────────────────────────────────────────
# init-groups   : setpriv --init-groups works (modern) → current shell-out OK
# explicit-groups: setpriv present but no --init-groups (EL7 2.23) → --groups path
# present-unusable: setpriv present but neither flag → native privdrop needed
# none          : no setpriv (jessie/stretch) → native privdrop mandatory
SETPRIV_MODE="none"
if command -v setpriv >/dev/null 2>&1; then
  if setpriv --help 2>&1 | grep -q -- '--init-groups'; then
    SETPRIV_MODE="init-groups"
  elif setpriv --help 2>&1 | grep -q -- '--groups'; then
    SETPRIV_MODE="explicit-groups"
  else
    SETPRIV_MODE="present-unusable"
  fi
fi

# ── cgroup hierarchy ─────────────────────────────────────────────────────────
CGROUP_MODE="none"
if [ -e /sys/fs/cgroup/cgroup.controllers ]; then
  CGROUP_MODE="v2-unified"
elif grep -q 'cgroup2' /proc/self/mountinfo 2>/dev/null; then
  CGROUP_MODE="hybrid"
elif grep -q '^cgroup ' /proc/mounts 2>/dev/null || [ -d /sys/fs/cgroup/memory ]; then
  CGROUP_MODE="v1-legacy"
fi

# ── systemd version + self-update capability ────────────────────────────────
SYSTEMD_VERSION=""
if command -v systemctl >/dev/null 2>&1; then
  SYSTEMD_VERSION="$(systemctl --version 2>/dev/null | head -1 | grep -oE '[0-9]+' | head -1)"
fi
SYSTEMD_RUN_COLLECT="no"
if command -v systemd-run >/dev/null 2>&1 && [ -n "$SYSTEMD_VERSION" ] && [ "$SYSTEMD_VERSION" -ge 236 ] 2>/dev/null; then
  SYSTEMD_RUN_COLLECT="yes"
fi

# ── hardening directives IGNORED on this host's systemd (§3.3 table cross-ref) ─
# For each directive the shipped unit sets, if this host's systemd predates the
# version that introduced it, systemd parses+warns+IGNORES it → un-enforced.
HARDENING_IGNORED=""
if [ -r "$HARDENING_TABLE" ] && [ -n "$SYSTEMD_VERSION" ]; then
  while IFS='	' read -r d minv; do
    case "$d" in ''|\#*) continue ;; esac
    if [ "$SYSTEMD_VERSION" -lt "$minv" ] 2>/dev/null; then
      HARDENING_IGNORED="${HARDENING_IGNORED:+$HARDENING_IGNORED, }\"$(jstr "$d")\""
    fi
  done < "$HARDENING_TABLE"
fi

# ── seccomp: is a filter loaded on THIS process? (direct enforcement signal) ──
# Seccomp != 0 proves SOME filter is loaded, not specifically systemd's
# RestrictAddressFamilies — decisive for NotEnforced, only suggestive for
# Enforced. Cross-referenced with the +/-SECCOMP build flag of systemd.
SECCOMP_SELF="$(grep -m1 '^Seccomp:' /proc/self/status 2>/dev/null | awk '{print $2}')"
[ -z "$SECCOMP_SELF" ] && SECCOMP_SELF="unknown"
SECCOMP_BUILD="unknown"
if command -v systemctl >/dev/null 2>&1; then
  if systemctl --version 2>/dev/null | grep -q '+SECCOMP'; then SECCOMP_BUILD="yes"
  elif systemctl --version 2>/dev/null | grep -q -- '-SECCOMP'; then SECCOMP_BUILD="no"; fi
fi

DISTRO="unknown"; DISTRO_VER=""
if [ -r /etc/os-release ]; then
  # shellcheck disable=SC1091
  . /etc/os-release 2>/dev/null
  DISTRO="${ID:-unknown}"; DISTRO_VER="${VERSION_ID:-}"
fi

cat > "$OUT" <<EOF
{
  "schema": 1,
  "distro": "$(jstr "$DISTRO")",
  "distro_version": "$(jstr "$DISTRO_VER")",
  "kernel": "$(jstr "$(uname -r 2>/dev/null)")",
  "arch": "$(jstr "$(uname -m 2>/dev/null)")",
  "setpriv_mode": "$(jstr "$SETPRIV_MODE")",
  "cgroup_mode": "$(jstr "$CGROUP_MODE")",
  "cgroup_note": "reads the running kernel; authoritative only on a real host",
  "systemd_version": "$(jstr "$SYSTEMD_VERSION")",
  "systemd_run_collect": "$(jstr "$SYSTEMD_RUN_COLLECT")",
  "systemd_hardening_ignored": [${HARDENING_IGNORED}],
  "seccomp_self": "$(jstr "$SECCOMP_SELF")",
  "seccomp_build": "$(jstr "$SECCOMP_BUILD")"
}
EOF

echo "[capability-probe] wrote $OUT (setpriv=$SETPRIV_MODE cgroup=$CGROUP_MODE systemd=${SYSTEMD_VERSION:-none})"
exit 0
