#!/bin/bash


help() {
  cat << EOH

NAME
    $1 - extract a certificate from a certificate chain PEM file

SYNOPSIS
    $1 [-n CERT-NUM] [[-c] CERT-CHAIN]
    $1 -h

DESCRIPTION
    This script extracts a certificate from CERT-CHAIN, which contains
    concatenated (chained) certificates in PEM format.

OPTIONS
    -n CERT-NUM
        Output the n'th certificate in the chain (counted from 1).

        If CERT-NUM is not given or 0, the script outputs the number of
        certificates in the chain. Otherwise, the script outputs the
        certificate, related to n.

    -c CERT-CHAIN
        Path to the file that contains the concatenated (chained) certificates
        in PEM format. It is also possible to set CERT-CHAIN without typing '-c'
        explicitly, if CERT-CHAIN is the last option. If CERT-CHAIN is not
        given, the chain is expected via stdin.

    -h
        This "manual page".

EXAMPLES
    $1 -c fullchain.cer
    $1 -c fullchain.cer -n 2
    echo | openssl s_client -verify_quiet -connect wu6ch.de:443 -showcerts | $1

AUTHOR
    Wolfgang <w6g@wu6ch.de>

LICENSE
    MIT (https://wu6ch.de/bash/functional_bash/LICENSE)

SEE ALSO
    Functional Bash (https://wu6ch.de/bash/functional_bash/)
EOH
}


set_env() {
  source "/usr/local/lib/functional_bash.sh"

  # shellcheck disable=SC2034
  local -A options=()
  local -a remaining_args=()

  get_options "n:c:" options remaining_args help "$@" && {
    set -- "${remaining_args[@]}"

    cert_num="$(  get_arg options "n" "0")"
    cert_chain="$(get_arg options "c" "${1-"-"}")"

    declare -gr cert_num cert_chain
  }
}


output_num_certs() {
  local cert="certificate" ; (( $1 != 1 )) && cert="${cert}s"
  if (( cert_num <= $1 )) ; then echo "$1 $cert" ; else put_err "$1 $cert" ; fi
}


extract_cert() {
  local line cnt=0

  while read -r line
  do
    (( cnt != -1       )) && [ "$line" == "-----BEGIN CERTIFICATE-----" ] && cnt=$((cnt + 1))
    (( cnt !=  0       )) && (( cnt == cert_num ))                        && echo "$line"
    (( cnt == cert_num )) && [ "$line" == "-----END CERTIFICATE-----"   ] && cnt=-1
  done

  (( cnt < 0 )) || output_num_certs "$cnt"
}


set_env "$@" && read_file "$cert_chain" | extract_cert


# EOF - vim:cc=101
