makepkg: Verify git signatures

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@gmail.com>
Signed-off-by: Allan McRae <allan@archlinux.org>
This commit is contained in:
Eli Schwartz 2017-01-03 15:10:18 -05:00 committed by Allan McRae
parent 42e7020281
commit eaa82b4d07
3 changed files with 79 additions and 12 deletions

View file

@ -32,7 +32,7 @@ check_pgpsigs() {
msg "$(gettext "Verifying source file signatures with %s...")" "gpg" 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 warning=0
local errors=0 local errors=0
local statusfile=$(mktemp) local statusfile=$(mktemp)
@ -47,7 +47,13 @@ check_pgpsigs() {
;; ;;
esac esac
for netfile in "${all_sources[@]}"; do for netfile in "${all_sources[@]}"; do
proto="$(get_protocol "$netfile")"
if [[ $proto = git* ]]; then
verify_git_signature "$netfile" "$statusfile" || continue
else
verify_file_signature "$netfile" "$statusfile" || continue verify_file_signature "$netfile" "$statusfile" || continue
fi
# these variables are assigned values in parse_gpg_statusfile # these variables are assigned values in parse_gpg_statusfile
success=0 success=0
@ -153,6 +159,42 @@ verify_file_signature() {
$decompress < "$sourcefile" | gpg --quiet --batch --status-file "$statusfile" --verify "$file" - 2> /dev/null $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() { parse_gpg_statusfile() {
local type arg1 arg6 arg10 local type arg1 arg6 arg10
@ -212,11 +254,14 @@ parse_gpg_statusfile() {
} }
source_has_signatures() { source_has_signatures() {
local file all_sources local file all_sources proto
get_all_sources_for_arch 'all_sources' get_all_sources_for_arch 'all_sources'
for file in "${all_sources[@]}"; do 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 return 0
fi fi
done done

View file

@ -39,6 +39,7 @@ download_git() {
local url=$(get_url "$netfile") local url=$(get_url "$netfile")
url=${url#git+} url=${url#git+}
url=${url%%#*} url=${url%%#*}
url=${url%%\?*}
if [[ ! -d "$dir" ]] || dir_is_empty "$dir" ; then if [[ ! -d "$dir" ]] || dir_is_empty "$dir" ; then
msg2 "$(gettext "Cloning %s %s repo...")" "${repo}" "git" msg2 "$(gettext "Cloning %s %s repo...")" "${repo}" "git"
@ -66,14 +67,8 @@ download_git() {
extract_git() { extract_git() {
local netfile=$1 local netfile=$1
local fragment=${netfile#*#} local fragment=$(get_uri_fragment "$netfile")
if [[ $fragment = "$netfile" ]]; then local repo=$(get_filename "$netfile")
unset fragment
fi
local repo=${netfile##*/}
repo=${repo%%#*}
repo=${repo%%.git*}
local dir=$(get_filepath "$netfile") local dir=$(get_filepath "$netfile")
[[ -z "$dir" ]] && dir="$SRCDEST/$(get_filename "$netfile")" [[ -z "$dir" ]] && dir="$SRCDEST/$(get_filename "$netfile")"

View file

@ -65,6 +65,7 @@ get_filename() {
case $proto in case $proto in
bzr*|git*|hg*|svn*) bzr*|git*|hg*|svn*)
filename=${netfile%%#*} filename=${netfile%%#*}
filename=${filename%%\?*}
filename=${filename%/} filename=${filename%/}
filename=${filename##*/} filename=${filename##*/}
if [[ $proto = bzr* ]]; then if [[ $proto = bzr* ]]; then
@ -111,6 +112,32 @@ get_filepath() {
printf "%s\n" "$file" 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() { get_downloadclient() {
local proto=$1 local proto=$1