#!/bin/bash
# SPDX-Version: 3.0
# SPDX-CreationInfo: 2025-06-17; WEIDNER, Marc S.; <msw@coresecret.dev>
# SPDX-ExternalRef: GIT https://git.coresecret.dev/msw/CISS.debian.installer.git
# SPDX-FileContributor: WEIDNER, Marc S.; Centurion Intelligence Consulting Agency
# SPDX-FileCopyrightText: 2024-2025; WEIDNER, Marc S.; <msw@coresecret.dev>
# SPDX-FileType: SOURCE
# SPDX-License-Identifier: EUPL-1.2 OR LicenseRef-CCLA-1.0
# SPDX-LicenseComment: This file is part of the CISS.debian.installer.secure framework.
# SPDX-PackageName: CISS.debian.installer
# SPDX-Security-Contact: security@coresecret.eu

guard_sourcing

#######################################
# Set up Dropbear Initramfs Environment.
# Globals:
#   TARGET
#   VAR_FINAL_FQDN
#   VAR_FINAL_IPV4
#   VAR_FINAL_IPV4_GW
#   VAR_FINAL_IPV4_SUBNET
#   VAR_FINAL_NIC
#   VAR_SETUP_PATH
#   dropbear_dhcp
#   dropbear_firewall
#   dropbear_port
#   network_static_ipv4nameserver_0
#   network_static_ipv4nameserver_1
#   ssh_allow_ipv4_0
#   user_root_sshpubkey
# Arguments:
#   None
# Returns:
#   0: on success
#######################################
dropbear_setup() {
  ### Declare Arrays, HashMaps, and Variables.
  declare     network_static_ipv4ntpserver_0="192.53.103.108"

  ### Prepare strong dropbear host keys
  rm -f "${TARGET}"/etc/dropbear/initramfs/dropbear*key

  do_in_target "${TARGET}" /usr/bin/dropbearkey -t rsa -s 4096 -f /etc/dropbear/initramfs/dropbear_rsa_host_key
  do_in_target "${TARGET}" /usr/bin/dropbearkey -t ed25519 -f /etc/dropbear/initramfs/dropbear_ed25519_host_key

  chmod 0600 "${TARGET}"/etc/dropbear/initramfs/dropbear*key
  chown root:root "${TARGET}"/etc/dropbear/initramfs/dropbear*key

  ### Prepare dropbear authorized_keys
  touch "${TARGET}/etc/dropbear/initramfs/authorized_keys" && chmod 0600 "${TARGET}/etc/dropbear/initramfs/authorized_keys"
  printf "%s\n" "${user_root_sshpubkey}" >> "${TARGET}/etc/dropbear/initramfs/authorized_keys"
  install -m 0755 -o root -g root "${VAR_SETUP_PATH}/includes/target/etc/banner" "${TARGET}/etc/dropbear/initramfs/"

  ### Check for initramfs "IP"-variable: static or dynamic configuration vai dhcp.
  if [[ "${dropbear_dhcp}" = "false" ]]; then

    ### "IP=<HOST IP>::<GATEWAY IP>:<SUBNET MASK>:<FQDN>:<NIC>:none:<DNS 0 IP>:<DNS 1 IP>:<NTP IP>"
    printf "IP=%s::%s:%s:%s:%s:none:%s:%s:%s\n" \
      "${VAR_FINAL_IPV4}" \
      "${VAR_FINAL_IPV4_GW}" \
      "${VAR_FINAL_IPV4_SUBNET}" \
      "${VAR_FINAL_FQDN}" \
      "${VAR_FINAL_NIC}" \
      "${network_static_ipv4nameserver_0:-135.181.207.105}" \
      "${network_static_ipv4nameserver_1:-89.58.62.53}" \
      "${network_static_ipv4ntpserver_0:-192.53.103.104}" \
      >| "${TARGET}/etc/initramfs-tools/conf.d/ip"

  else

    ### "IP=:::::<NIC>:dhcp"
    printf "IP=:::::%s:dhcp\n" "${VAR_FINAL_NIC}" >| "${TARGET}/etc/initramfs-tools/conf.d/ip"

  fi

  ### Generate dropbear configuration file
  write_dropbear_conf

  ### Install the script to be called by 'update-initramfs' for updating 'PATH'-variable inside initramfs.
  install -D -m 0755 -o root -g root "${VAR_SETUP_PATH}/includes/target/etc/initramfs-tools/scripts/init-top/fixpath.sh" \
    "${TARGET}/etc/initramfs-tools/scripts/init-top/"

  ### Install the script to be called by 'update-initramfs' for customizing dropbear inside initramfs.
  install -D -m 0755 -o root -g root "${VAR_SETUP_PATH}/includes/target/etc/initramfs-tools/hooks/custom-initramfs.sh" \
    "${TARGET}/etc/initramfs-tools/hooks/"

  ### Install the script to be called by 'update-initramfs' for customizing prompt inside initramfs environment.
  install -D -m 0755 -o root -g root "${VAR_SETUP_PATH}/includes/target/etc/initramfs-tools/hooks/custom-prompt.sh" \
    "${TARGET}/etc/initramfs-tools/hooks/"

  ### Install the script to be called inside initramfs environment for unlocking LUKS and NUKE Devices.
  install -D -m 0755 -o root -g root "${VAR_SETUP_PATH}/includes/target/etc/initramfs-tools/files/unlock_wrapper.sh" \
    "${TARGET}/etc/initramfs-tools/files/"

  ### Install the script to be called inside the Host environment for signing 'unlock_wrapper.sh'-script.
  install -D -m 0700 -o root -g root "${VAR_SETUP_PATH}/includes/target/etc/initramfs-tools/files/unlock_wrapper_signer.sh" \
    "${TARGET}/etc/initramfs-tools/files/"

  ### Install the script to be called inside the initramfs environment for preparing dropbear execution.
  do_in_target "${TARGET}" mv /usr/share/initramfs-tools/scripts/init-premount/dropbear /usr/share/initramfs-tools/scripts/init-premount/dropbear.2022.83
  install -D -m 0755 -o root -g root "${VAR_SETUP_PATH}/includes/target/usr/share/initramfs-tools/scripts/init-premount/dropbear" \
    "${TARGET}/usr/share/initramfs-tools/scripts/init-premount/"

  ### Install the variable file to be called inside the initramfs environment for setting up dropbear firewall.
  install -D -m 0600 -o root -g root "${VAR_SETUP_PATH}/includes/target/etc/initramfs-tools/files/dropbear_fw.cnf" \
    "${TARGET}/etc/initramfs-tools/files/dropbear_fw.conf"

  ### Install the firewall script to be called inside initramfs environment for setting up dropbear firewall.
  install -D -m 0755 -o root -g root "${VAR_SETUP_PATH}/includes/target/etc/initramfs-tools/files/dropbear_fw.sh" \
    "${TARGET}/etc/initramfs-tools/files/"

  if [[ "${dropbear_firewall,,}" == "true" && -n "${ssh_allow_ipv4_0}" ]]; then

    sed -i 's/^DROPBEAR_FIREWALL_ENABLED=0$/DROPBEAR_FIREWALL_ENABLED=1/' "${TARGET}/etc/initramfs-tools/files/dropbear_fw.cnf"
    sed -i '/^# vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=sh$/d' "${TARGET}/etc/initramfs-tools/files/dropbear_fw.cnf"

    cat << EOF >> "${TARGET}/includes/initramfs-tools/files/dropbear_fw.cnf"
DROPBEAR_PORT=${dropbear_port}
DROPBEAR_JUMP_SERVER_IP=${ssh_allow_ipv4_0}

# vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=sh
EOF

  fi

  guard_dir && return 0
}

