diff --git a/scripts/libmakepkg/integrity/verify_signature.sh.in b/scripts/libmakepkg/integrity/verify_signature.sh.in index ad5bb66d..4aa14d94 100644 --- a/scripts/libmakepkg/integrity/verify_signature.sh.in +++ b/scripts/libmakepkg/integrity/verify_signature.sh.in @@ -26,6 +26,18 @@ LIBRARY=${LIBRARY:-'@libmakepkgdir@'} source "$LIBRARY/util/message.sh" source "$LIBRARY/util/pkgbuild.sh" +# Returns the elements of the first array that are not found in the second +# array as the third array. All arrays are passed by name. +set_difference() { + local -n first=$1 + local -n second=$2 + local -n result=$3 + result=() + for element in "${first[@]}"; do + ! in_array "$element" "${second[@]}" && result+=("$element") + done +} + check_pgpsigs() { (( SKIPPGPCHECK )) && return 0 ! source_has_signatures && return 0 @@ -56,48 +68,53 @@ check_pgpsigs() { fi # these variables are assigned values in parse_gpg_statusfile - success=0 - status= - pubkey= - fingerprint= + success= + declare -A status + fingerprints=() trusted= parse_gpg_statusfile "$statusfile" if (( ! $success )); then printf '%s' "$(gettext "FAILED")" >&2 - case "$status" in - "missingkey") - printf ' (%s)' "$(gettext "unknown public key") $pubkey" >&2 - ;; - "revokedkey") - printf " ($(gettext "public key %s has been revoked"))" "$pubkey" >&2 - ;; - "bad") - printf ' (%s)' "$(gettext "bad signature from public key") $pubkey" >&2 - ;; - "error") - printf ' (%s)' "$(gettext "error during signature verification")" >&2 - ;; - esac + for pubkey in "${!status[@]}"; do + case "${status["$pubkey"]}" in + "missingkey") + printf ' (%s)' "$(gettext "unknown public key") $pubkey" >&2 + ;; + "revokedkey") + printf " ($(gettext "public key %s has been revoked"))" "$pubkey" >&2 + ;; + "bad") + printf ' (%s)' "$(gettext "bad signature from public key") $pubkey" >&2 + ;; + "error") + printf ' (%s)' "$(gettext "error during signature verification")" >&2 + ;; + esac + done errors=1 else + local invalid_keys + set_difference fingerprints validpgpkeys invalid_keys if (( ${#validpgpkeys[@]} == 0 && !trusted )); then - printf "%s ($(gettext "the public key %s is not trusted"))" $(gettext "FAILED") "$fingerprint" >&2 + printf "%s ($(gettext "the public key %s is not trusted"))" $(gettext "FAILED") "${fingerprints[*]}" >&2 errors=1 - elif (( ${#validpgpkeys[@]} > 0 )) && ! in_array "$fingerprint" "${validpgpkeys[@]}"; then - printf "%s (%s %s)" "$(gettext "FAILED")" "$(gettext "invalid public key")" "$fingerprint" >&2 + elif (( ${#validpgpkeys[@]} > 0 )) && (( ${#invalid_keys[@]} > 0 )); then + printf "%s (%s %s)" "$(gettext "FAILED")" "$(gettext "invalid public key")" "${invalid_keys[*]}" >&2 errors=1 else printf '%s' "$(gettext "Passed")" >&2 - case "$status" in - "expired") - printf ' (%s)' "$(gettext "WARNING:") $(gettext "the signature has expired.")" >&2 - warnings=1 - ;; - "expiredkey") - printf ' (%s)' "$(gettext "WARNING:") $(gettext "the key has expired.")" >&2 - warnings=1 - ;; - esac + for pubkey in "${!status[@]}"; do + case "${status["$pubkey"]}" in + "expired") + printf " (%s $(gettext "the signature by key %s has expired."))" "$(gettext "WARNING:")" "$pubkey" >&2 + warnings=1 + ;; + "expiredkey") + printf " (%s $(gettext "the key %s has expired."))" "$(gettext "WARNING:")" "$pubkey" >&2 + warnings=1 + ;; + esac + done fi fi printf '\n' >&2 @@ -201,59 +218,57 @@ verify_git_signature() { parse_gpg_statusfile() { local type arg1 arg6 arg10 + success=-1 + trusted=-1 while read -r _ type arg1 _ _ _ _ arg6 _ _ _ arg10 _; do case "$type" in GOODSIG) - pubkey=$arg1 - success=1 - status="good" + success=$((success!=0)) + status["$arg1"]="good" ;; EXPSIG) - pubkey=$arg1 - success=1 - status="expired" + success=$((success!=0)) + status["$arg1"]="expired" ;; EXPKEYSIG) - pubkey=$arg1 - success=1 - status="expiredkey" + success=$((success!=0)) + status["$arg1"]="expiredkey" ;; REVKEYSIG) - pubkey=$arg1 success=0 - status="revokedkey" + status["$arg1"]="revokedkey" ;; BADSIG) - pubkey=$arg1 success=0 - status="bad" + status["$arg1"]="bad" ;; ERRSIG) - pubkey=$arg1 success=0 if [[ $arg6 == 9 ]]; then - status="missingkey" + status["$arg1"]="missingkey" else - status="error" + status["$arg1"]="error" fi ;; VALIDSIG) if [[ $arg10 ]]; then # If the file was signed with a subkey, arg10 contains # the fingerprint of the primary key - fingerprint=$arg10 + fingerprints+=("$arg10") else - fingerprint=$arg1 + fingerprints+=("$arg1") fi ;; TRUST_UNDEFINED|TRUST_NEVER) trusted=0 ;; TRUST_MARGINAL|TRUST_FULLY|TRUST_ULTIMATE) - trusted=1 + trusted=$((trusted!=0)) ;; esac done < "$1" + success=$((success>0)) + trusted=$((trusted>0)) } source_has_signatures() {