#!/usr/bin/env bash

# `boot --server` is deliberately public and must be safe before it reaches the
# cloned repository. Exercise its root branch through a PTY, against only a
# temporary filesystem and PATH adapters.

set -uo pipefail

repo_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
boot="$repo_dir/boot"

[[ -x "$boot" ]] || {
    printf 'root server bootstrap: %s is not executable\n' "$boot" >&2
    exit 1
}

python3 - "$boot" <<'PY'
import atexit
import errno
import fcntl
import os
import pty
import re
import shutil
import subprocess
import sys
import tempfile
import termios
from pathlib import Path

boot = sys.argv[1]
work = Path(tempfile.mkdtemp())
atexit.register(shutil.rmtree, work, ignore_errors=True)
findings: list[str] = []


def note(message: str) -> None:
    findings.append(message)


def write_executable(path: Path, contents: str) -> None:
    path.write_text(contents)
    path.chmod(0o755)


def make_stubs(stub_dir: Path, fixture_root: Path, calls: Path) -> None:
    common = f'''#!/usr/bin/env bash
set -u
calls={str(calls)!r}
log() {{
  local argument
  {{ for argument in "$@"; do printf '%q ' "$argument"; done; printf '\\n'; }} >>"$calls"
}}
consume_result() {{
  local name="$1" results result
  results="$PANAMA_BOOT_FIXTURE_ROOT/state/$name"
  if ! IFS= read -r result <"$results"; then
    return 0
  fi
  /usr/bin/tail -n +2 "$results" >"$results.next"
  /usr/bin/mv -f -- "$results.next" "$results"
  [[ "$result" =~ ^[0-9]+$ ]] || exit 97
  return "$result"
}}
'''

    write_executable(stub_dir / "id", common + r'''
log id "$@"
case "${1:-}" in
  -u)
    case "${2:-}" in
      '') printf '0\n' ;;
      root) printf '0\n' ;;
      gib) cat "$PANAMA_BOOT_FIXTURE_ROOT/state/target-uid" ;;
      *) exit 97 ;;
    esac
    ;;
  -nG) [[ "${2:-}" == gib ]] || exit 97; printf 'gib wheel\n' ;;
  *) exit 97 ;;
esac
''')
    write_executable(stub_dir / "passwd", common + r'''
log passwd "$@"
[[ "${1:-}" == -S && "${2:-}" == gib ]] || exit 97
printf 'gib PS\n'
''')
    write_executable(stub_dir / "getent", common + r'''
log getent "$@"
[[ "${1:-}" == passwd && "${2:-}" == gib ]] || exit 97
home="$(<"$PANAMA_BOOT_FIXTURE_ROOT/state/home")"
printf 'gib:x:1000:1000::%s:/bin/bash\n' "$home"
''')
    write_executable(stub_dir / "stat", common + r'''
log stat "$@"
[[ "${1:-}" == -Lc && "${2:-}" == '%u:%a' ]] || exit 97
case "${3:-}" in
  "$PANAMA_BOOT_FIXTURE_ROOT/home/gib/.ssh") cat "$PANAMA_BOOT_FIXTURE_ROOT/state/target-dir-meta" ;;
  "$PANAMA_BOOT_FIXTURE_ROOT/home/gib/.ssh/authorized_keys") cat "$PANAMA_BOOT_FIXTURE_ROOT/state/target-key-meta" ;;
  "$PANAMA_BOOT_FIXTURE_ROOT/root/.ssh/authorized_keys") cat "$PANAMA_BOOT_FIXTURE_ROOT/state/root-key-meta" ;;
  *) exit 97 ;;
esac
''')
    write_executable(stub_dir / "runuser", common + r'''
log runuser "$@"
[[ "${1:-}" == -u && "${2:-}" == gib && "${3:-}" == -- ]] || exit 97
shift 3
"$@"
''')
    write_executable(stub_dir / "git", common + r'''
log git "$@"
case "${1:-}" in
  clone)
    mkdir -p "$3/.git"
    cp "$PANAMA_BOOT_FIXTURE_ROOT/stub-install" "$3/install"
    chmod +x "$3/install"
    ;;
  -C) [[ "${3:-}" == pull && "${4:-}" == --ff-only ]] || exit 97 ;;
  *) exit 97 ;;
esac
''')
    write_executable(stub_dir / "dnf", common + r'''
log dnf "$@"
[[ "${1:-}" == install && "${2:-}" == -y && "${3:-}" == git ]] || exit 97
''')
    write_executable(stub_dir / "sshd", common + r'''
log sshd "$@"
[[ "$#" -eq 1 && "$1" == -t ]] || exit 97
for artifact in "$PANAMA_BOOT_FIXTURE_ROOT/etc/ssh/sshd_config.d"/.90-panama.*; do
  [[ -e "$artifact" ]] || continue
  log ssh-artifact "$artifact" "$(/usr/bin/stat -c %a -- "$artifact")"
done
consume_result SSHD_RESULTS
''')
    write_executable(stub_dir / "systemctl", common + r'''
log systemctl "$@"
case "${1:-}:${2:-}" in
  cat:sshd.service) [[ "$(<"$PANAMA_BOOT_FIXTURE_ROOT/state/SSHD_UNIT")" == present ]] ;;
  cat:ssh.service) [[ "$(<"$PANAMA_BOOT_FIXTURE_ROOT/state/SSH_UNIT")" == present ]] ;;
  reload:sshd.service|reload:ssh.service) consume_result RELOAD_RESULTS ;;
  *) exit 97 ;;
esac
''')
    write_executable(stub_dir / "mv", common + r'''
log mv "$@" "source-mode=$(/usr/bin/stat -c %a -- "${3:-}")"
exec /usr/bin/mv "$@"
''')
    for command in ("useradd", "usermod"):
        write_executable(stub_dir / command, common + f'''\nlog {command} "$@"\nexit 97\n''')


