4bf0de7
#!/bin/bash
4bf0de7
4bf0de7
# Copyright 2018 B. Persson, Bjorn@Rombobeorn.se
4bf0de7
#
4bf0de7
# This program is free software; you can redistribute it and/or modify
4bf0de7
# it under the terms of the GNU General Public License as published by
4bf0de7
# the Free Software Foundation; either version 2 of the License, or
4bf0de7
# (at your option) any later version.
4bf0de7
#
4bf0de7
# This program is distributed in the hope that it will be useful,
4bf0de7
# but WITHOUT ANY WARRANTY; without even the implied warranty of
4bf0de7
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
4bf0de7
# GNU General Public License for more details.
4bf0de7
#
4bf0de7
# You should have received a copy of the GNU General Public License along
4bf0de7
# with this program; if not, write to the Free Software Foundation, Inc.,
4bf0de7
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
4bf0de7
4bf0de7
4bf0de7
function print_help {
4bf0de7
    cat <<'EOF'
4bf0de7
Usage: gpgverify --keyring=<pathname> --signature=<pathname> --data=<pathname>
4bf0de7
4bf0de7
gpgverify is a wrapper around gpgv designed for easy and safe scripting. It
4bf0de7
verifies a file against a detached OpenPGP signature and a keyring. The keyring
4bf0de7
shall contain all the keys that are trusted to certify the authenticity of the
4bf0de7
file, and must not contain any untrusted keys.
4bf0de7
4bf0de7
The differences, compared to invoking gpgv directly, are that gpgverify accepts
4bf0de7
the keyring in either ASCII-armored or unarmored form, and that it will not
4bf0de7
accidentally use a default keyring in addition to the specified one.
4bf0de7
4bf0de7
Parameters:
4bf0de7
  --keyring=<pathname>    keyring with all the trusted keys and no others
4bf0de7
  --signature=<pathname>  detached signature to verify
4bf0de7
  --data=<pathname>       file to verify against the signature
4bf0de7
EOF
4bf0de7
}
4bf0de7
4bf0de7
4bf0de7
fatal_error() {
4bf0de7
    message="$1"  # an error message
4bf0de7
    status=$2     # a number to use as the exit code
4bf0de7
    echo "gpgverify: $message" >&2
4bf0de7
    exit $status
4bf0de7
}
4bf0de7
4bf0de7
4bf0de7
require_parameter() {
4bf0de7
    term="$1"   # a term for a required parameter
4bf0de7
    value="$2"  # Complain and terminate if this value is empty.
4bf0de7
    if test -z "${value}" ; then
4bf0de7
        fatal_error "No ${term} was provided." 2
4bf0de7
    fi
4bf0de7
}
4bf0de7
4bf0de7
4bf0de7
check_status() {
4bf0de7
    action="$1"  # a string that describes the action that was attempted
4bf0de7
    status=$2    # the exit code of the command
4bf0de7
    if test $status -ne 0 ; then
4bf0de7
        fatal_error "$action failed." $status
4bf0de7
    fi
4bf0de7
}
4bf0de7
4bf0de7
4bf0de7
# Parse the command line.
4bf0de7
keyring=
4bf0de7
signature=
4bf0de7
data=
4bf0de7
for parameter in "$@" ; do
4bf0de7
    case "${parameter}" in
4bf0de7
        (--help)
4bf0de7
            print_help
4bf0de7
            exit
4bf0de7
            ;;
4bf0de7
        (--keyring=*)
4bf0de7
            keyring="${parameter#*=}"
4bf0de7
            ;;
4bf0de7
        (--signature=*)
4bf0de7
            signature="${parameter#*=}"
4bf0de7
            ;;
4bf0de7
        (--data=*)
4bf0de7
            data="${parameter#*=}"
4bf0de7
            ;;
4bf0de7
        (*)
4bf0de7
            fatal_error "Unknown parameter: \"${parameter}\"" 2
4bf0de7
            ;;
4bf0de7
    esac
4bf0de7
done
4bf0de7
require_parameter 'keyring' "${keyring}"
4bf0de7
require_parameter 'signature' "${signature}"
4bf0de7
require_parameter 'data file' "${data}"
4bf0de7
4bf0de7
# Make a temporary working directory.
4bf0de7
workdir="$(mktemp --directory)"
4bf0de7
check_status 'Making a temporary directory' $?
4bf0de7
workring="${workdir}/keyring.gpg"
4bf0de7
4bf0de7
# Decode any ASCII armor on the keyring. This is harmless if the keyring isn't
4bf0de7
# ASCII-armored.
4bf0de7
gpg2 --homedir="${workdir}" --yes --output="${workring}" --dearmor "${keyring}"
4bf0de7
check_status 'Decoding the keyring' $?
4bf0de7
4bf0de7
# Verify the signature using the decoded keyring.
4bf0de7
gpgv2 --homedir="${workdir}" --keyring="${workring}" "${signature}" "${data}"
4bf0de7
check_status 'Signature verification' $?
4bf0de7
4bf0de7
# (--homedir isn't actually necessary. --dearmor processes only the input file,
4bf0de7
# and if --keyring is used and contains a slash, then gpgv2 uses only that
4bf0de7
# keyring. Thus neither command will look for a default keyring, but --homedir
4bf0de7
# makes extra double sure that no default keyring will be touched in case
4bf0de7
# another version of GPG works differently.)
4bf0de7
4bf0de7
# Clean up. (This is not done in case of an error that may need inspection.)
4bf0de7
rm --recursive --force ${workdir}