#######################################
# Write '/etc/dropbear/initramfs/dropbear.conf'.
# Globals:
#   TARGET
#   ssh_port
# Arguments:
#   None
# Returns:
#   0: on success
#######################################
write_dropbear_conf() {
  [[ -z "${dropbear_port:-}" ]] && dropbear_port="2222"

  cat << EOF >| "${TARGET}/etc/dropbear/initramfs/dropbear.conf"
# SPDX-Version: 3.0
# SPDX-CreationInfo: 2025-06-17; WEIDNER, Marc S.; <msw@coresecret.dev>
# SPDX-ExternalRef: GIT https://git.coresecret.dev/msw/CISS.debian.installer.git
# SPDX-FileContributor: WEIDNER, Marc S.; Centurion Intelligence Consulting Agency
# SPDX-FileCopyrightText: 2024-2025; WEIDNER, Marc S.; <msw@coresecret.dev>
# SPDX-FileType: SOURCE
# SPDX-License-Identifier: EUPL-1.2 OR LicenseRef-CCLA-1.0
# SPDX-LicenseComment: This file is part of the CISS.debian.installer.secure framework.
# SPDX-PackageName: CISS.debian.installer
# SPDX-Security-Contact: security@coresecret.eu

# Static file system information: /etc/dropbear/dropbear.conf
# Generated by CISS.debian.installer ${VAR_VERSION}
# Architecture: ${VAR_ARCHITECTURE}
# Distribution: ${VAR_CODENAME}

# Configuration options for the dropbear-initramfs boot scripts.
# Variable assignment follow shell semantics and escaping/quoting rules.
# You must run update-initramfs(8) to effect changes to this file (like
# for other files in the '/etc/dropbear/initramfs' directory).

# Command line options to pass to dropbear(8).
# Dropbear options for 2025+:
# -b: Display the contents of bannerfile before user login
# -E: Log to stderr
# -I: Idle timeout in seconds
# -K: Keepalive interval in seconds
# -p: Specify port (and optionally address)
# -w: Disable root login (SHOULD NOT be implemented for initramfs)
DROPBEAR_OPTIONS="-b /etc/dropbear/banner -c /usr/local/bin/unlock_wrapper.sh -E -I 300 -K 60 -p ${dropbear_port}"

# On local (non-NFS) mounts, interfaces matching this pattern are
# brought down before exiting the ramdisk to avoid dirty network
# configuration in the normal kernel.
# The special value 'none' keeps all interfaces up and preserves routing
# tables and addresses.
#IFDOWN="*"

# On local (non-NFS) mounts, the network stack and dropbear are started
# asynchronously at init-premount stage.  This value specifies the
# maximum number of seconds to wait (while the network/dropbear are
# being configured) at init-bottom stage before terminating dropbear and
# bringing the network down.
# If the timeout is too short, and if the boot process is not blocking
# on user input supplied via SSHd (ie no remote unlocking), then the
# initrd might pivot to init(1) too early, thereby causing a race
# condition between network configuration from initramfs vs from the
# normal system.
#DROPBEAR_SHUTDOWN_TIMEOUT=60

# vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=sh
EOF

  do_log "info" "file_only" "4312() Written: '${TARGET}/etc/dropbear/initramfs/dropbear.conf'."
  return 0
}
# vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=sh