def configure_case(
    name: str,
    *,
    sshd_results: tuple[int, ...] = (),
    reload_results: tuple[int, ...] = (),
    prior_dropin: bytes | None = None,
    sshd_unit: bool = True,
    ssh_unit: bool = True,
) -> tuple[Path, Path]:
    fixture_root = work / name / "root"
    stub_dir = work / name / "bin"
    calls = fixture_root / "calls"
    state = fixture_root / "state"
    ssh_dir = fixture_root / "home/gib/.ssh"
    root_ssh_dir = fixture_root / "root/.ssh"
    (fixture_root / "etc/ssh/sshd_config.d").mkdir(parents=True)
    ssh_dir.mkdir(parents=True)
    root_ssh_dir.mkdir(parents=True)
    stub_dir.mkdir(parents=True)
    state.mkdir()
    calls.touch()
    (state / "target-uid").write_text("1000\n")
    (state / "home").write_text("/home/gib\n")
    (state / "target-dir-meta").write_text("1000:700\n")
    (state / "target-key-meta").write_text("1000:600\n")
    (state / "root-key-meta").write_text("0:600\n")
    (state / "SSHD_RESULTS").write_text("".join(f"{result}\n" for result in sshd_results))
    (state / "RELOAD_RESULTS").write_text("".join(f"{result}\n" for result in reload_results))
    (state / "SSHD_UNIT").write_text("present\n" if sshd_unit else "absent\n")
    (state / "SSH_UNIT").write_text("present\n" if ssh_unit else "absent\n")
    (fixture_root / "stub-install").write_text(
        "#!/usr/bin/env bash\nprintf 'install-handoff %s\\n' \"${PANAMA_PATH:-unset}\" >> \"$PANAMA_BOOT_FIXTURE_ROOT/calls\"\n"
    )
    (fixture_root / "stub-install").chmod(0o755)
    make_stubs(stub_dir, fixture_root, calls)

    if prior_dropin is not None:
        dropin = fixture_root / "etc/ssh/sshd_config.d/90-panama.conf"
        dropin.write_bytes(prior_dropin)
        dropin.chmod(0o600)

    target_keys = ssh_dir / "authorized_keys"
    root_keys = root_ssh_dir / "authorized_keys"
    if name == "missing":
        pass
    elif name == "empty":
        target_keys.touch()
    elif name == "comment-only":
        target_keys.write_text("# no usable key\n\n")
    elif name == "ssh-directory-symlink":
        shutil.rmtree(ssh_dir)
        alternate = fixture_root / "unsafe-ssh"
        alternate.mkdir()
        (fixture_root / "home/gib/.ssh").symlink_to(alternate)
    elif name == "authorized-keys-symlink":
        alternate = fixture_root / "unsafe-authorized-keys"
        alternate.write_text("ssh-ed25519 unsafe\n")
        target_keys.symlink_to(alternate)
    elif name == "directory-wrong-mode":
        target_keys.write_text("ssh-ed25519 target\n")
        (state / "target-dir-meta").write_text("1000:755\n")
    elif name == "root-copy-directory-wrong-mode":
        root_keys.write_text("ssh-ed25519 root\n")
        (state / "target-dir-meta").write_text("1000:755\n")
    elif name == "file-wrong-mode":
        target_keys.write_text("ssh-ed25519 target\n")
        (state / "target-key-meta").write_text("1000:644\n")
    elif name == "directory-wrong-owner":
        target_keys.write_text("ssh-ed25519 target\n")
        (state / "target-dir-meta").write_text("0:700\n")
    elif name == "file-wrong-owner":
        target_keys.write_text("ssh-ed25519 target\n")
        (state / "target-key-meta").write_text("0:600\n")
    elif name == "root-target-account":
        target_keys.write_text("ssh-ed25519 target\n")
        (state / "target-uid").write_text("0\n")
    elif name == "relative-home":
        target_keys.write_text("ssh-ed25519 target\n")
        (state / "home").write_text("home/gib\n")
    elif name in (
        "safe-existing-key",
        "success-without-prior-dropin",
        "success-replaces-prior-dropin",
        "candidate-invalid",
        "candidate-reload-fails",
        "rollback-validation-fails",
        "rollback-reload-fails",
    ):
        target_keys.write_text("ssh-ed25519 target\n")
    elif name == "safe-root-key-copy":
        root_keys.write_text("ssh-ed25519 root\n")
    else:
        raise ValueError(name)
    return fixture_root, stub_dir


