#!/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 ####################################### # IPv4 validation. # Globals: # None # Arguments: # 1: IPv4 to validate. # Returns: # ERR_INVALID_IPV4 ####################################### validation_ipv4() { declare var_ip="$1" ### Single-pass check: 4 octets, each 0-255, no leading zeros (unless the octet is exactly "0") if [[ "${var_ip}" =~ ^((25[0-5]|2[0-4][0-9]|1?[0-9]{1,2})\.){3}(25[0-5]|2[0-4][0-9]|1?[0-9]{1,2})$ ]]; then do_log "info" "file_only" "'${var_ip}' seems to be a valid IPv4." else return "${ERR_INVALID_IPV4}" fi } ### Prevents accidental 'unset -f'. # shellcheck disable=SC2034 readonly -f validation_ipv4 ####################################### # IPv6 validation, including # - Standard IPv6 notation with eight groups such as 2001:0db8:85a3:0000:0000:8a2e:0370:7334 # - Shortened notation with :: like 2001:db8::1 # - Addresses with embedded IPv4 addresses like ::ffff:192.0.2.128 # - Link-local addresses like fe80::1%eth0 # Globals: # None # Arguments: # 1: IPv6 address # Returns: # ERR_INVALID_IPV6 ####################################### validation_ipv6() { ### Original input (may include %zone). declare var_ip="$1" ### Strip optional zone id, e.g. fe80::1%eth0 -> fe80::1 declare var_addr="${var_ip%%\%*}" declare var_has_double_colon=0 ### Step 1 - IPv4-mapped / -embedded addresses (::ffff:192.0.2.1) if [[ "${var_addr}" == *.* ]]; then declare var_ipv4_part="${var_addr##*:}" validation_ipv4 "${var_ipv4_part}" || return "${ERR_INVALID_IPV6}" ### Replace IPv4 part by a placeholder, so we can count hextets later var_addr="${var_addr%:*}:0:0" fi ### Step 2 - Detect forbidden multiple '::' if [[ "${var_addr}" == *::* ]]; then var_has_double_colon=1 ### Remove first '::' and check there is no second one. [[ ${var_addr#*::*} == *::* ]] && return "${ERR_INVALID_IPV6}" fi ### Step 3 - Split into hextets and validate format. declare var_hextet declare -a var_segments IFS=':' read -ra var_segments <<< "${var_addr}" declare seg_count=${#var_segments[@]} for var_hextet in "${var_segments[@]}"; do ### Empty part of '::' compression [[ -z "${var_hextet}" ]] && continue [[ "${var_hextet}" =~ ^[0-9a-fA-F]{1,4}$ ]] || return "${ERR_INVALID_IPV6}" done ### Step 4 - Check total hextet count. if (( var_has_double_colon )); then (( seg_count <= 8 )) || return "${ERR_INVALID_IPV6}" else (( seg_count == 8 )) || return "${ERR_INVALID_IPV6}" fi ### Success do_log "info" "file_only" "'${var_ip}' seems to be a valid IPv6." } ### Prevents accidental 'unset -f'. # shellcheck disable=SC2034 readonly -f validation_ipv6 ####################################### # Port validation. # Globals: # None # Arguments: # 1: Port number # Returns: # ERR_INVALID_PORT ####################################### validation_port() { declare var_port="$1" if [[ "${var_port}" =~ ^[0-9]+$ ]] && (( var_port >= 1 && var_port <= 65535 )); then do_log "info" "file_only" "'${var_port}' seems to be a valid port." else do_log "error" "file_only" "'${var_port}' seems to be NOT a valid port." return "${ERR_INVALID_PORT}" fi } ### Prevents accidental 'unset -f'. # shellcheck disable=SC2034 readonly -f validation_port # vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=sh