#!/usr/bin/env bash
# Runs AS ROOT. Installs and starts the LAN recovery door: a second ssh listener on
# 2223 that shares no state with the converged sshd on 2222.
#
# debian2 and debian3 were lost because every way in was the same door. sshd on the LAN
# address and sshd on the tailnet address are one daemon, one config tree, one converge;
# a rewrite under /etc/ssh/sshd_config.d that binds fine while the box is up and fails at
# the next cold boot takes all of them at once. This door reads no file under /etc/ssh,
# uses its own host key, and its port is bound by PID 1 through a socket unit, so a
# broken sshd cannot leave 2223 unbound and there is no crash loop to give up on.
#
# Installed and invoked by host-config/apply.sh. Safe to re-run, and safe to run by hand
# from a console on a box whose only remaining way in is that console.
set -euo pipefail
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

DIR=/etc/buildbox-rescue-door
CONF="$DIR/sshd_config"
KEY="$DIR/ssh_host_ed25519_key"
# With no argument it re-arms from the copy it already installed, so a person at a
# console can bring the door back without a checkout of this repo in front of them.
SRC="${1:-$CONF}"

[ "$(id -u)" = 0 ] || { echo "buildbox-rescue-door: must run as root" >&2; exit 2; }
[ -r "$SRC" ] || { echo "buildbox-rescue-door: no such config: $SRC" >&2; exit 2; }

install -d -m 0700 -o root -g root "$DIR"
[ "$SRC" = "$CONF" ] || install -m 0600 -o root -g root "$SRC" "$CONF"

# Its own key, so the door does not depend on anything under /etc/ssh being intact.
# An empty or half-written key is replaced, never reused.
if [ ! -s "$KEY" ]; then
  rm -f "$KEY" "$KEY.pub"
  ssh-keygen -q -t ed25519 -N '' -C "buildbox-rescue-door $(hostname)" -f "$KEY"
fi

# sshd refuses to parse a config without its privilege separation directory, and that
# directory belongs to ssh.service's RuntimeDirectory= — so it is missing in exactly the
# state this door exists for. The per-connection unit recreates it the same way.
install -d -m 0755 -o root -g root /run/sshd
if ! rejected=$(sshd -t -f "$CONF" 2>&1); then
  echo "buildbox-rescue-door: sshd rejected the rescue config — not arming a door that cannot serve" >&2
  printf '%s\n' "$rejected" >&2
  exit 1
fi

systemctl enable --now buildbox-rescue-sshd.socket >/dev/null
bound=$(ss -H -lnt 'sport = :2223' 2>/dev/null | awk '{print $4}' | sed 's/:2223$//; s/^\[//; s/\]$//' | LC_ALL=C sort -u)
want=$(printf '0.0.0.0\n::\n' | LC_ALL=C sort -u)
if [ "$bound" != "$want" ]; then
  echo "buildbox-rescue-door: 2223 bound [$(echo $bound)], want [$(echo $want)]" >&2
  exit 1
fi
echo "RESCUE door 2223 on $(echo $want), key $(ssh-keygen -lf "$KEY.pub" | awk '{print $2}')"
