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

root="$XDG_RUNTIME_DIR/hardened"
home="$root/home"
wayland="$XDG_RUNTIME_DIR/$WAYLAND_DISPLAY"
resolver="$root/resolv.conf"

bwrap_bin="$(command -v bwrap)"
emacs_bin="$(readlink -f "$(command -v emacs)")"
profile="$(readlink -f "$HOME/.nix-profile")"

mkdir -p "$home/.emacs.d" "$home/.nix-profile"
chmod 700 "$root" "$home"
printf 'nameserver 1.1.1.1\nnameserver 9.9.9.9\noptions edns0\n' >"$resolver"

HARDENED_ROUTES4="$(ip -4 route show scope link | awk '$1 != "default" && $1 ~ /\// {print $1}')"
HARDENED_ROUTES6="$(ip -6 route show | awk '$1 != "default" && $1 ~ /\// {print $1}')"
export HARDENED_ROUTES4 HARDENED_ROUTES6

emacs_args=()

for arg in "$@"; do
  case "$arg" in
    "$home")
      emacs_args+=("$HOME")
      ;;
    "$home/"*)
      emacs_args+=("$HOME/${arg#"$home/"}")
      ;;
    *)
      emacs_args+=("$arg")
      ;;
  esac
done

exec pasta \
  --config-net \
  --map-host-loopback none \
  --no-map-gw \
  -t none \
  -u none \
  -T none \
  -U none \
  -- \
  /run/current-system/sw/bin/bash -c '
set -euo pipefail
for subnet in 10.0.0.0/8 100.64.0.0/10 169.254.0.0/16 172.16.0.0/12 192.168.0.0/16 224.0.0.0/4 240.0.0.0/4; do
  iptables -A OUTPUT -d "$subnet" -j REJECT
done
while IFS= read -r subnet; do
  if [[ -n "$subnet" ]]; then iptables -A OUTPUT -d "$subnet" -j REJECT; fi
done <<<"$HARDENED_ROUTES4"
for subnet in fc00::/7 fe80::/10 ff00::/8; do
  ip6tables -A OUTPUT -d "$subnet" -j REJECT
done
while IFS= read -r subnet; do
  if [[ -n "$subnet" ]]; then ip6tables -A OUTPUT -d "$subnet" -j REJECT; fi
done <<<"$HARDENED_ROUTES6"
exec "$@"
' hardened-network "$bwrap_bin" \
  --unshare-all \
  --share-net \
  --unshare-user \
  --disable-userns \
  --new-session \
  --cap-drop ALL \
  --clearenv \
  --dir /nix \
  --ro-bind /nix/store /nix/store \
  --ro-bind /etc /etc \
  --ro-bind "$resolver" /etc/resolv.conf \
  --dir /run \
  --ro-bind /run/current-system /run/current-system \
  --dir /run/user \
  --dir "/run/user/$UID" \
  --bind "$wayland" "$wayland" \
  --proc /proc \
  --dev /dev \
  --tmpfs /tmp \
  --dir /home \
  --bind "$home" "$HOME" \
  --dir "$HOME/.emacs.d" \
  --overlay-src "$HOME/.emacs.d" \
  --tmp-overlay "$HOME/.emacs.d" \
  --ro-bind "$profile" "$HOME/.nix-profile" \
  --dir /usr \
  --symlink /run/current-system/sw/bin /bin \
  --symlink /run/current-system/sw/bin /usr/bin \
  --chdir "$HOME" \
  --hostname hardened \
  --setenv HOME "$HOME" \
  --setenv USER "$USER" \
  --setenv LOGNAME "$USER" \
  --setenv PATH "$HOME/.nix-profile/bin:/run/current-system/sw/bin" \
  --setenv SHELL "${SHELL:-/bin/sh}" \
  --setenv LANG "${LANG:-C.UTF-8}" \
  --setenv TERM "${TERM:-xterm-256color}" \
  --setenv XDG_RUNTIME_DIR "/run/user/$UID" \
  --setenv XDG_DATA_DIRS "$HOME/.nix-profile/share:/run/current-system/sw/share" \
  --setenv WAYLAND_DISPLAY "$WAYLAND_DISPLAY" \
  --setenv GDK_BACKEND wayland \
  "$emacs_bin" "${emacs_args[@]}"
