[pacman-dev] [PATCH] makepkg: Verify git signatures
Eli Schwartz
eschwartz93 at gmail.com
Fri Dec 16 18:56:36 UTC 2016
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 | 56 ++++++++++++++++++----
scripts/libmakepkg/source/git.sh.in | 11 ++---
scripts/libmakepkg/util/source.sh.in | 27 +++++++++++
3 files changed, 76 insertions(+), 18 deletions(-)
diff --git a/scripts/libmakepkg/integrity/verify_signature.sh.in b/scripts/libmakepkg/integrity/verify_signature.sh.in
index 6df62727..634958f9 100644
--- a/scripts/libmakepkg/integrity/verify_signature.sh.in
+++ b/scripts/libmakepkg/integrity/verify_signature.sh.in
@@ -32,11 +32,12 @@ check_pgpsigs() {
msg "$(gettext "Verifying source file signatures with %s...")" "gpg"
- local file ext decompress found pubkey success status fingerprint trusted
+ local netfile file ext decompress found pubkey success status fingerprint trusted
local warning=0
local errors=0
local statusfile=$(mktemp)
local all_sources
+ local proto dir fragment query fragtype fragval
case $1 in
all)
@@ -46,15 +47,38 @@ check_pgpsigs() {
get_all_sources_for_arch 'all_sources'
;;
esac
- for file in "${all_sources[@]}"; do
- file="$(get_filename "$file")"
- if [[ $file != *.@(sig?(n)|asc) ]]; then
+ for netfile in "${all_sources[@]}"; do
+ file="$(get_filename "$netfile")"
+ proto="$(get_protocol "$netfile")"
+ dir=$(get_filepath "$netfile")
+ fragment=$(get_uri_fragment "$netfile")
+ query=$(get_uri_query "$netfile")
+
+ if [[ $proto = git* && $query = signed ]]; then
+ case ${fragment%%=*} in
+ tag)
+ fragtype=tag
+ fragval=${fragment##*=}
+ ;;
+ commit|branch)
+ fragtype=commit
+ fragval=${fragment##*=}
+ ;;
+ '')
+ fragtype=commit
+ fragval=HEAD
+ esac
+ elif [[ $file != *.@(sig?(n)|asc) ]]; then
continue
fi
- printf " %s ... " "${file%.*}" >&2
+ if [[ $proto = git* ]]; then
+ printf " %s git repo ... " "${file%.*}" >&2
+ else
+ printf " %s ... " "${file%.*}" >&2
+ fi
- if ! file="$(get_filepath "$file")"; then
+ if ! file="$(get_filepath "$netfile")"; then
printf '%s\n' "$(gettext "SIGNATURE NOT FOUND")" >&2
errors=1
continue
@@ -67,7 +91,7 @@ check_pgpsigs() {
break;
fi
done
- if (( ! found )); then
+ if [[ $proto != git* ]] && (( ! found )); then
printf '%s\n' "$(gettext "SOURCE FILE NOT FOUND")" >&2
errors=1
continue
@@ -83,7 +107,16 @@ check_pgpsigs() {
"") decompress="cat" ;;
esac
- $decompress < "$sourcefile" | gpg --quiet --batch --status-file "$statusfile" --verify "$file" - 2> /dev/null
+ if [[ $proto = git* ]]; then
+ 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
+ continue
+ fi
+ else
+ $decompress < "$sourcefile" | gpg --quiet --batch --status-file "$statusfile" --verify "$file" - 2> /dev/null
+ fi
# these variables are assigned values in parse_gpg_statusfile
success=0
status=
@@ -204,11 +237,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..890e92ba 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=${netfile%%\?*}
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 "signed" status of a source entry - defined as a trailing URI data component
+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