def run_case(name: str, **configuration: object) -> tuple[int, str, str, Path]:
    fixture_root, stub_dir = configure_case(name, **configuration)
    master, slave = pty.openpty()

    def attach_terminal() -> None:
        fcntl.ioctl(0, termios.TIOCSCTTY, 0)

    env = {
        **os.environ,
        "PATH": f"{stub_dir}:/usr/bin:/bin",
        "PANAMA_BOOT_FIXTURE_ROOT": str(fixture_root),
        "PANAMA_PATH": f"{fixture_root}/home/gib/.local/share/Panama",
        "HOME": f"{fixture_root}/root",
    }
    process = subprocess.Popen(
        ["bash", boot, "--server"],
        stdin=slave,
        stdout=slave,
        stderr=slave,
        env=env,
        start_new_session=True,
        preexec_fn=attach_terminal,
    )
    os.close(slave)
    os.write(master, b"gib\nY\n")
    chunks: list[bytes] = []
    while True:
        try:
            chunk = os.read(master, 4096)
        except OSError as error:
            if error.errno == errno.EIO:
                break
            raise
        if not chunk:
            break
        chunks.append(chunk)
    os.close(master)
    status = process.wait()
    calls = (fixture_root / "calls").read_text()
    output = b"".join(chunks).decode(errors="replace")
    return status, output, calls, fixture_root


unsafe_cases = (
    "missing",
    "empty",
    "comment-only",
    "ssh-directory-symlink",
    "authorized-keys-symlink",
    "directory-wrong-mode",
    "root-copy-directory-wrong-mode",
    "file-wrong-mode",
    "directory-wrong-owner",
    "file-wrong-owner",
    "root-target-account",
    "relative-home",
)
for case in unsafe_cases:
    status, output, calls, fixture_root = run_case(case)
    if status != 0:
        note(f"{case}: bootstrap stopped with status {status}: {output.strip()}")
    if "SSH hardening unavailable" not in output:
        note(f"{case}: unsafe login path did not explain why hardening was unavailable")
    if "sshd -t" in calls:
        note(f"{case}: unsafe login path validated sshd")
    if "systemctl reload" in calls:
        note(f"{case}: unsafe login path reloaded SSH")
    if (fixture_root / "etc/ssh/sshd_config.d/90-panama.conf").exists():
        note(f"{case}: unsafe login path changed the SSH drop-in")
    if case == "root-copy-directory-wrong-mode" and (
        fixture_root / "home/gib/.ssh/authorized_keys"
    ).exists():
        note("root-copy-directory-wrong-mode: copied a root key into an unsafe SSH directory")
    if "install-handoff " not in calls:
        note(f"{case}: unsafe login path did not hand off to install")

