From cddcb9ab39cb6fbf19a97e4b64881539a3c9ae92 Mon Sep 17 00:00:00 2001 From: Christian Tosta <7252968+christiantosta@users.noreply.github.com> Date: Mon, 4 Aug 2025 11:38:45 -0300 Subject: [PATCH] Replaced crt2bundle by cert-tool --- CMakeLists.txt | 103 +++++++++++++--------------- crt2bundle.sh | 14 ---- utils/cert-tool | 176 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 222 insertions(+), 71 deletions(-) delete mode 100755 crt2bundle.sh create mode 100755 utils/cert-tool diff --git a/CMakeLists.txt b/CMakeLists.txt index 288f1cc..dcf452f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,72 +29,61 @@ set(SourceFiles include(CPackLists.txt) +add_custom_target(clear-cache + COMMAND rm -rf cache/ +) + add_custom_target(clear-certs - COMMAND rm -rf - certs/ - docs/ - pki/ + COMMAND rm -rf certs/ +) + +add_custom_target(clear-anchors + COMMAND rm -rf pki/ ) add_custom_target(clear-docs - COMMAND rm -rf - docs/ + COMMAND rm -rf docs/ +) + +add_custom_target(clear-all + DEPENDS + clear-anchors + clear-cache + clear-certs + clear-docs +) + +add_custom_target(sources + COMMAND xargs -n1 + curl + --create-dirs + --output-dir cache + -ksO < ${CMAKE_CURRENT_SOURCE_DIR}/sources + DEPENDS + clear-cache ) add_custom_target(certs - COMMAND xargs -n1 - curl - --create-dirs - --output-dir certs - -ksO < ${CMAKE_CURRENT_SOURCE_DIR}/sources - && cd certs - && (sha512sum -c --quiet ${HASH_FILE} || exit -1) - && unzip ACcompactado.zip - && rm -f ACcompactado.zip ${HASH_FILE} + COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/utils/cert-tool extract + && ${CMAKE_CURRENT_SOURCE_DIR}/utils/cert-tool classify DEPENDS clear-certs -) - -add_custom_target(docs ALL - COMMAND mkdir docs - && mv certs/*.pdf docs/ - DEPENDS - clear-docs - certs -) - -add_custom_target(isrg-root-x2.crt - COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/crt2bundle.sh - pki/ca-trust-source/anchors/isrg-root-x2.crt - certs/isrg-root-x2.pem - DEPENDS - certs -) - -add_custom_target(lets-encrypt-ca-bundle.crt - COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/crt2bundle.sh - pki/ca-trust-source/anchors/lets-encrypt-ca-bundle.crt - certs/lets-encrypt-e1.pem - certs/lets-encrypt-e2.pem - certs/lets-encrypt-r3.pem - certs/lets-encrypt-r4.pem - DEPENDS - certs -) - -add_custom_target(icp-brasil-ca-bundle.crt - COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/crt2bundle.sh - pki/ca-trust-source/anchors/icp-brasil-ca-bundle.crt - certs/*.crt - DEPENDS - certs + sources ) add_custom_target(anchors ALL + COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/utils/cert-tool anchors DEPENDS - isrg-root-x2.crt - lets-encrypt-ca-bundle.crt - icp-brasil-ca-bundle.crt + clear-anchors + certs +) + +add_custom_target(docs ALL + COMMAND mkdir docs + && cp cache/*.pdf docs/ + DEPENDS + clear-docs + sources ) # Checks for OpeSSL utility @@ -124,12 +113,12 @@ endif() message("-- Set install path to CA certificates: ${CACERT_INSTALL_DIR}") install( - FILES - ${CMAKE_CURRENT_BINARY_DIR}/pki/ca-trust-source/anchors/isrg-root-x2.crt - ${CMAKE_CURRENT_BINARY_DIR}/pki/ca-trust-source/anchors/lets-encrypt-ca-bundle.crt - ${CMAKE_CURRENT_BINARY_DIR}/pki/ca-trust-source/anchors/icp-brasil-ca-bundle.crt + DIRECTORY + ${CMAKE_CURRENT_BINARY_DIR}/pki/ca-trust-source/anchors/. DESTINATION ${CMAKE_INSTALL_PREFIX}/${CACERT_INSTALL_DIR} + FILES_MATCHING + PATTERN "*.crt" ) set(DOCS_INSTALL_DIR "share/doc/${PROJECT_NAME}") diff --git a/crt2bundle.sh b/crt2bundle.sh deleted file mode 100755 index 04c856a..0000000 --- a/crt2bundle.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash - -out=${1} -mkdir -p $(dirname ${out}) -shift - -in='' -for c in ${*}; do - echo "+ Loading CA certificate: ${c}"; - in="${in} -certfile ${c}"; -done; - -openssl crl2pkcs7 -nocrl ${in} \ - | openssl pkcs7 -print_certs -out ${out} diff --git a/utils/cert-tool b/utils/cert-tool new file mode 100755 index 0000000..42bfc19 --- /dev/null +++ b/utils/cert-tool @@ -0,0 +1,176 @@ +#!/bin/bash +set -euo pipefail + +check_cert_validity() { + local cert=("${@}") + + # Get validity dates of certificate + local expire=$(printf "%s\\n" "${cert[@]:1}" \ + | openssl x509 \ + -noout \ + -dates \ + | sed '/notAfter/!d;s/notAfter=//g;s/ /\\ /g' \ + | xargs date +%s -d + ) + + # Checks if certificate is valid at this date + if [[ ${expire} -gt $(date +%s -d now) ]]; then + return 0 + else + printf "%s: %s [%s %s]\\n" \ + $"-- WARNING" \ + $"Certificate was expired" \ + $"Fingerprint=(SHA256)" \ + ${cert[0]} + return 1 + fi +} + +unzip_fingerprint() { + local zip_source=${1:-} + local fp_algo=sha256 + + local files=$( + [[ -f "${zip_source}" ]] && \ + (unzip -qql ${zip_source} | awk '{print $4}') + ) + + # Unzip cert into array and compute their fingerprint + printf "%s: %s\\n" $"Archive" "${zip_source}" + local file; for file in ${files}; do + readarray -t cert < <( + unzip -p ${zip_source} ${file} \ + | openssl x509 \ + -fingerprint \ + -${fp_algo} \ + | sed 's/.*Fingerprint=//g;s/://g' + ) + + # Check validity dates of certificate then writes it to disk + if check_cert_validity "${cert[@]}"; then + local cert_file="certs/${cert[0]}.crt" + printf " %s %s\\n" $"Inflating" "certs/${file}" + #printf " %s %s\\n" $"Inflating" "certs/${cert[0]}.crt" + #printf " - %s=(%s) %s\\n" "Fingerprint" "${fp_algo^^}" "${cert[0]}" + printf "%s\\n" "${cert[@]:1}" > "${cert_file}" + fi + done +} + +copy_fingerprint() { + local cert_source=${1:-} + local fp_algo=sha256 + + readarray -t cert < <( + cat ${cert_source} \ + | openssl x509 \ + -fingerprint \ + -${fp_algo} \ + | sed 's/.*Fingerprint=//g;s/://g' + ) + + # Check validity dates of certificate then writes it to disk + if check_cert_validity "${cert[@]}"; then + local cert_file="certs/${cert[0]}.crt" + printf "%s %s\\n" $"Copying" "certs/${cert_source}" + printf "%s\\n" "${cert[@]:1}" > "${cert_file}" + fi +} + +#split() { +# local certs=("${@}") +# +# printf "%s\\n" "${certs[@]}" \ +# | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' \ +# | csplit \ +# --quiet \ +# --elide-empty-files \ +# --prefix ${random_prefix:-}-cert \ +# --suffix-format=-%02d.crt \ +# - '/-END CERTIFICATE-/1' \ +# '{*}' +#} + +function extract() { + local file + mkdir -p certs + find cache -type f | while read file; do + case "$(file -b --mime-type ${file})" in + application/zip) unzip_fingerprint "${file}" ;; + application/x-pem-file) copy_fingerprint ${file} ;; + esac + done +} + + +function classify() { + # Create classified output directories + mkdir -p certs/{ca-root,ca-trust,servers} + + # Process and classify generated files + echo -e "\n-- CLASSIFYING CACHED CERTIFICATES\n" + count=0 + cert_files=$(find certs/ -maxdepth 1 -type f) + for cert_file in ${cert_files}; do + fingerprint="(SHA256) ${cert_file}" + echo "+ Processing certificate [Fingerprint: ${fingerprint}]" + issuer=$(openssl x509 -in "${cert_file}" -noout -issuer | sed 's/^issuer=//g') + issuer_o=$(echo "${issuer}" | grep -iPo 'O\s*=\s*\K[^,]+' || :) + subject=$(openssl x509 -in "${cert_file}" -noout -subject | sed 's/^subject=//g') + subject_o=$(echo "${subject}" | grep -iPo 'O\s*=\s*\K[^,]+' || :) + subject_cn=$(echo "${subject}" | grep -iPo 'CN\s*=\s*\K[^,]+' || :) + cert_o=$(echo "${subject_o^^}" | sed -E "s/\s/_/g;s/'//g;s/\/.*//g;s/\*\.//g") + cert_cn=$(echo "${subject_cn}" | sed -E "s/\s/_/g;s/\/.*//g;s/^\*\./wildcard-/g") + + # save temporary pem file to .CRT file + if [[ "${subject_cn}" =~ "gov.br" ]]; then # it's a server certificate + cert_crt_file="${issuer_o^^}-${cert_cn}.crt" + openssl x509 -in "${cert_file}" -out "certs/servers/${cert_crt_file}" + let count=count+1 + elif [[ "${subject}" == "${issuer}" ]]; then # it's a root certificate (self-signed) + cert_crt_file="${cert_o}-${cert_cn}.crt" + openssl x509 -in "${cert_file}" -out "certs/ca-root/${cert_crt_file}" + let count=count+1 + else # it's an intermediate certificate + cert_crt_file="${cert_o}-${cert_cn}.crt" + openssl x509 -in "${cert_file}" -out "certs/ca-trust/${cert_crt_file}" + let count=count+1 + fi + done + echo "-- Processed certificates: ${count}" +} + +function anchors() { + echo -e "\n-- GENERATING P11-KIT SOURCE ANCHORS" + + local ca_list=$( + (for cert in certs/{ca-root,ca-trust}/*.crt; do + openssl x509 -in ${cert} -noout -subject \ + | grep -iPo 'O\s*=\s*\K[^,]+' \ + | sed -E "s/\s/_/g;s/'//g;s/\/.*//g;s/\*\.//g;s/.*/\U&/"; + done; + for cert in certs/servers/*.crt; do + openssl x509 -in ${cert} -noout -issuer \ + | grep -iPo 'O\s*=\s*\K[^,]+' \ + | sed -E "s/\s/_/g;s/'//g;s/\/.*//g;s/\*\.//g;s/.*/\U&/"; + done;) | sort -u) + + for ca in ${ca_list}; do + echo -e "\n-> Generating p11-kit source anchors for CA \"${ca}\"" + local out=pki/ca-trust-source/anchors/${ca,,}-ca-bundle.crt + mkdir -p $(dirname ${out}); in= + for c in $(find certs/{ca-root,ca-trust,servers}/ -name ${ca}*); do + echo "+ Loading CA certificate: ${c}" + in="${in} -certfile ${c}" + done \ + && openssl crl2pkcs7 -nocrl ${in} \ + | openssl pkcs7 -print_certs -out ${out} + done +} + +cmd=${@:1}; shift +${cmd} ${@} + +exit 0 + +# vim: ts=2:sw=2:sts=2:et