#!/bin/bash
# SPDX-Version: 3.0
# SPDX-CreationInfo: 2025-10-11; 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: 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.live.builder
# SPDX-Security-Contact: security@coresecret.eu
set -Ceuo pipefail

printf "\e[95m++++ ++++ ++++ ++++ ++++ ++++ ++ 🧪 '%s' starting ... \e[0m\n" "${0}"

declare -a search_dirs=("/etc/ssl/certs" "/usr/local/share/ca-certificates" "/usr/share/ca-certificates" "/etc/letsencrypt")
declare backup_dir="/root/.ciss/cdlb/backup/certificates"
declare current_date
current_date=$(date +%s)
declare -ax expired_certificates=()

#######################################
# Backup Wrapper for all x509 Root CA Certs
# Globals:
#   backup_dir
#   search_dirs
#   dir
# Arguments:
#   None
#######################################
create_backup() {
  printf "\e[95m++++ ++++ ++++ ++++ ++++ ++++ ++ 🧪 Backup Certificate: '%s' ... \e[0m\n" "${backup_dir}"

  mkdir -p "${backup_dir}"
  declare dir=""

  for dir in "${search_dirs[@]}"; do

    if [[ -d "${dir}" ]] && compgen -G "${dir}"/* > /dev/null; then

      cp -r "${dir}"/* "${backup_dir}"

    fi

  done

  printf "\e[92m++++ ++++ ++++ ++++ ++++ ++++ ++ ✅ Backup Certificate: '%s' done.\e[0m\n" "${backup_dir}"
}

#######################################
# Check the validity of each certificate.
# Globals:
#   CERT
#   CERT_DATE
#   CERT_DATE_SECONDS
#   CURRENT_DATE
#   DIR
#   EXPIRED_CERTIFICATES
#   SEARCH_DIRS
# Arguments:
#   None
#######################################
check_certificates() {
  declare dir=""
  declare cert=""
  declare cert_date=""
  declare cert_date_seconds=""

  for dir in "${search_dirs[@]}"; do

    # shellcheck disable=SC2312
    while IFS= read -r -d '' cert; do

      cert_date=$(openssl x509 -in "${cert}" -noout -enddate | sed 's/notAfter=//')
      cert_date_seconds=$(date -d "${cert_date}" +%s)

      if [[ ${cert_date_seconds} -lt ${current_date} ]]; then

        declare -g expired_certificates+=("${cert}")

      fi

    done < <(find "${dir}" -type f \( -name "*.crt" -o -name "*.pem" \) -print0)

  done
}

#######################################
# Find and clean all ca-certificates.crt files in SEARCH_DIRS.
# Globals:
#   CURRENT_DATE
#   SEARCH_DIRS
#   cert
#   line
# Arguments:
#   None
#######################################
delete_expired_from_all_bundles() {
  declare dir bundle

  for dir in "${search_dirs[@]}"; do

    bundle="${dir}/ca-certificates.crt"

    if [[ -f ${bundle} ]]; then

      printf "\e[95m++++ ++++ ++++ ++++ ++++ ++++ ++ 🧪 Checking Root-CA Bundle: '%s' ...\e[0m\n" "${bundle}"
      declare tmp_bundle="${bundle}.tmp"
      declare -a block=()
      declare expired=0
      declare enddate cert_date_seconds

      : > "${tmp_bundle}"

      declare line=""
      while IFS= read -r line; do

        block+=("${line}")

        if [[ ${line} == "-----END CERTIFICATE-----"   ]]; then

          cert=$(printf "%s\n" "${block[@]}")
          enddate=$(echo "${cert}" | openssl x509 -noout -enddate 2> /dev/null | sed 's/notAfter=//')

          if [[ -n ${enddate}   ]]; then

            declare cert_date_seconds=""
            cert_date_seconds=$(date -d "${enddate}" +%s)

            if [[ ${cert_date_seconds} -lt ${current_date} ]]; then

              expired=1

            else

              expired=0

            fi

          else

            expired=0

          fi

          if [[ ${expired} -eq 0 ]]; then

            printf "%s\n" "${block[@]}" >> "${tmp_bundle}"

          else

            printf "\e[92m++++ ++++ ++++ ++++ ++++ ++++ ++ ✅  Certificate deleted: '%s' (Expired: %s)\e[0m\n" "${bundle}" "${enddate}"

          fi

          block=()

        fi

      done < "${bundle}"

      mv -f "${tmp_bundle}" "${bundle}"

      printf "\e[92m++++ ++++ ++++ ++++ ++++ ++++ ++ ✅ Checking Root-CA Bundle: '%s' done. \e[0m\n" "${bundle}"

    fi

  done
}

printf "\e[95m++++ ++++ ++++ ++++ ++++ ++++ ++ 🧪 Check certificates in: '%s'.\e[0m\n" "${search_dirs[*]}"
create_backup
delete_expired_from_all_bundles
check_certificates

if [[ ${#expired_certificates[@]} -eq 0 ]]; then

  printf "\e[92m++++ ++++ ++++ ++++ ++++ ++++ ++ ✅ No expired certificates found.\e[0m\n"

else

  printf "\e[95m++++ ++++ ++++ ++++ ++++ ++++ ++ 🧪 Expired certificates found:\e[0m\n"

  for exp_cert in "${expired_certificates[@]}"; do

    printf "\e[92m++++ ++++ ++++ ++++ ++++ ++++ ++ '%s'. \e[0m\n" "${exp_cert}"

  done

  for exp_cert in "${expired_certificates[@]}"; do

    rm -f "${exp_cert}"

    printf "\e[92m++++ ++++ ++++ ++++ ++++ ++++ ++ ✅ Certificate deleted: '%s'.\e[0m\n" "${exp_cert}"
    basename=$(basename "${exp_cert}")
    mozilla_entry="mozilla/${basename%.pem}.crt"
    mozilla_entry="${mozilla_entry%.crt}.crt"
    declare ca_conf="/etc/ca-certificates.conf"

    if grep -Fxq "${mozilla_entry}" "${ca_conf}"; then

      sed -i "s|^${mozilla_entry}$|#${mozilla_entry}|" "${ca_conf}"
      printf "\e[92m++++ ++++ ++++ ++++ ++++ ++++ ++ ✅ Entry in ca-certificates.conf deselected: '#%s'.\e[0m\n" "${mozilla_entry}"

    fi

  done

  printf "\e[95m++++ ++++ ++++ ++++ ++++ ++++ ++ ✅ Updating the certificate cache ... \e[0m\n"
  update-ca-certificates --fresh
  printf "\e[92m++++ ++++ ++++ ++++ ++++ ++++ ++ ✅ Updating the certificate cache done.\e[0m\n"

fi

printf "\e[92m++++ ++++ ++++ ++++ ++++ ++++ ++ ✅ '%s' applied successfully. \e[0m\n" "${0}"


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