[pacman-dev] [PATCH v2] libmakepkg: extract functions for integrity checking

Ashley Whetter ashley at awhetter.co.uk
Sun May 8 16:28:28 UTC 2016


Signed-off-by: Ashley Whetter <ashley at awhetter.co.uk>
---
 scripts/Makefile.am                                |   6 +
 scripts/libmakepkg/.gitignore                      |   2 +
 scripts/libmakepkg/integrity.sh.in                 |  45 +++
 .../libmakepkg/integrity/generate_checksum.sh.in   | 107 ++++++
 .../libmakepkg/integrity/generate_signature.sh.in  |  49 +++
 scripts/libmakepkg/integrity/verify_checksum.sh.in | 130 +++++++
 .../libmakepkg/integrity/verify_signature.sh.in    | 216 +++++++++++
 scripts/libmakepkg/util/pkgbuild.sh.in             |  20 +-
 scripts/makepkg.sh.in                              | 428 ---------------------
 scripts/po/POTFILES.in                             |   5 +
 10 files changed, 579 insertions(+), 429 deletions(-)
 create mode 100644 scripts/libmakepkg/integrity.sh.in
 create mode 100644 scripts/libmakepkg/integrity/generate_checksum.sh.in
 create mode 100644 scripts/libmakepkg/integrity/generate_signature.sh.in
 create mode 100644 scripts/libmakepkg/integrity/verify_checksum.sh.in
 create mode 100644 scripts/libmakepkg/integrity/verify_signature.sh.in

diff --git a/scripts/Makefile.am b/scripts/Makefile.am
index 1e6a40b..e4f9fb1 100644
--- a/scripts/Makefile.am
+++ b/scripts/Makefile.am
@@ -41,6 +41,7 @@ LIBRARY = \
 libmakepkgdir = $(datarootdir)/makepkg
 
 LIBMAKEPKGDIRS = \
+	integrity \
 	lint_package \
 	lint_pkgbuild \
 	source \
@@ -53,6 +54,11 @@ LIBMAKEPKG = \
 	libmakepkg/util/util.sh
 
 LIBMAKEPKG_IN = \
+	libmakepkg/integrity.sh \
+	libmakepkg/integrity/generate_checksum.sh \
+	libmakepkg/integrity/generate_signature.sh \
+	libmakepkg/integrity/verify_checksum.sh \
+	libmakepkg/integrity/verify_signature.sh \
 	libmakepkg/lint_package.sh \
 	libmakepkg/lint_package/build_references.sh \
 	libmakepkg/lint_package/missing_backup.sh \
