[pacman-dev] [PATCH] makepkg: Verify git signatures
Allan McRae
allan at archlinux.org
Tue Jan 3 05:22:48 UTC 2017
On 17/12/16 04:56, Eli Schwartz wrote:
> 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.
>
Needs documentation added. e.g. can the query string occur anywhere
relative to the fragment?
> 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
I'm guessing other modern VCS tools can have signatures verified too?
This function will become a mess when they are included. Please split
out git and standard file verification to their own functions called
within this one.
> + 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
>
>
More information about the pacman-dev
mailing list