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@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