From 8ab1665575137e607ead3fa34982b6279373c39c Mon Sep 17 00:00:00 2001 From: Patrick McDermott Date: Fri, 17 Jul 2020 21:50:30 -0400 Subject: Initial commit --- (limited to 'certdata2pem.sh') diff --git a/certdata2pem.sh b/certdata2pem.sh new file mode 100755 index 0000000..e12fc67 --- /dev/null +++ b/certdata2pem.sh @@ -0,0 +1,176 @@ +#!/bin/sh +# +# Converts NSS certdata objects text into a concatenated PEM bundle. +# +# Copyright (C) 2020 Patrick McDermott +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +set -eu + +error() +{ + local fmt="${1}" + shift 1 + + printf "Error: ${fmt}\n" "${@}" 1>&2 +} + +parse() +{ + local txt_input="${1}" + local trust_type="${2}" + local pem_output="${3}" + shift 3 + local attr= + local type= + local val= + local class= + local label= + local value= + local trust= + local trusted= + + if [ x"${txt_input}" != x'-' ]; then + exec 0<"${txt_input}" + fi + if [ x"${pem_output}" != x'-' ]; then + exec 1>"${pem_output}" + fi + + while read -r attr && [ x"${attr}" != x'BEGINDATA' ]; do :; done + + while read -r attr type val; do + case "${attr}" in + '#'*) + continue + ;; + 'CKA_CLASS') + class="${val}" + ;; + 'CKA_LABEL') + val="${val#\"}" + val="${val%\"}" + label="$(printf '%s' "${val}" | \ + tr -C 'A-Za-z0-9_' '_')" + ;; + 'CKA_VALUE') + if [ x"${type}" != x'MULTILINE_OCTAL' ]; then + error 'Unsupported value type' + return 1 + fi + value= + while read -r val; do + case "${val}" in + 'END') + break + ;; + *[!0-7\\]*) + error "Invalid $(: \ + )multiline $(: \ + )octal value" + return 1 + ;; + *) + value="${value}$(printf\ + "${val}")" + ;; + esac + done + ;; + "CKA_TRUST_${trust_type}") + trust="${val}" + ;; + '') + if [ -z "${class}" ]; then + error 'Object missing class' + return 1 + fi + if [ -z "${label}" ]; then + error 'Object missing label' + return 1 + fi + if [ x"${class}" = x'CKO_CERTIFICATE' ]; then + if [ -z "${value}" ]; then + error 'Object missing value' + return 1 + fi + eval "certificate_${label}=\${value}" + elif [ x"${class}" = x'CKO_NSS_TRUST' ]; then + if [ -z "${trust}" ]; then + error 'Object missing trust' + return 1 + fi + if [ x"${trust}" = \ + x'CKT_NSS_TRUSTED_DELEGATOR' ] + then + trusted="${trusted} ${label}" + fi + elif [ x"${class}" = \ + x'CKO_NSS_BUILTIN_ROOT_LIST' ] + then + : + else + error 'Unknown class "%s"' "${val}" + return 1 + fi + class= + label= + value= + trust= + esac + done <<-EOF + $(cat) + + EOF + # Extra newline in input to trigger final empty line block in parser. + + for label in ${trusted}; do + printf '%s\n' '-----BEGIN CERTIFICATE-----' + eval "printf '%s' \"\${certificate_${label}}\"" | base64 - + printf '%s\n' '-----END CERTIFICATE-----' + done + + return 0 +} + +usage() +{ + printf 'Usage: %s \n' "${0}" + printf 'Example: %s certdata.txt SERVER_AUTH certdata.pem\n' "${0}" + + return 0 +} + +main() +{ + local txt_input= + local trust_type= + local pem_output= + + if [ ${#} -ne 3 ]; then + usage 1>&2 + return 1 + fi + txt_input="${1}" + trust_type="${2}" + pem_output="${3}" + shift 3 + + parse "${txt_input}" "${trust_type}" "${pem_output}" || return 1 + + return 0 +} + +main "${@}" -- cgit v0.9.1