Files
CISS.debian.live.builder/lib/lib_arg_parser.sh
2025-05-30 00:28:39 +02:00

387 lines
14 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
# SPDX-Version: 3.0
# SPDX-CreationInfo: 2025-05-05; WEIDNER, Marc S.; <msw@coresecret.dev>
# SPDX-ExternalRef: GIT https://git.coresecret.dev/msw/CISS.debian.live.builder.git
# SPDX-FileContributor: WEIDNER, Marc S.; Centurion Intelligence Consulting Agency
# SPDX-FileCopyrightText: 20242025; 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.live.builder
# SPDX-Security-Contact: security@coresecret.eu
#######################################
# Argument Parser
# Globals:
# BUILD_LOG
# DEBUG
# EARLY_DEBUG
# ERR_CONTROL_CT
# ERR_MISS_PWD_F
# ERR_MISS_PWD_P
# ERR_OWNS_PWD_F
# ERR_PASS_LENGH
# ERR_PASS_PLICY
# ERR_REIONICE_P
# ERR_REIO_C_VAL
# ERR_REIO_P_VAL
# ERR_RENICE_PRI
# ERR_RGHT_PWD_F
# ERR_SPLASH_PNG
# ERR_UNCRITICAL
# ERR__SSH__PORT
# HANDLER_ARCHITECTURE
# HANDLER_BUILD_DIR
# HANDLER_CDI
# HANDLER_DHCP
# HANDLER_ISO_COUNTER
# HANDLER_PRIORITY
# HANDLER_SPLASH
# HANDLER_SSHPORT
# HANDLER_SSHPUBKEY
# HANDLER_STA
# HASHED_PWD
# ISO8601
# REIONICE_CLASS
# REIONICE_PRIORITY
# VERSION
# handler_jumphost
# Arguments:
# None
#######################################
arg_parser() {
while [[ $# -gt 0 ]]; do
declare argument="${1}"
case "${argument,,}" in
-c | --contact)
if [[ -n "${2}" && "${2}" != -* ]]; then
boot_screen_cleaner
printf "\e[91m❌ Error: --contact MUST NOT be followed by an argument.\e[0m\n" >&2
read -p -r $'\e[92m✅ Press \'ENTER\' to exit the script ... \e[0m'
exit "${ERR_ARG_MSMTCH}"
fi
shift 1
;;
-h | --help)
if [[ -n "${2}" && "${2}" != -* ]]; then
boot_screen_cleaner
printf "\e[91m❌ Error: --help MUST NOT be followed by an argument.\e[0m\n" >&2
read -p -r $'\e[92m✅ Press \'ENTER\' to exit the script ... \e[0m'
exit "${ERR_ARG_MSMTCH}"
fi
shift 1
;;
-v | --version)
if [[ -n "${2}" && "${2}" != -* ]]; then
boot_screen_cleaner
printf "\e[91m❌ Error: --version MUST NOT be followed by an argument.\e[0m\n" >&2
read -p -r $'\e[92m✅ Press \'ENTER\' to exit the script ... \e[0m'
exit "${ERR_ARG_MSMTCH}"
fi
shift 1
;;
--architecture)
if [[ "${2}" == "amd64" || "${2}" == "arm64" ]]; then
declare -gx HANDLER_ARCHITECTURE="$2"
shift 2
else
boot_screen_cleaner
printf "\e[91m❌ Error: --architecture MUST be 'amd64' or 'arm64'.\e[0m\n" >&2
# shellcheck disable=SC2162
read -p $'\e[92m✅ Press \'ENTER\' to exit the script ... \e[0m'
exit "${ERR_UNCRITICAL}"
fi
;;
--build-directory)
declare -gx HANDLER_BUILD_DIR="${2}"
declare -gx BUILD_LOG="${HANDLER_BUILD_DIR}/${ISO8601}_build.log"
shift 2
;;
--cdi)
if [[ -n "${2}" && "${2}" != -* ]]; then
boot_screen_cleaner
printf "\e[91m❌ Error: --cdi MUST NOT be followed by an argument.\e[0m\n" >&2
read -p -r $'\e[92m✅ Press \'ENTER\' to exit the script ... \e[0m'
exit "${ERR_ARG_MSMTCH}"
fi
declare -g HANDLER_CDI=true
shift 1
;;
--change-splash )
if [[ "${2}" == "club" || "${2}" == "hexagon" ]]; then
declare -g HANDLER_SPLASH="${2}"
shift 2
else
boot_screen_cleaner
printf "\e[91m❌ Error: --change-splash MUST be 'club' or 'hexagon'.\e[0m\n" >&2
# shellcheck disable=SC2162
read -p $'\e[92m✅ Press \'ENTER\' to exit the script ... \e[0m'
exit "${ERR_SPLASH_PNG}"
fi
;;
--control)
if [[ -n "${2}" && "${2}" =~ ^-?[0-9]+$ && "${2}" -ge 1 && "${2}" -le 65536 ]]; then
declare -gi HANDLER_ISO_COUNTER="$2"
shift 2
else
boot_screen_cleaner
printf "\e[91m❌ Error: --control MUST be an integer between '1' and '65535'.\e[0m\n" >&2
# shellcheck disable=SC2162
read -p $'\e[92m✅ Press \'ENTER\' to exit the script ... \e[0m'
exit "${ERR_CONTROL_CT}"
fi
;;
--debug)
if [[ -n "${2}" && "${2}" != -* ]]; then
boot_screen_cleaner
printf "\e[91m❌ Error: --debug MUST NOT be followed by an argument.\e[0m\n" >&2
read -p -r $'\e[92m✅ Press \'ENTER\' to exit the script ... \e[0m'
exit "${ERR_ARG_MSMTCH}"
fi
shift 1
;;
--dhcp-centurion)
if [[ -n "${2}" && "${2}" != -* ]]; then
boot_screen_cleaner
printf "\e[91m❌ Error: --dhcp-centurion MUST NOT be followed by an argument.\e[0m\n" >&2
read -p -r $'\e[92m✅ Press \'ENTER\' to exit the script ... \e[0m'
exit "${ERR_ARG_MSMTCH}"
fi
declare -gi HANDLER_DHCP=1
shift 1
;;
--jump-host)
if [[ -n "${2}" && "${2}" != -* ]]; then
declare -i count=0
shift
while [[ "${#}" -gt 0 && "${1}" != -* && count -lt 10 ]]; do
declare -g handler_jumphost+=("$1")
count=$((count + 1))
shift
done
while [[ "${#}" -gt 0 && "${1}" != -* ]]; do
shift
done
else
boot_screen_cleaner
printf "\e[91m❌ Error: --jump-host MUST contain one or up to ten IPs.\e[0m\n" >&2
read -p -r $'\e[92m✅ Press \'ENTER\' to exit the script ... \e[0m'
exit "${ERR_ARG_MSMTCH}"
fi
;;
--log-statistics-only)
if [[ -n "${2}" && "${2}" != -* ]]; then
boot_screen_cleaner
printf "\e[91m❌ Error: --log-statistics-only MUST NOT be followed by an argument.\e[0m\n" >&2
read -p -r $'\e[92m✅ Press \'ENTER\' to exit the script ... \e[0m'
exit "${ERR_ARG_MSMTCH}"
fi
declare -gi HANDLER_STA=1
shift 1
;;
--provider-netcup-ipv6)
if [[ -n "${2}" && "${2}" != -* ]]; then
declare -i count=0
declare -g handler_netcup_ipv6=true
shift
while [[ "${#}" -gt 0 && "${1}" != -* && count -lt 1 ]]; do
declare cleaned="${1//[\[\]]/}"
declare -g handler_netcup_ipv6_array+=("${cleaned}")
count=$((count + 1))
shift
done
while [[ "${#}" -gt 0 && "${1}" != -* ]]; do
shift
done
else
boot_screen_cleaner
printf "\e[91m❌ Error: --provider-netcup-ipv6 MUST provide one IPv6.\e[0m\n" >&2
read -p -r $'\e[92m✅ Press \'ENTER\' to exit the script ... \e[0m'
exit "${ERR_ARG_MSMTCH}"
fi
;;
--renice-priority)
if [[ -n ${2} && ${2} =~ ^-?[0-9]+$ && ${2} -ge -19 && ${2} -le 19 ]]; then
declare -gi HANDLER_PRIORITY="$2"
shift 2
else
boot_screen_cleaner
printf "\e[91m❌ Error: --renice-priority MUST an integer between '-19' and '19'.\e[0m\n" >&2
# shellcheck disable=SC2162
read -p $'\e[92m✅ Press \'ENTER\' to exit the script ... \e[0m'
exit "${ERR_RENICE_PRI}"
fi
;;
--reionice-priority)
if [[ -z "${2}" ]]; then
boot_screen_cleaner
printf "\e[91m❌ Error: --reionice-priority no values provided.\e[0m\n" >&2
read -p -r $'\e[92m✅ Press \'ENTER\' to exit the script ... \e[0m'
exit "${ERR_REIONICE_P}"
else
if [[ "${2}" =~ ^[1-3]$ ]]; then
declare -gi REIONICE_CLASS="${2}"
if [[ -z "${3}" ]]; then
:
else
if [[ "${3}" =~ ^[0-7]$ ]]; then
declare -gi REIONICE_PRIORITY="${3}"
else
boot_screen_cleaner
printf "\e[91m❌ Error: --reionice-priority PRIORITY MUST be an integer between '0' and '7'.\e[0m\n" >&2
read -p -r $'\e[92m✅ Press \'ENTER\' to exit the script ... \e[0m'
exit "${ERR_REIO_P_VAL}"
fi
fi
else
boot_screen_cleaner
printf "\e[91m❌ Error: --reionice-priority CLASS MUST be an integer between '1' and '3'.\e[0m\n" >&2
read -p -r $'\e[92m✅ Press \'ENTER\' to exit the script ... \e[0m'
exit "${ERR_REIO_C_VAL}"
fi
fi
if [[ -n ${REIONICE_PRIORITY} ]]; then
shift 3
else
shift 2
fi
;;
--root-password-file)
declare pw_file="${2}"
if [[ -z "${pw_file}" ]]; then
boot_screen_cleaner
printf "\e[91m❌ Error: --root-password-file missing password file path argument.\e[0m\n" >&2
# shellcheck disable=SC2162
read -p $'\e[92m✅ Press \'ENTER\' to exit the script ... \e[0m'
exit "${ERR_MISS_PWD_P}"
fi
if [[ ! -f "${pw_file}" ]]; then
boot_screen_cleaner
printf "\e[91m❌ Error: --root-password-file password file '%s' does not exist.\e[0m\n" "${pw_file}" >&2
# shellcheck disable=SC2162
read -p $'\e[92m✅ Press \'ENTER\' to exit the script ... \e[0m'
exit "${ERR_MISS_PWD_F}"
fi
declare owner
owner=$(stat -c '%U:%G' "${pw_file}")
if [[ "${owner}" != "root:root" ]]; then
chown root:root "${pw_file}" || {
boot_screen_cleaner
printf "\e[91m❌ Error: --root-password-file failed to set owner root:root on '%s'.\e[0m\n" "${pw_file}" >&2
# shellcheck disable=SC2162
read -p $'\e[92m✅ Press \'ENTER\' to exit the script ... \e[0m'
exit "${ERR_OWNS_PWD_F}"
}
fi
declare perms
perms=$(stat -c '%a' "${pw_file}")
if [[ "${perms}" -ne 400 ]]; then
chmod 400 "${pw_file}" || {
boot_screen_cleaner
printf "\e[91m❌ Error: --root-password-file failed to set permissions 0400 on '%s'.\e[0m\n" "${pw_file}" >&2
# shellcheck disable=SC2162
read -p $'\e[92m✅ Press \'ENTER\' to exit the script ... \e[0m'
exit "${ERR_RGHT_PWD_F}"
}
fi
declare plaintext_pw
[[ "${EARLY_DEBUG}" == "true" ]] && set +x # No tracing for security reasons
if ! IFS= read -r plaintext_pw < "${pw_file}"; then
:
fi
[[ "${EARLY_DEBUG}" == "true" ]] && set -x # Turn on tracing again
declare pw_length
pw_length=${#plaintext_pw}
if (( pw_length < 20 || pw_length > 64 )); then
boot_screen_cleaner
printf "\e[91m❌ Error: --root-password-file password MUST be between 20 and 64 characters (got %d).\e[0m\n" "${pw_length}" >&2
# shellcheck disable=SC2162
read -p $'\e[92m✅ Press \'ENTER\' to exit the script ... \e[0m'
exit "${ERR_PASS_LENGH}"
fi
[[ "${EARLY_DEBUG}" == "true" ]] && set +x # No tracing for security reasons
if [[ "${plaintext_pw}" == *\"* ]]; then
[[ "${EARLY_DEBUG}" == "true" ]] && set -x # Turn on tracing again
boot_screen_cleaner
printf "\e[91m❌ Error: --root-password-file password MUST NOT contain double quotes (\").\e[0m\n" >&2
# shellcheck disable=SC2162
read -p $'\e[92m✅ Press \'ENTER\' to exit the script ... \e[0m'
exit "${ERR_PASS_PLICY}"
fi
[[ "${EARLY_DEBUG}" == "true" ]] && set -x # Turn on tracing again
declare salt
set +o pipefail
while :; do
salt=$(tr -dc 'A-Za-z0-9' </dev/random | head -c 16)
[[ ${#salt} -eq 16 ]] && break
done
set -o pipefail
declare hash_temp
[[ "${EARLY_DEBUG}" == "true" ]] && set +x # No tracing for security reasons
hash_temp=$(mkpasswd --method=sha-512 --salt="${salt}" --rounds=8388608 "${plaintext_pw}")
[[ "${EARLY_DEBUG}" == "true" ]] && set -x # Turn on tracing again
declare -g HASHED_PWD="${hash_temp}"
unset hash_temp plaintext_pw
sync
if shred -vfzu -n 5 "${pw_file}" > /dev/null 2>&1; then
printf "\e[92m✅ Password file '%s': shred -vfzu -n 5 >> done. \e[0m\n" "${pw_file}" > /dev/null 2>&1
else
printf "\e[91m❌ Password file '%s': shred -vfzu -n 5 >> NOT successful. \e[0m\n" "${pw_file}" > /dev/null 2>&1
fi
sync
shift 2
;;
--ssh-port)
if [[ -n "${2}" && "${2}" =~ ^-?[0-9]+$ && "${2}" -ge 1 && "${2}" -le 65535 ]]; then
declare -gi HANDLER_SSHPORT="${2}"
shift 2
else
boot_screen_cleaner
printf "\e[91m❌ Error: --ssh-port MUST be an integer between '1' and '65535'.\e[0m\n" >&2
read -p -r $'\e[92m✅ Press \'ENTER\' to exit the script ... \e[0m'
exit "${ERR__SSH__PORT}"
fi
;;
--ssh-pubkey)
declare -g HANDLER_SSHPUBKEY="${2}"
shift 2
;;
*)
boot_screen_cleaner
usage
;;
esac
done
}
# vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=sh