makepkg: Add support for verifying pgp signatures

Many projects provide signature files along with the source code
archives. It's good to check these, too, when verifying the integrity
of source code archives.
Not everybody is using gpg so the verification can be disabled with
--skippgpcheck.
Additionally, only a warning is displayed when the key that signed the
source file is unknown.

Signed-off-by: Allan McRae <allan@archlinux.org>
Signed-off-by: Dan McGee <dan@archlinux.org>
This commit is contained in:
Wieland Hoffmann 2011-07-06 13:02:19 +02:00 committed by Dan McGee
parent 9929a34a6d
commit 94f61c5b29
2 changed files with 96 additions and 2 deletions

View file

@ -87,6 +87,9 @@ Options
*--skipinteg*:: *--skipinteg*::
Do not perform any integrity checks, just print a warning instead. Do not perform any integrity checks, just print a warning instead.
*\--skippgpcheck*::
Do not verify PGP signatures of the source files.
*-h, \--help*:: *-h, \--help*::
Output syntax and command line options. Output syntax and command line options.

View file

@ -57,6 +57,7 @@ FORCE=0
INFAKEROOT=0 INFAKEROOT=0
GENINTEG=0 GENINTEG=0
SKIPINTEG=0 SKIPINTEG=0
SKIPPGPCHECK=0
INSTALL=0 INSTALL=0
NOBUILD=0 NOBUILD=0
NODEPS=0 NODEPS=0
@ -337,6 +338,16 @@ in_array() {
return 1 # Not Found return 1 # Not Found
} }
source_has_signatures(){
local file
for file in "${source[@]}"; do
if [[ $file =~ .*(sig|asc) ]]; then
return 0
fi
done
return 1
}
get_downloadclient() { get_downloadclient() {
# $1 = URL with valid protocol prefix # $1 = URL with valid protocol prefix
local url=$1 local url=$1
@ -684,6 +695,74 @@ check_checksums() {
fi fi
} }
check_pgpsigs() {
(( SKIPPGPCHECK )) && return 0
! source_has_signatures && return 0
msg "$(gettext "Verifying source file signatures with %s...")" "gpg"
local file
local warning=0
local errors=0
local statusfile=$(mktemp)
for file in "${source[@]}"; do
file="$(get_filename "$file")"
if [[ ! $file =~ .*(sig|asc) ]]; then
continue
fi
echo -n " ${file%.*} ... " >&2
if ! file="$(get_filepath "$file")"; then
echo "$(gettext "SIGNATURE NOT FOUND")" >&2
errors=1
continue
fi
if ! sourcefile="$(get_filepath "${file%.*}")"; then
echo "$(gettext "SOURCE FILE NOT FOUND")" >&2
errors=1
continue
fi
if ! gpg --quiet --batch --status-file "$statusfile" --verify "$file" "$sourcefile" 2> /dev/null; then
if grep "NO_PUBKEY" "$statusfile" > /dev/null; then
echo "$(gettext "Warning: Unknown public key") $(awk '/NO_PUBKEY/ {print $3}' $statusfile)" >&2
warnings=1
else
echo "$(gettext "FAILED")" >&2
errors=1
fi
else
if grep "REVKEYSIG" "$statusfile" > /dev/null; then
echo "$(gettext "Passed")" "-" "$(gettext "Warning: the key has been revoked.")" >&2
errors=1
elif grep "EXPSIG" "$statusfile" > /dev/null; then
echo "$(gettext "Passed")" "-" "$(gettext "Warning: the signature has expired.")" >&2
warnings=1
elif grep "EXPKEYSIG" "$statusfile" > /dev/null; then
echo "$(gettext "Passed")" "-" "$(gettext "Warning: the key has expired.")" >&2
warnings=1
else
echo $(gettext "Passed") >&2
fi
fi
done
rm -f "$statusfile"
if (( errors )); then
error "$(gettext "One or more PGP signatures could not be verified!")"
exit 1
fi
if (( warnings )); then
warning "$(gettext "Warnings have occurred while verifying the signatures.")"
plain "$(gettext "Please make sure you really trust them.")"
fi
}
extract_sources() { extract_sources() {
msg "$(gettext "Extracting Sources...")" msg "$(gettext "Extracting Sources...")"
local netfile local netfile
@ -1515,6 +1594,14 @@ check_software() {
fi fi
fi fi
# gpg - source verification
if (( ! SKIPPGPCHECK )) && [[ source_has_signatures ]]; then
if ! type -p gpg >/dev/null; then
error "$(gettext "Cannot find the %s binary required for verifying source files.")" "gpg"
ret=1
fi
fi
# openssl - checksum operations # openssl - checksum operations
if (( ! SKIPINTEG )); then if (( ! SKIPINTEG )); then
if ! type -p openssl >/dev/null; then if ! type -p openssl >/dev/null; then
@ -1752,6 +1839,7 @@ usage() {
echo "$(gettext " --pkg <list> Only build listed packages from a split package")" echo "$(gettext " --pkg <list> Only build listed packages from a split package")"
printf "$(gettext " --sign Sign the resulting package with %s")\n" "gpg" printf "$(gettext " --sign Sign the resulting package with %s")\n" "gpg"
echo "$(gettext " --skipinteg Do not fail when integrity checks are missing")" echo "$(gettext " --skipinteg Do not fail when integrity checks are missing")"
echo "$(gettext " --skippgpcheck Do not verify source files with pgp signatures")"
echo "$(gettext " --source Generate a source-only tarball without downloaded sources")" echo "$(gettext " --source Generate a source-only tarball without downloaded sources")"
echo echo
printf "$(gettext "These options can be passed to %s:")\n" "pacman" printf "$(gettext "These options can be passed to %s:")\n" "pacman"
@ -1786,9 +1874,9 @@ ARGLIST=("$@")
# Parse Command Line Options. # Parse Command Line Options.
OPT_SHORT="AcdefFghiLmop:rRsV" OPT_SHORT="AcdefFghiLmop:rRsV"
OPT_LONG="allsource,asroot,ignorearch,check,clean,nodeps" OPT_LONG="allsource,asroot,ignorearch,check,clean,nodeps"
OPT_LONG+=",noextract,force,forcever:,geninteg,help,holdver" OPT_LONG+=",noextract,force,forcever:,geninteg,help,holdver,skippgpcheck"
OPT_LONG+=",install,key:,log,nocolor,nobuild,nocheck,nosign,pkg:,rmdeps" OPT_LONG+=",install,key:,log,nocolor,nobuild,nocheck,nosign,pkg:,rmdeps"
OPT_LONG+=",repackage,skipinteg,sign,source,syncdeps,version,config:" OPT_LONG+=",repackage,skipinteg,skippgpcheck,sign,source,syncdeps,version,config:"
# Pacman Options # Pacman Options
OPT_LONG+=",noconfirm,noprogressbar" OPT_LONG+=",noconfirm,noprogressbar"
if ! OPT_TEMP="$(parse_options $OPT_SHORT $OPT_LONG "$@")"; then if ! OPT_TEMP="$(parse_options $OPT_SHORT $OPT_LONG "$@")"; then
@ -1830,6 +1918,7 @@ while true; do
-r|--rmdeps) RMDEPS=1 ;; -r|--rmdeps) RMDEPS=1 ;;
-R|--repackage) REPKG=1 ;; -R|--repackage) REPKG=1 ;;
--skipinteg) SKIPINTEG=1 ;; --skipinteg) SKIPINTEG=1 ;;
--skippgpcheck) SKIPPGPCHECK=1;;
--sign) SIGNPKG='y' ;; --sign) SIGNPKG='y' ;;
--source) SOURCEONLY=1 ;; --source) SOURCEONLY=1 ;;
-s|--syncdeps) DEP_BIN=1 ;; -s|--syncdeps) DEP_BIN=1 ;;
@ -2156,6 +2245,7 @@ if (( SOURCEONLY )); then
if (( ! SKIPINTEG )); then if (( ! SKIPINTEG )); then
# We can only check checksums if we have all files. # We can only check checksums if we have all files.
check_checksums check_checksums
check_pgpsigs
else else
warning "$(gettext "Skipping integrity checks.")" warning "$(gettext "Skipping integrity checks.")"
fi fi
@ -2234,6 +2324,7 @@ else
download_sources download_sources
if (( ! SKIPINTEG )); then if (( ! SKIPINTEG )); then
check_checksums check_checksums
check_pgpsigs
else else
warning "$(gettext "Skipping integrity checks.")" warning "$(gettext "Skipping integrity checks.")"
fi fi