for case in ("safe-existing-key", "safe-root-key-copy"):
    status, output, calls, fixture_root = run_case(case)
    if status != 0:
        note(f"{case}: safe login path stopped with status {status}: {output.strip()}")
    if "SSH hardening unavailable" in output:
        note(f"{case}: safe login path was rejected")
    if "systemctl reload" not in calls:
        note(f"{case}: safe login path did not reach SSH hardening")
    if "install-handoff " not in calls:
        note(f"{case}: safe login path did not hand off to install")
    dropin = fixture_root / "etc/ssh/sshd_config.d/90-panama.conf"
    if (dropin.read_text() if dropin.exists() else "") != "PermitRootLogin no\nPasswordAuthentication no\n":
        note(f"{case}: safe login path did not write the expected SSH drop-in")
    if case == "safe-root-key-copy":
        keys = fixture_root / "home/gib/.ssh/authorized_keys"
        if not keys.exists() or keys.read_text() != "ssh-ed25519 root\n":
            note("safe-root-key-copy: root key was not copied to the target account")

desired_dropin = b"PermitRootLogin no\nPasswordAuthentication no\n"
prior_dropin = b"# prior Panama settings\nPasswordAuthentication yes\n"
transaction_cases = {
    "success-without-prior-dropin": {
        "sshd_results": (0,),
        "reload_results": (0,),
        "prior_dropin": None,
        "sshd_unit": True,
        "ssh_unit": True,
        "succeeds": True,
    },
    "success-replaces-prior-dropin": {
        "sshd_results": (0,),
        "reload_results": (0,),
        "prior_dropin": prior_dropin,
        "sshd_unit": False,
        "ssh_unit": True,
        "succeeds": True,
    },
    "candidate-invalid": {
        "sshd_results": (1, 0),
        "reload_results": (),
        "prior_dropin": prior_dropin,
        "sshd_unit": True,
        "ssh_unit": True,
        "succeeds": False,
    },
    "candidate-reload-fails": {
        "sshd_results": (0, 0),
        "reload_results": (1, 0),
        "prior_dropin": prior_dropin,
        "sshd_unit": True,
        "ssh_unit": True,
        "succeeds": False,
    },
    "rollback-validation-fails": {
        "sshd_results": (0, 1),
        "reload_results": (1,),
        "prior_dropin": prior_dropin,
        "sshd_unit": True,
        "ssh_unit": True,
        "succeeds": False,
        "rollback_fails": True,
    },
    "rollback-reload-fails": {
        "sshd_results": (0, 0),
        "reload_results": (1, 1),
        "prior_dropin": prior_dropin,
        "sshd_unit": True,
        "ssh_unit": True,
        "succeeds": False,
        "rollback_fails": True,
    },
}

