#!/usr/bin/env bash
# Install + configure ``msfrpcd`` for the Tier-3 exploit driver.
#
# Idempotent: re-running on a host that already has msfrpcd refreshes
# the systemd unit and credentials but doesn't reinstall the framework.
#
# Steps:
#   1. Install metasploit-framework via the host package manager (or
#      report the right one-liner for that distro). Big download —
#      ~1 GiB and several minutes.
#   2. Generate a strong password and store at /etc/cis490/msfrpc.env
#      (mode 0640, owner root:cis490).
#   3. Drop /etc/systemd/system/cis490-msfrpcd.service that runs
#      msfrpcd bound to 127.0.0.1:55553 with the generated password.
#   4. Enable + start.
#
# After this runs, ``MSFRPC_PASSWORD=$(. /etc/cis490/msfrpc.env;
# echo $MSFRPC_PASSWORD)`` makes tools/run_tier3_demo.py work zero-touch.

set -euo pipefail

ETC_ROOT="/etc/cis490"
ENV_FILE="$ETC_ROOT/msfrpc.env"
UNIT="/etc/systemd/system/cis490-msfrpcd.service"
PORT="${MSFRPC_PORT:-55553}"
USER_NAME="${MSFRPC_USER:-msf}"

log() { printf '[install-msfrpcd] %s\n' "$*" >&2; }
die() { log "FATAL: $*"; exit 1; }

[[ $EUID -eq 0 ]] || die "must run as root"
command -v systemctl >/dev/null || die "systemd not found"

# --- 1. install metasploit-framework -----------------------------------
# Auto-install paths per package manager. Rapid7's omnibus installer
# is the canonical zero-touch path for Debian/Ubuntu — it adds the
# apt repo, the GPG key, and apt-installs the framework. Other
# distros use their native package or fall back to the omnibus shell
# script.
if ! command -v msfrpcd >/dev/null && [[ ! -x /opt/metasploit-framework/bin/msfrpcd ]]; then
    log "msfrpcd not found; installing metasploit-framework (~1 GiB)"
    if command -v apt-get >/dev/null; then
        # Rapid7's omnibus installer wraps the apt-repo + GPG-key
        # bootstrap + apt install in a single script. We fetch and
        # exec it non-interactively. The script does:
        #   1. add apt.metasploit.com to /etc/apt/sources.list.d/
        #   2. install the GPG key
        #   3. apt-get install -y metasploit-framework
        log "running Rapid7 omnibus installer"
        TMP="$(mktemp -d)"
        curl -fsSL \
            https://raw.githubusercontent.com/rapid7/metasploit-omnibus/master/config/templates/metasploit-framework-wrappers/msfupdate.erb \
            -o "$TMP/msfinstall"
        chmod +x "$TMP/msfinstall"
        DEBIAN_FRONTEND=noninteractive "$TMP/msfinstall" </dev/null
        rm -rf "$TMP"
    elif command -v pacman >/dev/null; then
        log "pacman -S metasploit"
        pacman -Sy --noconfirm metasploit
    elif command -v dnf >/dev/null; then
        # The omnibus installer also supports rpm distros via the
        # same script — it auto-detects and uses dnf/yum.
        log "running Rapid7 omnibus installer (dnf path)"
        TMP="$(mktemp -d)"
        curl -fsSL \
            https://raw.githubusercontent.com/rapid7/metasploit-omnibus/master/config/templates/metasploit-framework-wrappers/msfupdate.erb \
            -o "$TMP/msfinstall"
        chmod +x "$TMP/msfinstall"
        "$TMP/msfinstall" </dev/null
        rm -rf "$TMP"
    else
        die "unknown package manager — install metasploit-framework manually, then re-run"
    fi
fi

# After install, msfrpcd may live at /opt/metasploit-framework/bin/
# (omnibus) or on PATH (apt repo). Symlink so callers find it.
if ! command -v msfrpcd >/dev/null; then
    if [[ -x /opt/metasploit-framework/bin/msfrpcd ]]; then
        ln -sf /opt/metasploit-framework/bin/msfrpcd /usr/local/bin/msfrpcd
    fi
fi
command -v msfrpcd >/dev/null || die "msfrpcd still missing after install — see journalctl"

# --- 2. generate password ----------------------------------------------
install -d -m 0755 -o root -g root "$ETC_ROOT"
if ! id -u cis490 >/dev/null 2>&1; then
    useradd --system --no-create-home --shell /usr/sbin/nologin cis490
fi
if [[ ! -f "$ENV_FILE" ]]; then
    log "generating msfrpc password"
    PW="$(openssl rand -base64 24 | tr -d '/+=' | head -c 32)"
    install -m 0640 -o root -g cis490 /dev/stdin "$ENV_FILE" <<EOF
# Auto-generated by install-msfrpcd.sh — do not edit.
MSFRPC_HOST=127.0.0.1
MSFRPC_PORT=$PORT
MSFRPC_USER=$USER_NAME
MSFRPC_PASSWORD=$PW
EOF
else
    log "$ENV_FILE exists; preserving existing password"
fi

# --- 3. systemd unit ----------------------------------------------------
# msfrpcd writes module cache + logs to $HOME/.msf4. With ProtectHome=true
# the service can't reach /root, so we redirect HOME to a path under
# /var/lib/cis490 that is always writable.
MSF_HOME="/var/lib/cis490/msf4"
install -d -m 0755 -o root -g root "$MSF_HOME"

log "installing systemd unit"
cat > "$UNIT" <<EOF
[Unit]
Description=CIS490 — Metasploit RPC daemon (loopback only)
Documentation=https://maxgit.wg/spectral/CIS490
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
EnvironmentFile=$ENV_FILE
Environment=HOME=$MSF_HOME
# msfrpcd flags:
#   -P <pw>   password
#   -U <user> username
#   -a <ip>   bind address (loopback only — Tier-3 driver runs locally)
#   -p <port> port
#   -f        foreground (no daemonization, so systemd manages PID)
ExecStart=/usr/bin/env msfrpcd -P \${MSFRPC_PASSWORD} -U \${MSFRPC_USER} -a 127.0.0.1 -p \${MSFRPC_PORT} -f
Restart=on-failure
RestartSec=5
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=full
ProtectHome=true

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable --now cis490-msfrpcd

# --- 4. final smoke -----------------------------------------------------
sleep 2
if ! ss -ltn 2>/dev/null | grep -q ":$PORT"; then
    log "WARN: nothing listening on 127.0.0.1:$PORT yet — check"
    log "       journalctl -u cis490-msfrpcd"
fi

log "done. To run a Tier-3 episode:"
log "  set -a; . $ENV_FILE; set +a"
log "  python tools/run_tier3_demo.py --module vsftpd_234_backdoor"
