#!/bin/sh
# shellcheck disable=SC2039

# Check if the script is being sourced or not.
# shellcheck disable=SC2142
alias is_sourced='[ "$_" != "$0" ] && expr "$-" : ".*i.*" > /dev/null'

# Returns the subject hash of the certificate path provided.
alias subject_hash='openssl x509 -noout -subject_hash -in'

# Returns the issuer hash of the certificate path provided.
alias issuer_hash='openssl x509 -noout -issuer_hash -in'

find_root_cert () {
    # Returns the (first) root (self-signed) certificate found in the list
    # of file paths provided.
    local filename
    for filename in "$@"
    do
        if [ -f "$filename" ] && \
            [ "$(subject_hash "$filename")" = "$(issuer_hash "$filename")" ]
        then
            echo "$filename"
            break
        fi
    done
}

find_cert_by_issuer_hash () {
    # Gets a hash and a list of filenames, returns the
    # filename of the certificate with that issuer hash. Ignores self-signed
    # (root CA) certificates.
    local certhash filename
    certhash="$1"
    shift
    for filename in "$@"
    do
        if [ -f "$filename" ] && \
            [ "$(issuer_hash "$filename")" = "$certhash" ] && \
            [ "$(issuer_hash "$filename")" != "$(subject_hash "$filename")" ]
        then
            echo "$filename"
            break
        fi
    done
}

unbundle_cert () {
    # Recieves a file path, creates a directory named certs with all of the
    # individual certs contained within that file inside the directory (the
    # filenames are the subject hash for each certificate).
    local certificate
    mkdir -p certs
    awk '/-----BEGIN[A-Z0-9 ]*CERTIFICATE-----/ {n++}
        n > 0 {print > ("certs/cert" (1+n))}' "$1"
    for certificate in certs/cert*
    do
        [ -f "$certificate" ] || continue
        mv "$certificate" "certs/$(subject_hash "$certificate")"
    done
}

bundle_certs () {
    local issuer issued ordered_certs filename
    for filename in "$@"
    do
        [ -f "$filename" ] && unbundle_cert "$filename"
    done
    cd certs
    issuer="$(find_root_cert "*")"
    if [ -z "$issuer" ]
    then
        echo "Failed to find root certificate." > /dev/stderr
        exit 1
    fi
    issued="$(find_cert_by_issuer_hash "$issuer" "*")"
    while [ -n "$issued" ]
    do
        ordered_certs="$issued $ordered_certs"
        issuer="$issued"
        issued="$(find_cert_by_issuer_hash "$issuer" "*")"
    done
    cat "$ordered_certs"
    cd ..
    rm -r certs
}


if ! is_sourced
then
    set -eu
    if [ $# -eq 0 ]
    then
        echo "Usage: $0 filename [filename2 [filename3 ...]]" > /dev/stderr
        exit 1
    else
        bundle_certs "$@"
    fi
fi