for case, expected in transaction_cases.items():
    configuration = {
        key: value
        for key, value in expected.items()
        if key not in {"succeeds", "rollback_fails"}
    }
    status, output, calls, fixture_root = run_case(case, **configuration)
    call_lines = calls.splitlines()
    dropin = fixture_root / "etc/ssh/sshd_config.d/90-panama.conf"
    sshd_dir = dropin.parent
    validations = [index for index, line in enumerate(call_lines) if line.startswith("sshd -t ")]
    reloads = [
        index
        for index, line in enumerate(call_lines)
        if line.startswith("systemctl reload ")
    ]
    activation_lines = [
        (index, line)
        for index, line in enumerate(call_lines)
        if re.fullmatch(
            rf"mv -f -- {re.escape(str(sshd_dir))}/\.90-panama\.[A-Za-z0-9]+\.tmp "
            rf"{re.escape(str(dropin))} source-mode=600 ",
            line,
        )
    ]
    restore_lines = [
        index
        for index, line in enumerate(call_lines)
        if re.fullmatch(
            rf"mv -f -- {re.escape(str(sshd_dir))}/\.90-panama\.[A-Za-z0-9]+\.restore "
            rf"{re.escape(str(dropin))} source-mode=600 ",
            line,
        )
    ]

    succeeds = bool(expected["succeeds"])
    if succeeds and status != 0:
        note(f"{case}: transaction stopped with status {status}: {output.strip()}")
    if not succeeds and status == 0:
        note(f"{case}: failed transaction returned success")
    if succeeds and "install-handoff " not in calls:
        note(f"{case}: successful transaction did not hand off to install")
    if not succeeds and "install-handoff " in calls:
        note(f"{case}: failed transaction handed off to install")

    wanted_contents = desired_dropin if succeeds else prior_dropin
    actual_contents = dropin.read_bytes() if dropin.exists() else None
    if actual_contents != wanted_contents:
        note(f"{case}: SSH drop-in contents were not {'activated' if succeeds else 'restored'}")

    if len(activation_lines) != 1:
        note(f"{case}: candidate was not activated once through a restrictive same-directory rename")
    if succeeds:
        if len(validations) != 1 or len(reloads) != 1:
            note(f"{case}: success did not validate once and reload once")
        elif activation_lines and not activation_lines[0][0] < validations[0] < reloads[0]:
            note(f"{case}: success did not activate, validate, then reload")
    elif case == "candidate-invalid":
        if len(validations) != 2 or reloads:
            note(f"{case}: invalid candidate did not validate candidate and restoration without reload")
        elif activation_lines and restore_lines and not (
            activation_lines[0][0] < validations[0] < restore_lines[0] < validations[1]
        ):
            note(f"{case}: rollback command order was wrong")
    else:
        if len(validations) != 2 or len(reloads) != 2:
            note(f"{case}: reload failure did not validate and reload the restored configuration")
        elif activation_lines and restore_lines and not (
            activation_lines[0][0]
            < validations[0]
            < reloads[0]
            < restore_lines[0]
            < validations[1]
            < reloads[1]
        ):
            note(f"{case}: rollback command order was wrong")

    if succeeds and restore_lines:
        note(f"{case}: successful transaction performed a rollback")
    if not succeeds and len(restore_lines) != 1:
        note(f"{case}: prior drop-in was not restored exactly once")

    detected_unit = "ssh.service" if case == "success-replaces-prior-dropin" else "sshd.service"
    other_unit = "sshd.service" if detected_unit == "ssh.service" else "ssh.service"
    reload_lines = [call_lines[index] for index in reloads]
    if reload_lines and any(line != f"systemctl reload {detected_unit} " for line in reload_lines):
        note(f"{case}: reloaded a unit other than detected {detected_unit}")
    if any(line == f"systemctl reload {other_unit} " for line in call_lines):
        note(f"{case}: guessed {other_unit} after reload failure")
    if detected_unit == "sshd.service":
        if "systemctl cat sshd.service " not in call_lines:
            note(f"{case}: did not detect sshd.service")
        if "systemctl cat ssh.service " in call_lines:
            note(f"{case}: probed ssh.service after finding sshd.service")
    elif not (
        "systemctl cat sshd.service " in call_lines
        and "systemctl cat ssh.service " in call_lines
        and call_lines.index("systemctl cat sshd.service ")
        < call_lines.index("systemctl cat ssh.service ")
    ):
        note(f"{case}: did not fall back from absent sshd.service to ssh.service")

    artifacts = list(sshd_dir.glob(".90-panama.*"))
    rollback_fails = bool(expected.get("rollback_fails", False))
    if not rollback_fails and artifacts:
        note(f"{case}: successful or cleanly rolled-back transaction left temporary artifacts")
    if rollback_fails:
        backups = [artifact for artifact in artifacts if artifact.name.endswith(".backup")]
        if len(backups) != 1:
            note(f"{case}: rollback failure did not retain exactly one backup")
        else:
            backup = backups[0]
            if backup.parent != sshd_dir or backup.read_bytes() != prior_dropin:
                note(f"{case}: retained backup was not a same-directory byte copy")
            if backup.stat().st_mode & 0o777 != 0o600:
                note(f"{case}: retained backup permissions were not restrictive")
            if str(backup.resolve()) not in output:
                note(f"{case}: recovery output omitted the absolute backup path")
        if "sshd -t" not in output or f"systemctl reload {detected_unit}" not in output:
            note(f"{case}: recovery output omitted validation or reload commands")

    artifact_logs = [line for line in call_lines if line.startswith("ssh-artifact ")]
    if expected["prior_dropin"] is not None and not any(
        re.fullmatch(
            rf"ssh-artifact {re.escape(str(sshd_dir))}/\.90-panama\.[A-Za-z0-9]+\.backup 600 ",
            line,
        )
        for line in artifact_logs
    ):
        note(f"{case}: backup was not collision-safe, same-directory, non-.conf, and restrictive")

if findings:
    print(f"root server bootstrap: {len(findings)} finding(s)", file=sys.stderr)
    for finding in findings:
        print(f"  - {finding}", file=sys.stderr)
    raise SystemExit(1)

print("root server bootstrap: PASS")
PY
