[pacman-dev] [PATCH v3 1/2] makepkg: Add support for verifying pgp signatures

Wieland Hoffmann themineo at googlemail.com
Wed Jul 6 07:02:19 EDT 2011


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.
---
 doc/makepkg.8.txt     |    3 ++
 scripts/makepkg.sh.in |   92 ++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 94 insertions(+), 1 deletions(-)

diff --git a/doc/makepkg.8.txt b/doc/makepkg.8.txt
index e11e9b3..bc1ffc1 100644
--- a/doc/makepkg.8.txt
+++ b/doc/makepkg.8.txt
@@ -87,6 +87,9 @@ Options
 *--skipinteg*::
 	Do not perform any integrity checks, just print a warning instead.
 
+*\--skippgpcheck*::
+	Do not verify PGP signatures of the source files.
+
 *-h, \--help*::
 	Output syntax and command line options.
 
diff --git a/scripts/makepkg.sh.in b/scripts/makepkg.sh.in
index 1b132a9..20ba431 100644
--- a/scripts/makepkg.sh.in
+++ b/scripts/makepkg.sh.in
@@ -57,6 +57,7 @@ FORCE=0
 INFAKEROOT=0
 GENINTEG=0
 SKIPINTEG=0
+SKIPPGPCHECK=0
 INSTALL=0
 NOBUILD=0
 NODEPS=0
@@ -327,6 +328,15 @@ in_array() {
 	return 1 # Not Found
 }
 
+source_has_signatures(){
+	for file in "${source[@]}"; do
+		if [[ $file =~ .*(sig|asc) ]]; then
+			return 0
+		fi
+	done
+	return 1
+}
+
 get_downloadclient() {
 	# $1 = URL with valid protocol prefix
 	local url=$1
@@ -674,6 +684,74 @@ check_checksums() {
 	fi
 }
 
+check_pgpsigs() {
+	(( SKIPPGPCHECK )) && return 0
+	(( ! ${#source[@]} )) && 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
+				errors=1
+				echo "$(gettext "Passed")" "-" "$(gettext "Warning: the key has been revoked.")" >&2
+			elif grep "EXPSIG" "$statusfile" > /dev/null; then
+				warnings=1
+				echo "$(gettext "Passed")" "-" "$(gettext "Warning: the signature has expired.")" >&2
+			elif grep "EXPKEYSIG" "$statusfile" > /dev/null; then
+				warnings=1
+				echo "$(gettext "Passed")" "-" "$(gettext  "Warning: the key has expired.")" >&2
+			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. Please make sure you really trust them.")"
+	fi
+}
+
 extract_sources() {
 	msg "$(gettext "Extracting Sources...")"
 	local netfile
@@ -1478,6 +1556,14 @@ check_software() {
 		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
 	if (( ! SKIPINTEG )); then
 		if ! type -p openssl >/dev/null; then
@@ -1715,6 +1801,7 @@ usage() {
 	echo "$(gettext "  --pkg <list>     Only build listed packages from a split package")"
 	printf "$(gettext "  --sign           Sign the resulting package with %s")\n" "gpg"
 	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
 	printf "$(gettext "These options can be passed to %s:")\n" "pacman"
@@ -1749,7 +1836,7 @@ ARGLIST=("$@")
 # Parse Command Line Options.
 OPT_SHORT="AcCdefFghiLmop:rRsV"
 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+=",repackage,skipinteg,sign,source,syncdeps,version,config:"
 # Pacman Options
@@ -1791,6 +1878,7 @@ while true; do
 		--nosign)         SIGNPKG='n' ;;
 		-o|--nobuild)     NOBUILD=1 ;;
 		-p)               shift; BUILDFILE=$1 ;;
+		--skippgpcheck)   SKIPPGPCHECK=1;;
 		--pkg)            shift; PKGLIST=($1) ;;
 		-r|--rmdeps)      RMDEPS=1 ;;
 		-R|--repackage)   REPKG=1 ;;
@@ -2122,6 +2210,7 @@ if (( SOURCEONLY )); then
 	if (( ! SKIPINTEG )); then
 		# We can only check checksums if we have all files.
 		check_checksums
+		check_pgpsigs
 	else
 		warning "$(gettext "Skipping integrity checks.")"
 	fi
@@ -2200,6 +2289,7 @@ else
 	download_sources
 	if (( ! SKIPINTEG )); then
 		check_checksums
+		check_pgpsigs
 	else
 		warning "$(gettext "Skipping integrity checks.")"
 	fi
-- 
1.7.6



More information about the pacman-dev mailing list