diff --git a/scripts/libmakepkg/.gitignore b/scripts/libmakepkg/.gitignore
index 211a088..941d39a 100644
--- a/scripts/libmakepkg/.gitignore
+++ b/scripts/libmakepkg/.gitignore
@@ -1,3 +1,5 @@
+integrity.sh
+integrity/*.sh
 lint_package.sh
 lint_package/*.sh
 lint_pkgbuild.sh
diff --git a/scripts/libmakepkg/integrity.sh.in b/scripts/libmakepkg/integrity.sh.in
new file mode 100644
index 0000000..cb8159d
--- /dev/null
+++ b/scripts/libmakepkg/integrity.sh.in
@@ -0,0 +1,45 @@
+#!/bin/bash
+#
+#   integrity.sh - functions relating to source integrity checking
+#
+#   Copyright (c) 2011-2016 Pacman Development Team <pacman-dev at archlinux.org>
+#
+#   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 2 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 <http://www.gnu.org/licenses/>.
+#
+
+[[ -n "$LIBMAKEPKG_INTEGRITY_SH" ]] && return
+LIBMAKEPKG_INTEGRITY_SH=1
+
+LIBRARY=${LIBRARY:-'@libmakepkgdir@'}
+
+source "$LIBRARY/util/message.sh"
+
+for lib in "$LIBRARY/integrity/"*.sh; do
+	source "$lib"
+done
+
+check_source_integrity() {
+	if (( SKIPCHECKSUMS && SKIPPGPCHECK )); then
+		warning "$(gettext "Skipping all source file integrity checks.")"
+	elif (( SKIPCHECKSUMS )); then
+		warning "$(gettext "Skipping verification of source file checksums.")"
+		check_pgpsigs "$@"
+	elif (( SKIPPGPCHECK )); then
+		warning "$(gettext "Skipping verification of source file PGP signatures.")"
+		check_checksums "$@"
+	else
+		check_checksums "$@"
+		check_pgpsigs "$@"
+	fi
+}
diff --git a/scripts/libmakepkg/integrity/generate_checksum.sh.in b/scripts/libmakepkg/integrity/generate_checksum.sh.in
new file mode 100644
index 0000000..7a56710
--- /dev/null
+++ b/scripts/libmakepkg/integrity/generate_checksum.sh.in
@@ -0,0 +1,107 @@
+#!/bin/bash
+#
+#   generate_checksum.sh - functions for generating source checksums
+#
+#   Copyright (c) 2014-2016 Pacman Development Team <pacman-dev at archlinux.org>
+#
+#   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 2 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 <http://www.gnu.org/licenses/>.
+#
+
+[[ -n "$LIBMAKEPKG_INTEGRITY_GENERATE_CHECKSUM_SH" ]] && return
+LIBMAKEPKG_INTEGRITY_GENERATE_CHECKSUM_SH=1
+
+LIBRARY=${LIBRARY:-'@libmakepkgdir@'}
+
+source "$LIBRARY/util/message.sh"
+source "$LIBRARY/util/pkgbuild.sh"
+
+generate_one_checksum() {
+	local integ=$1 arch=$2 sources numsrc indentsz idx
+
+	if [[ $arch ]]; then
+		array_build sources "source_$arch"
+	else
+		array_build sources 'source'
+	fi
+
+	numsrc=${#sources[*]}
+	if (( numsrc == 0 )); then
+		return
+	fi
+
+	if [[ $arch ]]; then
+		printf "%ssums_%s=(%n" "$integ" "$arch" indentsz
+	else
+		printf "%ssums=(%n" "$integ" indentsz
+	fi
+
+	for (( idx = 0; idx < numsrc; ++idx )); do
+		local netfile=${sources[idx]}
+		local proto sum
+		proto="$(get_protocol "$netfile")"
+
+		case $proto in
+			bzr*|git*|hg*|svn*)
+				sum="SKIP"
+				;;
+			*)
+				if [[ $netfile != *.@(sig?(n)|asc) ]]; then
+					local file
+					file="$(get_filepath "$netfile")" || missing_source_file "$netfile"
+					sum="$(openssl dgst -${integ} "$file")"
+					sum=${sum##* }
+				else
+					sum="SKIP"
+				fi
+				;;
+		esac
+
+		# indent checksum on lines after the first
+		printf "%*s%s" $(( idx ? indentsz : 0 )) '' "'$sum'"
+
+		# print a newline on lines before the last
+		(( idx < (numsrc - 1) )) && echo
+	done
+
+	echo ")"
+}
+
+generate_checksums() {
+	msg "$(gettext "Generating checksums for source files...")"
+
+	if ! type -p openssl >/dev/null; then
+		error "$(gettext "Cannot find the %s binary required for generating sourcefile checksums.")" "openssl"
+		exit 1 # $E_MISSING_PROGRAM
+	fi
+
+	local integlist
+	if (( $# == 0 )); then
+		IFS=$'\n' read -rd '' -a integlist < <(get_integlist)
+	else
+		integlist=("$@")
+	fi
+
+	local integ
+	for integ in "${integlist[@]}"; do
+		if ! in_array "$integ" "${known_hash_algos[@]}"; then
+			error "$(gettext "Invalid integrity algorithm '%s' specified.")" "$integ"
+			exit 1 # $E_CONFIG_ERROR
+		fi
+
+		generate_one_checksum "$integ"
+		for a in "${arch[@]}"; do
+			generate_one_checksum "$integ" "$a"
+		done
+	done
+}
diff --git a/scripts/libmakepkg/integrity/generate_signature.sh.in b/scripts/libmakepkg/integrity/generate_signature.sh.in
new file mode 100644
index 0000000..d7f7cb1
--- /dev/null
+++ b/scripts/libmakepkg/integrity/generate_signature.sh.in
@@ -0,0 +1,49 @@
+#!/bin/bash
+#
+#   generate_signature.sh - functions for generating PGP signatures
+#
+#   Copyright (c) 2008-2016 Pacman Development Team <pacman-dev at archlinux.org>
+#
+#   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 2 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 <http://www.gnu.org/licenses/>.
+#
+
+[[ -n "$LIBMAKEPKG_INTEGRITY_GENERATE_SIGNATURE_SH" ]] && return
+LIBMAKEPKG_INTEGRITY_GENERATE_SIGNATURE_SH=1
+
+LIBRARY=${LIBRARY:-'@libmakepkgdir@'}
+
+source "$LIBRARY/util/message.sh"
+
+create_signature() {
+	if [[ $SIGNPKG != 'y' ]]; then
+		return
+	fi
+	local ret=0
+	local filename="$1"
+	msg "$(gettext "Signing package...")"
+
+	local SIGNWITHKEY=""
+	if [[ -n $GPGKEY ]]; then
+		SIGNWITHKEY="-u ${GPGKEY}"
+	fi
+
+	gpg --detach-sign --use-agent ${SIGNWITHKEY} --no-armor "$filename" &>/dev/null || ret=$?
+
+
+	if (( ! ret )); then
+		msg2 "$(gettext "Created signature file %s.")" "$filename.sig"
+	else
+		warning "$(gettext "Failed to sign package file.")"
+	fi
+}
diff --git a/scripts/libmakepkg/integrity/verify_checksum.sh.in b/scripts/libmakepkg/integrity/verify_checksum.sh.in
new file mode 100644
index 0000000..44a2b2e
--- /dev/null
+++ b/scripts/libmakepkg/integrity/verify_checksum.sh.in
@@ -0,0 +1,130 @@
+#!/bin/bash
+#
+#   verify_checksum.sh - functions for checking source checksums
+#
+#   Copyright (c) 2014-2016 Pacman Development Team <pacman-dev at archlinux.org>
+#
+#   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 2 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 <http://www.gnu.org/licenses/>.
+#
+
+[[ -n "$LIBMAKEPKG_INTEGRITY_VERIFY_CHECKSUM_SH" ]] && return
+LIBMAKEPKG_INTEGRITY_CHECKSUM_SH=1
+
+LIBRARY=${LIBRARY:-'@libmakepkgdir@'}
+
+source "$LIBRARY/util/message.sh"
+source "$LIBRARY/util/pkgbuild.sh"
+
+check_checksums() {
+	local integ a
+	declare -A correlation
+	(( SKIPCHECKSUMS )) && return 0
+
+	# Initialize a map which we'll use to verify that every source array has at
+	# least some kind of checksum array associated with it.
+	(( ${#source[*]} )) && correlation['source']=1
+	case $1 in
+		all)
+			for a in "${arch[@]}"; do
+				array_build _ source_"$a" && correlation["source_$a"]=1
+			done
+			;;
+		*)
+			array_build _ source_"$CARCH" && correlation["source_$CARCH"]=1
+			;;
+	esac
+
+	for integ in "${known_hash_algos[@]}"; do
+		verify_integrity_sums "$integ" && unset "correlation[source]"
+
+		case $1 in
+			all)
+				for a in "${arch[@]}"; do
+					verify_integrity_sums "$integ" "$a" && unset "correlation[source_$a]"
+				done
+				;;
+			*)
+				verify_integrity_sums "$integ" "$CARCH" && unset "correlation[source_$CARCH]"
+				;;
+		esac
+	done
+
+	if (( ${#correlation[*]} )); then
+		error "$(gettext "Integrity checks are missing for: %s")" "${!correlation[*]}"
+		exit 1 # TODO: error code
+	fi
+}
+
+verify_integrity_one() {
+	local source_name=$1 integ=$2 expectedsum=$3
+
+	local file="$(get_filename "$source_name")"
+	printf '    %s ... ' "$file" >&2
+
+	if [[ $expectedsum = 'SKIP' ]]; then
+		printf '%s\n' "$(gettext "Skipped")" >&2
+		return
+	fi
+
+	if ! file="$(get_filepath "$file")"; then
+		printf '%s\n' "$(gettext "NOT FOUND")" >&2
+		return 1
+	fi
+
+	local realsum="$(openssl dgst -${integ} "$file")"
+	realsum="${realsum##* }"
+	if [[ ${expectedsum,,} = "$realsum" ]]; then
+		printf '%s\n' "$(gettext "Passed")" >&2
+	else
+		printf '%s\n' "$(gettext "FAILED")" >&2
+		return 1
+	fi
+
+	return 0
+}
+
+verify_integrity_sums() {
+	local integ=$1 arch=$2 integrity_sums=() sources=() srcname
+
+	if [[ $arch ]]; then
+		array_build integrity_sums "${integ}sums_$arch"
+		srcname=source_$arch
+	else
+		array_build integrity_sums "${integ}sums"
+		srcname=source
+	fi
+
+	array_build sources "$srcname"
+	if (( ${#integrity_sums[@]} == 0 && ${#sources[@]} == 0 )); then
+		return 1
+	fi
+
+	if (( ${#integrity_sums[@]} == ${#sources[@]} )); then
+		msg "$(gettext "Validating %s files with %s...")" "$srcname" "${integ}sums"
+		local idx errors=0
+		for (( idx = 0; idx < ${#sources[*]}; idx++ )); do
+			verify_integrity_one "${sources[idx]}" "$integ" "${integrity_sums[idx]}" || errors=1
+		done
+
+		if (( errors )); then
+			error "$(gettext "One or more files did not pass the validity check!")"
+			exit 1 # TODO: error code
+		fi
+	elif (( ${#integrity_sums[@]} )); then
+		error "$(gettext "Integrity checks (%s) differ in size from the source array.")" "$integ"
+		exit 1 # TODO: error code
+	else
+		return 1
+	fi
+}
diff --git a/scripts/libmakepkg/integrity/verify_signature.sh.in b/scripts/libmakepkg/integrity/verify_signature.sh.in
new file mode 100644
index 0000000..6df6272
--- /dev/null
+++ b/scripts/libmakepkg/integrity/verify_signature.sh.in
@@ -0,0 +1,216 @@
+#!/bin/bash
+#
+#   verify_signature.sh - functions for checking PGP signatures
+#
+#   Copyright (c) 2011-2016 Pacman Development Team <pacman-dev at archlinux.org>
+#
+#   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 2 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 <http://www.gnu.org/licenses/>.
+#
+
+[[ -n "$LIBMAKEPKG_INTEGRITY_VERIFY_SIGNATURE_SH" ]] && return
+LIBMAKEPKG_INTEGRITY_VERIFY_SIGNATURE_SH=1
+
+LIBRARY=${LIBRARY:-'@libmakepkgdir@'}
+
+source "$LIBRARY/util/message.sh"
+source "$LIBRARY/util/pkgbuild.sh"
+
+check_pgpsigs() {
+	(( SKIPPGPCHECK )) && return 0
+	! source_has_signatures && return 0
+
+	msg "$(gettext "Verifying source file signatures with %s...")" "gpg"
+
+	local file ext decompress found pubkey success status fingerprint trusted
+	local warning=0
+	local errors=0
+	local statusfile=$(mktemp)
+	local all_sources
+
+	case $1 in
+		all)
+			get_all_sources 'all_sources'
+			;;
+		*)
+			get_all_sources_for_arch 'all_sources'
+			;;
+	esac
+	for file in "${all_sources[@]}"; do
+		file="$(get_filename "$file")"
+		if [[ $file != *.@(sig?(n)|asc) ]]; then
+			continue
+		fi
+
+		printf "    %s ... " "${file%.*}" >&2
+
+		if ! file="$(get_filepath "$file")"; then
+			printf '%s\n' "$(gettext "SIGNATURE NOT FOUND")" >&2
+			errors=1
+			continue
+		fi
+
+		found=0
+		for ext in "" gz bz2 xz lrz lzo Z; do
+			if sourcefile="$(get_filepath "${file%.*}${ext:+.$ext}")"; then
+				found=1
+				break;
+			fi
+		done
+		if (( ! found )); then
+			printf '%s\n' "$(gettext "SOURCE FILE NOT FOUND")" >&2
+			errors=1
+			continue
+		fi
+
+		case "$ext" in
+			gz)  decompress="gzip -c -d -f" ;;
+			bz2) decompress="bzip2 -c -d -f" ;;
+			xz)  decompress="xz -c -d" ;;
+			lrz) decompress="lrzip -q -d" ;;
+			lzo) decompress="lzop -c -d -q" ;;
+			Z)   decompress="uncompress -c -f" ;;
+			"")  decompress="cat" ;;
+		esac
+
+		$decompress < "$sourcefile" | gpg --quiet --batch --status-file "$statusfile" --verify "$file" - 2> /dev/null
+		# these variables are assigned values in parse_gpg_statusfile
+		success=0
+		status=
+		pubkey=
+		fingerprint=
+		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
+			errors=1
+		else
+			if (( ${#validpgpkeys[@]} == 0 && !trusted )); then
+				printf "%s ($(gettext "the public key %s is not trusted"))" $(gettext "FAILED") "$fingerprint" >&2
+				errors=1
+			elif (( ${#validpgpkeys[@]} > 0 )) && ! in_array "$fingerprint" "${validpgpkeys[@]}"; then
+				printf "%s (%s %s)" "$(gettext "FAILED")" "$(gettext "invalid public key")" "$fingerprint"
+				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
+			fi
+		fi
+		printf '\n' >&2
+	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
+}
+
+parse_gpg_statusfile() {
+	local type arg1 arg6 arg10
+
+	while read -r _ type arg1 _ _ _ _ arg6 _ _ _ arg10 _; do
+		case "$type" in
+			GOODSIG)
+				pubkey=$arg1
+				success=1
+				status="good"
+				;;
+			EXPSIG)
+				pubkey=$arg1
+				success=1
+				status="expired"
+				;;
+			EXPKEYSIG)
+				pubkey=$arg1
+				success=1
+				status="expiredkey"
+				;;
+			REVKEYSIG)
+				pubkey=$arg1
+				success=0
+				status="revokedkey"
+				;;
+			BADSIG)
+				pubkey=$arg1
+				success=0
+				status="bad"
+				;;
+			ERRSIG)
+				pubkey=$arg1
+				success=0
+				if [[ $arg6 == 9 ]]; then
+					status="missingkey"
+				else
+					status="error"
+				fi
+				;;
+			VALIDSIG)
+				if [[ $arg10 ]]; then
+					# If the file was signed with a subkey, arg10 contains
+					# the fingerprint of the primary key
+					fingerprint=$arg10
+				else
+					fingerprint=$arg1
+				fi
+				;;
+			TRUST_UNDEFINED|TRUST_NEVER)
+				trusted=0
+				;;
+			TRUST_MARGINAL|TRUST_FULLY|TRUST_ULTIMATE)
+				trusted=1
+				;;
+		esac
+	done < "$1"
+}
+
+source_has_signatures() {
+	local file all_sources
+
+	get_all_sources_for_arch 'all_sources'
+	for file in "${all_sources[@]}"; do
+		if [[ ${file%%::*} = *.@(sig?(n)|asc) ]]; then
+			return 0
+		fi
+	done
+	return 1
+}
diff --git a/scripts/libmakepkg/util/pkgbuild.sh.in b/scripts/libmakepkg/util/pkgbuild.sh.in
index 51d8732..1a4567d 100644
--- a/scripts/libmakepkg/util/pkgbuild.sh.in
+++ b/scripts/libmakepkg/util/pkgbuild.sh.in
@@ -2,7 +2,7 @@
 #
 #   pkgbuild.sh - functions to extract information from PKGBUILD files
 #
-#   Copyright (c) 2014-2016 Pacman Development Team <pacman-dev at archlinux.org>
+#   Copyright (c) 2009-2016 Pacman Development Team <pacman-dev at archlinux.org>
 #
 #   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
@@ -189,3 +189,21 @@ get_all_sources_for_arch() {
 
 	array_build "$1" "aggregate"
 }
+
+get_integlist() {
+	local integ
+	local integlist=()
+
+	for integ in "${known_hash_algos[@]}"; do
+		local sumname="${integ}sums[@]"
+		if [[ -n ${!sumname} ]]; then
+			integlist+=("$integ")
+		fi
+	done
+
+	if (( ${#integlist[@]} > 0 )); then
+		printf "%s\n" "${integlist[@]}"
+	else
+		printf "%s\n" "${INTEGRITY_CHECK[@]}"
+	fi
+}
diff --git a/scripts/makepkg.sh.in b/scripts/makepkg.sh.in
index f80e37a..837dc85 100644
--- a/scripts/makepkg.sh.in
+++ b/scripts/makepkg.sh.in
@@ -204,18 +204,6 @@ missing_source_file() {
 	exit 1 # $E_MISSING_FILE
 }
 
-source_has_signatures() {
-	local file all_sources
-
-	get_all_sources_for_arch 'all_sources'
-	for file in "${all_sources[@]}"; do
-		if [[ ${file%%::*} = *.@(sig?(n)|asc) ]]; then
-			return 0
-		fi
-	done
-	return 1
-}
-
 run_pacman() {
 	local cmd
 	if [[ $1 != -@(T|Qq) ]]; then
@@ -332,399 +320,6 @@ remove_deps() {
 	fi
 }
 
-get_integlist() {
-	local integ
-	local integlist=()
-
-	for integ in "${known_hash_algos[@]}"; do
-		local sumname="${integ}sums[@]"
-		if [[ -n ${!sumname} ]]; then
-			integlist+=("$integ")
-		fi
-	done
-
-	if (( ${#integlist[@]} > 0 )); then
-		printf "%s\n" "${integlist[@]}"
-	else
-		printf "%s\n" "${INTEGRITY_CHECK[@]}"
-	fi
-}
-
-generate_one_checksum() {
-	local integ=$1 arch=$2 sources numsrc indentsz idx
-
-	if [[ $arch ]]; then
-		array_build sources "source_$arch"
-	else
-		array_build sources 'source'
-	fi
-
-	numsrc=${#sources[*]}
-	if (( numsrc == 0 )); then
-		return
-	fi
-
-	if [[ $arch ]]; then
-		printf "%ssums_%s=(%n" "$integ" "$arch" indentsz
-	else
-		printf "%ssums=(%n" "$integ" indentsz
-	fi
-
-	for (( idx = 0; idx < numsrc; ++idx )); do
-		local netfile=${sources[idx]}
-		local proto sum
-		proto="$(get_protocol "$netfile")"
-
-		case $proto in
-			bzr*|git*|hg*|svn*)
-				sum="SKIP"
-				;;
-			*)
-				if [[ $netfile != *.@(sig?(n)|asc) ]]; then
-					local file
-					file="$(get_filepath "$netfile")" || missing_source_file "$netfile"
-					sum="$(openssl dgst -${integ} "$file")"
-					sum=${sum##* }
-				else
-					sum="SKIP"
-				fi
-				;;
-		esac
-
-		# indent checksum on lines after the first
-		printf "%*s%s" $(( idx ? indentsz : 0 )) '' "'$sum'"
-
-		# print a newline on lines before the last
-		(( idx < (numsrc - 1) )) && echo
-	done
-
-	echo ")"
-}
-
-generate_checksums() {
-	msg "$(gettext "Generating checksums for source files...")"
-
-	if ! type -p openssl >/dev/null; then
-		error "$(gettext "Cannot find the %s binary required for generating sourcefile checksums.")" "openssl"
-		exit 1 # $E_MISSING_PROGRAM
-	fi
-
-	local integlist
-	if (( $# == 0 )); then
-		IFS=$'\n' read -rd '' -a integlist < <(get_integlist)
-	else
-		integlist=("$@")
-	fi
-
-	local integ
-	for integ in "${integlist[@]}"; do
-		if ! in_array "$integ" "${known_hash_algos[@]}"; then
-			error "$(gettext "Invalid integrity algorithm '%s' specified.")" "$integ"
-			exit 1 # $E_CONFIG_ERROR
-		fi
-
-		generate_one_checksum "$integ"
-		for a in "${arch[@]}"; do
-			generate_one_checksum "$integ" "$a"
-		done
-	done
-}
-
-verify_integrity_one() {
-	local source_name=$1 integ=$2 expectedsum=$3
-
-	local file="$(get_filename "$source_name")"
-	printf '    %s ... ' "$file" >&2
-
-	if [[ $expectedsum = 'SKIP' ]]; then
-		printf '%s\n' "$(gettext "Skipped")" >&2
-		return
-	fi
-
-	if ! file="$(get_filepath "$file")"; then
-		printf '%s\n' "$(gettext "NOT FOUND")" >&2
-		return 1
-	fi
-
-	local realsum="$(openssl dgst -${integ} "$file")"
-	realsum="${realsum##* }"
-	if [[ ${expectedsum,,} = "$realsum" ]]; then
-		printf '%s\n' "$(gettext "Passed")" >&2
-	else
-		printf '%s\n' "$(gettext "FAILED")" >&2
-		return 1
-	fi
-
-	return 0
-}
-
-verify_integrity_sums() {
-	local integ=$1 arch=$2 integrity_sums=() sources=() srcname
-
-	if [[ $arch ]]; then
-		array_build integrity_sums "${integ}sums_$arch"
-		srcname=source_$arch
-	else
-		array_build integrity_sums "${integ}sums"
-		srcname=source
-	fi
-
-	array_build sources "$srcname"
-	if (( ${#integrity_sums[@]} == 0 && ${#sources[@]} == 0 )); then
-		return 1
-	fi
-
-	if (( ${#integrity_sums[@]} == ${#sources[@]} )); then
-		msg "$(gettext "Validating %s files with %s...")" "$srcname" "${integ}sums"
-		local idx errors=0
-		for (( idx = 0; idx < ${#sources[*]}; idx++ )); do
-			verify_integrity_one "${sources[idx]}" "$integ" "${integrity_sums[idx]}" || errors=1
-		done
-
-		if (( errors )); then
-			error "$(gettext "One or more files did not pass the validity check!")"
-			exit 1 # TODO: error code
-		fi
-	elif (( ${#integrity_sums[@]} )); then
-		error "$(gettext "Integrity checks (%s) differ in size from the source array.")" "$integ"
-		exit 1 # TODO: error code
-	else
-		return 1
-	fi
-}
-
-check_checksums() {
-	local integ a
-	declare -A correlation
-	(( SKIPCHECKSUMS )) && return 0
-
-	# Initialize a map which we'll use to verify that every source array has at
-	# least some kind of checksum array associated with it.
-	(( ${#source[*]} )) && correlation['source']=1
-	case $1 in
-		all)
-			for a in "${arch[@]}"; do
-				array_build _ source_"$a" && correlation["source_$a"]=1
-			done
-			;;
-		*)
-			array_build _ source_"$CARCH" && correlation["source_$CARCH"]=1
-			;;
-	esac
-
-	for integ in "${known_hash_algos[@]}"; do
-		verify_integrity_sums "$integ" && unset "correlation[source]"
-
-		case $1 in
-			all)
-				for a in "${arch[@]}"; do
-					verify_integrity_sums "$integ" "$a" && unset "correlation[source_$a]"
-				done
-				;;
-			*)
-				verify_integrity_sums "$integ" "$CARCH" && unset "correlation[source_$CARCH]"
-				;;
-		esac
-	done
-
-	if (( ${#correlation[*]} )); then
-		error "$(gettext "Integrity checks are missing for: %s")" "${!correlation[*]}"
-		exit 1 # TODO: error code
-	fi
-}
-
-parse_gpg_statusfile() {
-	local type arg1 arg6 arg10
-
-	while read -r _ type arg1 _ _ _ _ arg6 _ _ _ arg10 _; do
-		case "$type" in
-			GOODSIG)
-				pubkey=$arg1
-				success=1
-				status="good"
-				;;
-			EXPSIG)
-				pubkey=$arg1
-				success=1
-				status="expired"
-				;;
-			EXPKEYSIG)
-				pubkey=$arg1
-				success=1
-				status="expiredkey"
-				;;
-			REVKEYSIG)
-				pubkey=$arg1
-				success=0
-				status="revokedkey"
-				;;
-			BADSIG)
-				pubkey=$arg1
-				success=0
-				status="bad"
-				;;
-			ERRSIG)
-				pubkey=$arg1
-				success=0
-				if [[ $arg6 == 9 ]]; then
-					status="missingkey"
-				else
-					status="error"
-				fi
-				;;
-			VALIDSIG)
-				if [[ $arg10 ]]; then
-					# If the file was signed with a subkey, arg10 contains
-					# the fingerprint of the primary key
-					fingerprint=$arg10
-				else
-					fingerprint=$arg1
-				fi
-				;;
-			TRUST_UNDEFINED|TRUST_NEVER)
-				trusted=0
-				;;
-			TRUST_MARGINAL|TRUST_FULLY|TRUST_ULTIMATE)
-				trusted=1
-				;;
-		esac
-	done < "$1"
-}
-
-check_pgpsigs() {
-	(( SKIPPGPCHECK )) && return 0
-	! source_has_signatures && return 0
-
-	msg "$(gettext "Verifying source file signatures with %s...")" "gpg"
-
-	local file ext decompress found pubkey success status fingerprint trusted
-	local warning=0
-	local errors=0
-	local statusfile=$(mktemp)
-	local all_sources
-
-	case $1 in
-		all)
-			get_all_sources 'all_sources'
-			;;
-		*)
-			get_all_sources_for_arch 'all_sources'
-			;;
-	esac
-	for file in "${all_sources[@]}"; do
-		file="$(get_filename "$file")"
-		if [[ $file != *.@(sig?(n)|asc) ]]; then
-			continue
-		fi
-
-		printf "    %s ... " "${file%.*}" >&2
-
-		if ! file="$(get_filepath "$file")"; then
-			printf '%s\n' "$(gettext "SIGNATURE NOT FOUND")" >&2
-			errors=1
-			continue
-		fi
-
-		found=0
-		for ext in "" gz bz2 xz lrz lzo Z; do
-			if sourcefile="$(get_filepath "${file%.*}${ext:+.$ext}")"; then
-				found=1
-				break;
-			fi
-		done
-		if (( ! found )); then
-			printf '%s\n' "$(gettext "SOURCE FILE NOT FOUND")" >&2
-			errors=1
-			continue
-		fi
-
-		case "$ext" in
-			gz)  decompress="gzip -c -d -f" ;;
-			bz2) decompress="bzip2 -c -d -f" ;;
-			xz)  decompress="xz -c -d" ;;
-			lrz) decompress="lrzip -q -d" ;;
-			lzo) decompress="lzop -c -d -q" ;;
-			Z)   decompress="uncompress -c -f" ;;
-			"")  decompress="cat" ;;
-		esac
-
-		$decompress < "$sourcefile" | gpg --quiet --batch --status-file "$statusfile" --verify "$file" - 2> /dev/null
-		# these variables are assigned values in parse_gpg_statusfile
-		success=0
-		status=
-		pubkey=
-		fingerprint=
-		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
-			errors=1
-		else
-			if (( ${#validpgpkeys[@]} == 0 && !trusted )); then
-				printf "%s ($(gettext "the public key %s is not trusted"))" $(gettext "FAILED") "$fingerprint" >&2
-				errors=1
-			elif (( ${#validpgpkeys[@]} > 0 )) && ! in_array "$fingerprint" "${validpgpkeys[@]}"; then
-				printf "%s (%s %s)" "$(gettext "FAILED")" "$(gettext "invalid public key")" "$fingerprint"
-				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
-			fi
-		fi
-		printf '\n' >&2
-	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
-}
-
-check_source_integrity() {
-	if (( SKIPCHECKSUMS && SKIPPGPCHECK )); then
-		warning "$(gettext "Skipping all source file integrity checks.")"
-	elif (( SKIPCHECKSUMS )); then
-		warning "$(gettext "Skipping verification of source file checksums.")"
-		check_pgpsigs "$@"
-	elif (( SKIPPGPCHECK )); then
-		warning "$(gettext "Skipping verification of source file PGP signatures.")"
-		check_checksums "$@"
-	else
-		check_checksums "$@"
-		check_pgpsigs "$@"
-	fi
-}
-
 error_function() {
 	if [[ -p $logpipe ]]; then
 		rm "$logpipe"
@@ -1189,29 +784,6 @@ create_debug_package() {
 	create_package
 }
 
-create_signature() {
-	if [[ $SIGNPKG != 'y' ]]; then
-		return
-	fi
-	local ret=0
-	local filename="$1"
-	msg "$(gettext "Signing package...")"
-
-	local SIGNWITHKEY=""
-	if [[ -n $GPGKEY ]]; then
-		SIGNWITHKEY="-u ${GPGKEY}"
-	fi
-
-	gpg --detach-sign --use-agent ${SIGNWITHKEY} --no-armor "$filename" &>/dev/null || ret=$?
-
-
-	if (( ! ret )); then
-		msg2 "$(gettext "Created signature file %s.")" "$filename.sig"
-	else
-		warning "$(gettext "Failed to sign package file.")"
-	fi
-}
-
 create_srcpackage() {
 	local ret=0
 	msg "$(gettext "Creating source package...")"
diff --git a/scripts/po/POTFILES.in b/scripts/po/POTFILES.in
index d115d89..0240ad9 100644
--- a/scripts/po/POTFILES.in
+++ b/scripts/po/POTFILES.in
@@ -8,6 +8,11 @@ scripts/pacman-key.sh.in
 scripts/pacman-optimize.sh.in
 scripts/pkgdelta.sh.in
 scripts/repo-add.sh.in
+scripts/libmakepkg/integrity.sh
+scripts/libmakepkg/integrity/generate_checksum.sh
+scripts/libmakepkg/integrity/generate_signature.sh
+scripts/libmakepkg/integrity/verify_checksum.sh
+scripts/libmakepkg/integrity/verify_signature.sh
 scripts/libmakepkg/lint_package.sh.in
 scripts/libmakepkg/lint_package/build_references.sh.in
 scripts/libmakepkg/lint_package/missing_backup.sh.in
-- 
2.8.0


More information about the pacman-dev mailing list