[pacman-dev] [PATCH v3 2/3] makepkg: Verify git signatures

Eli Schwartz eschwartz93 at gmail.com
Tue Jan 3 20:10:18 UTC 2017


A git repository is marked as signed if it contains the query "signed"
as defined by https://tools.ietf.org/html/rfc3986

Adds two utility functions in util/source.sh.in to extract fragments and
queries, and modifies source/git.sh.in to use them.

Signed-off-by: Eli Schwartz <eschwartz93 at gmail.com>
---
 .../libmakepkg/integrity/verify_signature.sh.in    | 53 ++++++++++++++++++++--
 scripts/libmakepkg/source/git.sh.in                | 11 ++---
 scripts/libmakepkg/util/source.sh.in               | 27 +++++++++++
 3 files changed, 79 insertions(+), 12 deletions(-)

diff --git a/scripts/libmakepkg/integrity/verify_signature.sh.in b/scripts/libmakepkg/integrity/verify_signature.sh.in
index 6ffc6df4..7cce58ee 100644
--- a/scripts/libmakepkg/integrity/verify_signature.sh.in
+++ b/scripts/libmakepkg/integrity/verify_signature.sh.in
@@ -32,7 +32,7 @@ check_pgpsigs() {
 
 	msg "$(gettext "Verifying source file signatures with %s...")" "gpg"
 
-	local netfile pubkey success status fingerprint trusted
+	local netfile proto pubkey success status fingerprint trusted
 	local warning=0
 	local errors=0
 	local statusfile=$(mktemp)
@@ -47,7 +47,13 @@ check_pgpsigs() {
 			;;
 	esac
 	for netfile in "${all_sources[@]}"; do
-		verify_file_signature "$netfile" "$statusfile" || continue
+		proto="$(get_protocol "$netfile")"
+
+		if [[ $proto = git* ]]; then
+			verify_git_signature "$netfile" "$statusfile" || continue
+		else
+			verify_file_signature "$netfile" "$statusfile" || continue
+		fi
 
 		# these variables are assigned values in parse_gpg_statusfile
 		success=0
@@ -153,6 +159,42 @@ verify_file_signature() {
 	$decompress < "$sourcefile" | gpg --quiet --batch --status-file "$statusfile" --verify "$file" - 2> /dev/null
 }
 
+verify_git_signature() {
+	local netfile=$1 statusfile=$2
+	local dir fragment query fragtype fragval
+
+	dir=$(get_filepath "$netfile")
+	fragment=$(get_uri_fragment "$netfile")
+	query=$(get_uri_query "$netfile")
+
+	if [[ $query != signed ]]; then
+		return 1
+	fi
+
+	case ${fragment%%=*} in
+		tag)
+			fragtype=tag
+			fragval=${fragment##*=}
+			;;
+		commit|branch)
+			fragtype=commit
+			fragval=${fragment##*=}
+			;;
+		'')
+			fragtype=commit
+			fragval=HEAD
+	esac
+
+	printf "    %s git repo ... " "${dir##*/}" >&2
+
+	git -C "$dir" verify-$fragtype --raw "$fragval" > "$statusfile" 2>&1
+	if ! grep -qs NEWSIG "$statusfile"; then
+		printf '%s\n' "$(gettext "SIGNATURE NOT FOUND")" >&2
+		errors=1
+		return 1
+	fi
+}
+
 parse_gpg_statusfile() {
 	local type arg1 arg6 arg10
 
@@ -212,11 +254,14 @@ parse_gpg_statusfile() {
 }
 
 source_has_signatures() {
-	local file all_sources
+	local file all_sources proto
 
 	get_all_sources_for_arch 'all_sources'
 	for file in "${all_sources[@]}"; do
-		if [[ ${file%%::*} = *.@(sig?(n)|asc) ]]; then
+		proto="$(get_protocol "$file")"
+		query=$(get_uri_query "$netfile")
+
+		if [[ ${file%%::*} = *.@(sig?(n)|asc) || ( $proto = git* && $query = signed ) ]]; then
 			return 0
 		fi
 	done
diff --git a/scripts/libmakepkg/source/git.sh.in b/scripts/libmakepkg/source/git.sh.in
index cc27663d..3d370dbd 100644
--- a/scripts/libmakepkg/source/git.sh.in
+++ b/scripts/libmakepkg/source/git.sh.in
@@ -39,6 +39,7 @@ download_git() {
 	local url=$(get_url "$netfile")
 	url=${url#git+}
 	url=${url%%#*}
+	url=${url%%\?*}
 
 	if [[ ! -d "$dir" ]] || dir_is_empty "$dir" ; then
 		msg2 "$(gettext "Cloning %s %s repo...")" "${repo}" "git"
@@ -66,14 +67,8 @@ download_git() {
 extract_git() {
 	local netfile=$1
 
-	local fragment=${netfile#*#}
-	if [[ $fragment = "$netfile" ]]; then
-		unset fragment
-	fi
-
-	local repo=${netfile##*/}
-	repo=${repo%%#*}
-	repo=${repo%%.git*}
+	local fragment=$(get_uri_fragment "$netfile")
+	local repo=$(get_filename "$netfile")
 
 	local dir=$(get_filepath "$netfile")
 	[[ -z "$dir" ]] && dir="$SRCDEST/$(get_filename "$netfile")"
diff --git a/scripts/libmakepkg/util/source.sh.in b/scripts/libmakepkg/util/source.sh.in
index 9d4ba4a6..bbe3e927 100644
--- a/scripts/libmakepkg/util/source.sh.in
+++ b/scripts/libmakepkg/util/source.sh.in
@@ -65,6 +65,7 @@ get_filename() {
 	case $proto in
 		bzr*|git*|hg*|svn*)
 			filename=${netfile%%#*}
+			filename=${filename%%\?*}
 			filename=${filename%/}
 			filename=${filename##*/}
 			if [[ $proto = bzr* ]]; then
@@ -111,6 +112,32 @@ get_filepath() {
 	printf "%s\n" "$file"
 }
 
+# extract the VCS revision/branch specifier from a source entry
+get_uri_fragment() {
+	local netfile=$1
+
+	local fragment=${netfile#*#}
+	if [[ $fragment = "$netfile" ]]; then
+		unset fragment
+	fi
+	fragment=${fragment%\?*}
+
+	printf "%s\n" "$fragment"
+}
+
+# extract the VCS "signed" status from a source entry
+get_uri_query() {
+	local netfile=$1
+
+	local query=${netfile#*\?}
+	if [[ $query = "$netfile" ]]; then
+		unset query
+	fi
+	query=${query%#*}
+
+	printf "%s\n" "$query"
+}
+
 get_downloadclient() {
 	local proto=$1
 
-- 
2.11.0


More information about the pacman-dev mailing list