#!/bin/bash # SPDX-Version: 3.0 # SPDX-CreationInfo: 2025-06-17; WEIDNER, Marc S.; # 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.; # 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 ####################################### # Reading and extracting variables from "${PRESEED}". # Globals: # BASH_REMATCH # HMP_RECIPE_DEV_PARTITIONS # VAR_APT_FULL_UPGRADE VAR_ARCHITECTURE # VAR_CHROOT_DEBUG VAR_CODENAME # VAR_DEB822 VAR_DROPBEAR # VAR_GRUB_PASSWORD VAR_LUKS_BACKUP # VAR_LUKS_PGP VAR_LUKS_URL # VAR_NEED_RUN_IN_TARGET VAR_NUKE # VAR_NUKE_ROUNDS VAR_PRESEED # VAR_PROVIDER VAR_RECIPE_FIRMWARE # VAR_RECIPE_HIGHEST_DEVICE VAR_RECIPE_STRING # VAR_RECIPE_TABLE VAR_RECOVERY # VAR_SEC_FW VAR_SSH_CA # VAR_SSH_PORT VAR_UFW_OUT # VAR_USER_ROOT_SPECIFIC # apt_default_deb822 apt_full_upgrade # architecture chroot_debug # distribution dropbear_boot # grub_password needrun # provider security_ext # security_ufw_out ssh_port # ssh_root_ca user_root_specific # Arguments: # None # Returns: # 0: on success # ERR_NO_VALID_RECIPE: on failure ####################################### yaml_reader() { ### Declare Arrays, HashMaps, and Variables. # shellcheck disable=SC2034 declare -Ag HMP_RECIPE_DEV_PARTITIONS=() declare -gx VAR_RECIPE_STRING="" VAR_RECIPE_HIGHEST_DEVICE="" VAR_ARCHITECTURE="" VAR_RECIPE_FIRMWARE="" VAR_NUKE="" \ VAR_RECIPE_TABLE="" VAR_NEED_RUN_IN_TARGET="false" VAR_CODENAME="" VAR_DROPBEAR="" VAR_RECOVERY="" \ VAR_GRUB_PASSWORD="false" VAR_SSH_PORT="22" VAR_DEB822="true" VAR_PROVIDER="" VAR_SSH_CA="" VAR_UFW_OUT="deny" \ VAR_CHROOT_DEBUG="false" VAR_SEC_FW="selinux" VAR_APT_FULL_UPGRADE="true" VAR_LUKS_BACKUP="false" \ VAR_LUKS_URL="" VAR_LUKS_PGP="" VAR_USER_ROOT_SPECIFIC="" ### Declare and substitute input files. declare -r var_if="${VAR_PRESEED}" declare var_line="" var_middle_part="" var_highest_dev="" var_device="" var_fields="" var_partition="" \ recipe_firmware_var="" recipe_nuke_var="" recipe_nuke_rounds_var="" recipe_table_var="" recipe_recovery_var="" \ recipe_luks_var="" recipe_luks_url="" recipe_luks_pgp="" ### Read "${var_if}" line by line. while IFS= read -r var_line; do ### Check if the line matches the search pattern. if [[ "${var_line}" =~ ^recipe_([^_]+)_active=\'true\' ]]; then var_middle_part="${BASH_REMATCH[1]}" VAR_RECIPE_STRING="${var_middle_part,,}" break fi done < "${var_if}" if [[ -n "${VAR_RECIPE_STRING}" ]]; then do_log "info" "file_only" "1251() Found active recipe string: '${VAR_RECIPE_STRING}'." else do_log "fatal" "file_only" "1251() Found NO active recipe string: '${VAR_RECIPE_STRING}'." exit "${ERR_NO_VALID_RECIPE}" fi ### Search "${var_if}" for matching recipe_${VAR_RECIPE_STRING}_dev_* entries and find the highest dev letter. # shellcheck disable=SC2312 var_highest_dev=$(grep -E "^recipe_${VAR_RECIPE_STRING}_dev_" "${var_if}" | awk -F'_' ' { if (NF >= 4) { ### Extract 4th position (e.g., "recipe_${VAR_RECIPE_STRING}_dev_sda" or "recipe_${VAR_RECIPE_STRING}_dev_vda") device_field = $4 ### Check, if field is at least 3 char wide and last char contains a letter if (length(device_field) >= 3) { last_char = substr(device_field, length(device_field), 1) ### Extract last letter of respective field if (last_char ~ /^[a-z]$/ && last_char > max) { max = last_char } } } } END { print max } ') ### Save the result in VAR_RECIPE_HIGHEST_DEVICE. VAR_RECIPE_HIGHEST_DEVICE="${var_highest_dev}" if [[ -n "${VAR_RECIPE_HIGHEST_DEVICE}" ]]; then do_log "info" "file_only" "1251() Found highest recipe device: '${VAR_RECIPE_HIGHEST_DEVICE}'." else do_log "fatal" "file_only" "1251() Found NO highest recipe device: '${VAR_RECIPE_HIGHEST_DEVICE}'." exit "${ERR_NO_VALID_RECIPE}" fi ### Read var_if and iterate through all matching entries without executing in a subshell # shellcheck disable=SC2312 while read -r var_line; do ### Extract fields of line IFS='_' read -ra var_fields <<< "${var_line}" ### Check that enough fields are available if [[ "${#var_fields[@]}" -ge 5 ]]; then var_device="${var_fields[3]}" ### The fourth position includes the device (e.g., sda, vda, xvda) var_partition="${var_fields[4]}" ### The fifth position includes the partition (e.g., 13) ### Check if the partition is a number and higher than the current value if [[ "${var_partition}" =~ ^[0-9]+$ ]]; then declare -i cur="${HMP_RECIPE_DEV_PARTITIONS[${var_device}]:-0}" if (( var_partition > cur )); then #if [[ -z "${HMP_RECIPE_DEV_PARTITIONS[${var_device}]:-}" || "${var_partition}" -gt ${HMP_RECIPE_DEV_PARTITIONS[${var_device}]:-0} ]]; then # shellcheck disable=SC2004 HMP_RECIPE_DEV_PARTITIONS[${var_device}]="${var_partition}" fi fi fi done < <(grep -E "^recipe_${VAR_RECIPE_STRING}_dev_" "${var_if}") for var_device in "${!HMP_RECIPE_DEV_PARTITIONS[@]}"; do do_log "info" "file_only" "1251() Highest number of partitions: [${var_device}:${HMP_RECIPE_DEV_PARTITIONS[${var_device}]}]." done ### Extract APT file format. # shellcheck disable=SC2034 VAR_DEB822="${apt_default_deb822,,}" ### Extract Upgrade Policy. # shellcheck disable=SC2034 VAR_APT_FULL_UPGRADE="${apt_full_upgrade,,}" ### Extract architecture. # shellcheck disable=SC2034 VAR_ARCHITECTURE="${architecture,,}" ### Extract chroot debug policy. # shellcheck disable=SC2034 VAR_CHROOT_DEBUG="${chroot_debug,,}" ### Extract distribution. # shellcheck disable=SC2034 VAR_CODENAME="${distribution,,}" ### Extract dropbear installation. # shellcheck disable=SC2034 VAR_DROPBEAR="${dropbear_boot,,}" ### Extract grub password installation. # shellcheck disable=SC2034 VAR_GRUB_PASSWORD="${grub_password,,}" ### Extract SSH Port. # shellcheck disable=SC2034 VAR_SSH_PORT="${ssh_port,,}" ### Extract SSH Root CA. # shellcheck disable=SC2034 VAR_SSH_CA="${ssh_root_ca,,}" ### Extract chroot secure '/run' mounting strategy. # shellcheck disable=SC2034 VAR_NEED_RUN_IN_TARGET="${needrun,,}" ### Extract chosen firmware. recipe_firmware_var="recipe_${VAR_RECIPE_STRING}_control_firmware" VAR_RECIPE_FIRMWARE="${!recipe_firmware_var,,}" ### Extract the chosen LUKS Backup strategy. recipe_luks_var="recipe_${VAR_RECIPE_STRING}_control_luks_backup" # shellcheck disable=SC2034 VAR_LUKS_BACKUP="${!recipe_luks_var,,}" recipe_luks_pgp="recipe_${VAR_RECIPE_STRING}_control_luks_backup_pgp" # shellcheck disable=SC2034 VAR_LUKS_PGP="${!recipe_luks_pgp,,}" recipe_luks_url="recipe_${VAR_RECIPE_STRING}_control_luks_backup_url" # shellcheck disable=SC2034 VAR_LUKS_URL="${!recipe_luks_url,,}" ### Extract the chosen Nuke mechanism. recipe_nuke_var="recipe_${VAR_RECIPE_STRING}_control_nuke" # shellcheck disable=SC2034 VAR_NUKE="${!recipe_nuke_var,,}" ### Extract the chosen Nuke SHA512 KDF rounds. recipe_nuke_rounds_var="recipe_${VAR_RECIPE_STRING}_control_nuke_rounds" # shellcheck disable=SC2034 VAR_NUKE_ROUNDS="${!recipe_nuke_rounds_var}" ### Extract chosen partition table. recipe_table_var="recipe_${VAR_RECIPE_STRING}_control_table" VAR_RECIPE_TABLE="${!recipe_table_var,,}" if [[ "${VAR_RECIPE_TABLE}" == "gpt" && "${VAR_RECIPE_FIRMWARE}" == "uefi" ]]; then do_log "info" "file_only" "1251() Partition table: '${VAR_RECIPE_TABLE}' and firmware: '${VAR_RECIPE_FIRMWARE}' > ESP 'EF00' necessary." elif [[ "${VAR_RECIPE_TABLE}" == "gpt" && "${VAR_RECIPE_FIRMWARE}" == "bios" ]]; then do_log "info" "file_only" "1251() Partition table: '${VAR_RECIPE_TABLE}' and firmware: '${VAR_RECIPE_FIRMWARE}' > BIOS Boot Partition 'EF02' necessary." elif [[ "${VAR_RECIPE_TABLE}" == "msdos" && "${VAR_RECIPE_FIRMWARE}" == "uefi" ]]; then do_log "warn" "file_only" "1251() Partition table: '${VAR_RECIPE_TABLE}' and firmware: '${VAR_RECIPE_FIRMWARE}' > ESP on MBR needs partition type '0xEF'." elif [[ "${VAR_RECIPE_TABLE}" == "msdos" && "${VAR_RECIPE_FIRMWARE}" == "bios" ]]; then do_log "info" "file_only" "1251() Partition table: '${VAR_RECIPE_TABLE}' and firmware: '${VAR_RECIPE_FIRMWARE}' > No special firmware partition necessary." fi ### Extract provider. # shellcheck disable=SC2034 VAR_PROVIDER="${provider,,}" ### Extract the chosen Recovery mechanism. recipe_recovery_var="recipe_${VAR_RECIPE_STRING}_control_recovery" # shellcheck disable=SC2034 VAR_RECOVERY="${!recipe_recovery_var,,}" ### Extract security extensions. # shellcheck disable=SC2034 VAR_SEC_FW="${security_ext,,}" ### Extract ufw outgoing policy. # shellcheck disable=SC2034 VAR_UFW_OUT="${security_ufw_out,,}" ### Extract User Root Specific Branch. # shellcheck disable=SC2034 VAR_USER_ROOT_SPECIFIC="${user_root_specific,,}" guard_dir && return 0 } ### Prevents accidental 'unset -f'. # shellcheck disable=SC2034 readonly -f yaml_reader # vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=sh