1
0
mirror of https://github.com/moparisthebest/pacman synced 2024-11-16 06:15:08 -05:00

libmakepkg: extract functions for integrity checking

Signed-off-by: Ashley Whetter <ashley@awhetter.co.uk>
Signed-off-by: Allan McRae <allan@archlinux.org>
This commit is contained in:
Ashley Whetter 2016-05-08 17:28:28 +01:00 committed by Allan McRae
parent 892a1076c0
commit 4f114f3817
10 changed files with 579 additions and 429 deletions

View File

@ -41,6 +41,7 @@ LIBRARY = \
libmakepkgdir = $(datarootdir)/makepkg libmakepkgdir = $(datarootdir)/makepkg
LIBMAKEPKGDIRS = \ LIBMAKEPKGDIRS = \
integrity \
lint_package \ lint_package \
lint_pkgbuild \ lint_pkgbuild \
source \ source \
@ -53,6 +54,11 @@ LIBMAKEPKG = \
libmakepkg/util/util.sh libmakepkg/util/util.sh
LIBMAKEPKG_IN = \ LIBMAKEPKG_IN = \
libmakepkg/integrity.sh \
libmakepkg/integrity/generate_checksum.sh \
libmakepkg/integrity/generate_signature.sh \
libmakepkg/integrity/verify_checksum.sh \
libmakepkg/integrity/verify_signature.sh \
libmakepkg/lint_package.sh \ libmakepkg/lint_package.sh \
libmakepkg/lint_package/build_references.sh \ libmakepkg/lint_package/build_references.sh \
libmakepkg/lint_package/missing_backup.sh \ libmakepkg/lint_package/missing_backup.sh \

View File

@ -1,3 +1,5 @@
integrity.sh
integrity/*.sh
lint_package.sh lint_package.sh
lint_package/*.sh lint_package/*.sh
lint_pkgbuild.sh lint_pkgbuild.sh

View File

@ -0,0 +1,45 @@
#!/bin/bash
#
# integrity.sh - functions relating to source integrity checking
#
# Copyright (c) 2011-2016 Pacman Development Team <pacman-dev@archlinux.org>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
[[ -n "$LIBMAKEPKG_INTEGRITY_SH" ]] && return
LIBMAKEPKG_INTEGRITY_SH=1
LIBRARY=${LIBRARY:-'@libmakepkgdir@'}
source "$LIBRARY/util/message.sh"
for lib in "$LIBRARY/integrity/"*.sh; do
source "$lib"
done
check_source_integrity() {
if (( SKIPCHECKSUMS && SKIPPGPCHECK )); then
warning "$(gettext "Skipping all source file integrity checks.")"
elif (( SKIPCHECKSUMS )); then
warning "$(gettext "Skipping verification of source file checksums.")"
check_pgpsigs "$@"
elif (( SKIPPGPCHECK )); then
warning "$(gettext "Skipping verification of source file PGP signatures.")"
check_checksums "$@"
else
check_checksums "$@"
check_pgpsigs "$@"
fi
}

View File

@ -0,0 +1,107 @@
#!/bin/bash
#
# generate_checksum.sh - functions for generating source checksums
#
# Copyright (c) 2014-2016 Pacman Development Team <pacman-dev@archlinux.org>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
[[ -n "$LIBMAKEPKG_INTEGRITY_GENERATE_CHECKSUM_SH" ]] && return
LIBMAKEPKG_INTEGRITY_GENERATE_CHECKSUM_SH=1
LIBRARY=${LIBRARY:-'@libmakepkgdir@'}
source "$LIBRARY/util/message.sh"
source "$LIBRARY/util/pkgbuild.sh"
generate_one_checksum() {
local integ=$1 arch=$2 sources numsrc indentsz idx
if [[ $arch ]]; then
array_build sources "source_$arch"
else
array_build sources 'source'
fi
numsrc=${#sources[*]}
if (( numsrc == 0 )); then
return
fi
if [[ $arch ]]; then
printf "%ssums_%s=(%n" "$integ" "$arch" indentsz
else
printf "%ssums=(%n" "$integ" indentsz
fi
for (( idx = 0; idx < numsrc; ++idx )); do
local netfile=${sources[idx]}
local proto sum
proto="$(get_protocol "$netfile")"
case $proto in
bzr*|git*|hg*|svn*)
sum="SKIP"
;;
*)
if [[ $netfile != *.@(sig?(n)|asc) ]]; then
local file
file="$(get_filepath "$netfile")" || missing_source_file "$netfile"
sum="$(openssl dgst -${integ} "$file")"
sum=${sum##* }
else
sum="SKIP"
fi
;;
esac
# indent checksum on lines after the first
printf "%*s%s" $(( idx ? indentsz : 0 )) '' "'$sum'"
# print a newline on lines before the last
(( idx < (numsrc - 1) )) && echo
done
echo ")"
}
generate_checksums() {
msg "$(gettext "Generating checksums for source files...")"
if ! type -p openssl >/dev/null; then
error "$(gettext "Cannot find the %s binary required for generating sourcefile checksums.")" "openssl"
exit 1 # $E_MISSING_PROGRAM
fi
local integlist
if (( $# == 0 )); then
IFS=$'\n' read -rd '' -a integlist < <(get_integlist)
else
integlist=("$@")
fi
local integ
for integ in "${integlist[@]}"; do
if ! in_array "$integ" "${known_hash_algos[@]}"; then
error "$(gettext "Invalid integrity algorithm '%s' specified.")" "$integ"
exit 1 # $E_CONFIG_ERROR
fi
generate_one_checksum "$integ"
for a in "${arch[@]}"; do
generate_one_checksum "$integ" "$a"
done
done
}

View File

@ -0,0 +1,49 @@
#!/bin/bash
#
# generate_signature.sh - functions for generating PGP signatures
#
# Copyright (c) 2008-2016 Pacman Development Team <pacman-dev@archlinux.org>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
[[ -n "$LIBMAKEPKG_INTEGRITY_GENERATE_SIGNATURE_SH" ]] && return
LIBMAKEPKG_INTEGRITY_GENERATE_SIGNATURE_SH=1
LIBRARY=${LIBRARY:-'@libmakepkgdir@'}
source "$LIBRARY/util/message.sh"
create_signature() {
if [[ $SIGNPKG != 'y' ]]; then
return
fi
local ret=0
local filename="$1"
msg "$(gettext "Signing package...")"
local SIGNWITHKEY=""
if [[ -n $GPGKEY ]]; then
SIGNWITHKEY="-u ${GPGKEY}"
fi
gpg --detach-sign --use-agent ${SIGNWITHKEY} --no-armor "$filename" &>/dev/null || ret=$?
if (( ! ret )); then
msg2 "$(gettext "Created signature file %s.")" "$filename.sig"
else
warning "$(gettext "Failed to sign package file.")"
fi
}

View File

@ -0,0 +1,130 @@
#!/bin/bash
#
# verify_checksum.sh - functions for checking source checksums
#
# Copyright (c) 2014-2016 Pacman Development Team <pacman-dev@archlinux.org>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
[[ -n "$LIBMAKEPKG_INTEGRITY_VERIFY_CHECKSUM_SH" ]] && return
LIBMAKEPKG_INTEGRITY_CHECKSUM_SH=1
LIBRARY=${LIBRARY:-'@libmakepkgdir@'}
source "$LIBRARY/util/message.sh"
source "$LIBRARY/util/pkgbuild.sh"
check_checksums() {
local integ a
declare -A correlation
(( SKIPCHECKSUMS )) && return 0
# Initialize a map which we'll use to verify that every source array has at
# least some kind of checksum array associated with it.
(( ${#source[*]} )) && correlation['source']=1
case $1 in
all)
for a in "${arch[@]}"; do
array_build _ source_"$a" && correlation["source_$a"]=1
done
;;
*)
array_build _ source_"$CARCH" && correlation["source_$CARCH"]=1
;;
esac
for integ in "${known_hash_algos[@]}"; do
verify_integrity_sums "$integ" && unset "correlation[source]"
case $1 in
all)
for a in "${arch[@]}"; do
verify_integrity_sums "$integ" "$a" && unset "correlation[source_$a]"
done
;;
*)
verify_integrity_sums "$integ" "$CARCH" && unset "correlation[source_$CARCH]"
;;
esac
done
if (( ${#correlation[*]} )); then
error "$(gettext "Integrity checks are missing for: %s")" "${!correlation[*]}"
exit 1 # TODO: error code
fi
}
verify_integrity_one() {
local source_name=$1 integ=$2 expectedsum=$3
local file="$(get_filename "$source_name")"
printf ' %s ... ' "$file" >&2
if [[ $expectedsum = 'SKIP' ]]; then
printf '%s\n' "$(gettext "Skipped")" >&2
return
fi
if ! file="$(get_filepath "$file")"; then
printf '%s\n' "$(gettext "NOT FOUND")" >&2
return 1
fi
local realsum="$(openssl dgst -${integ} "$file")"
realsum="${realsum##* }"
if [[ ${expectedsum,,} = "$realsum" ]]; then
printf '%s\n' "$(gettext "Passed")" >&2
else
printf '%s\n' "$(gettext "FAILED")" >&2
return 1
fi
return 0
}
verify_integrity_sums() {
local integ=$1 arch=$2 integrity_sums=() sources=() srcname
if [[ $arch ]]; then
array_build integrity_sums "${integ}sums_$arch"
srcname=source_$arch
else
array_build integrity_sums "${integ}sums"
srcname=source
fi
array_build sources "$srcname"
if (( ${#integrity_sums[@]} == 0 && ${#sources[@]} == 0 )); then
return 1
fi
if (( ${#integrity_sums[@]} == ${#sources[@]} )); then
msg "$(gettext "Validating %s files with %s...")" "$srcname" "${integ}sums"
local idx errors=0
for (( idx = 0; idx < ${#sources[*]}; idx++ )); do
verify_integrity_one "${sources[idx]}" "$integ" "${integrity_sums[idx]}" || errors=1
done
if (( errors )); then
error "$(gettext "One or more files did not pass the validity check!")"
exit 1 # TODO: error code
fi
elif (( ${#integrity_sums[@]} )); then
error "$(gettext "Integrity checks (%s) differ in size from the source array.")" "$integ"
exit 1 # TODO: error code
else
return 1
fi
}

View File

@ -0,0 +1,216 @@
#!/bin/bash
#
# verify_signature.sh - functions for checking PGP signatures
#
# Copyright (c) 2011-2016 Pacman Development Team <pacman-dev@archlinux.org>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
[[ -n "$LIBMAKEPKG_INTEGRITY_VERIFY_SIGNATURE_SH" ]] && return
LIBMAKEPKG_INTEGRITY_VERIFY_SIGNATURE_SH=1
LIBRARY=${LIBRARY:-'@libmakepkgdir@'}
source "$LIBRARY/util/message.sh"
source "$LIBRARY/util/pkgbuild.sh"
check_pgpsigs() {
(( SKIPPGPCHECK )) && return 0
! source_has_signatures && return 0
msg "$(gettext "Verifying source file signatures with %s...")" "gpg"
local file ext decompress found pubkey success status fingerprint trusted
local warning=0
local errors=0
local statusfile=$(mktemp)
local all_sources
case $1 in
all)
get_all_sources 'all_sources'
;;
*)
get_all_sources_for_arch 'all_sources'
;;
esac
for file in "${all_sources[@]}"; do
file="$(get_filename "$file")"
if [[ $file != *.@(sig?(n)|asc) ]]; then
continue
fi
printf " %s ... " "${file%.*}" >&2
if ! file="$(get_filepath "$file")"; then
printf '%s\n' "$(gettext "SIGNATURE NOT FOUND")" >&2
errors=1
continue
fi
found=0
for ext in "" gz bz2 xz lrz lzo Z; do
if sourcefile="$(get_filepath "${file%.*}${ext:+.$ext}")"; then
found=1
break;
fi
done
if (( ! found )); then
printf '%s\n' "$(gettext "SOURCE FILE NOT FOUND")" >&2
errors=1
continue
fi
case "$ext" in
gz) decompress="gzip -c -d -f" ;;
bz2) decompress="bzip2 -c -d -f" ;;
xz) decompress="xz -c -d" ;;
lrz) decompress="lrzip -q -d" ;;
lzo) decompress="lzop -c -d -q" ;;
Z) decompress="uncompress -c -f" ;;
"") decompress="cat" ;;
esac
$decompress < "$sourcefile" | gpg --quiet --batch --status-file "$statusfile" --verify "$file" - 2> /dev/null
# these variables are assigned values in parse_gpg_statusfile
success=0
status=
pubkey=
fingerprint=
trusted=
parse_gpg_statusfile "$statusfile"
if (( ! $success )); then
printf '%s' "$(gettext "FAILED")" >&2
case "$status" in
"missingkey")
printf ' (%s)' "$(gettext "unknown public key") $pubkey" >&2
;;
"revokedkey")
printf " ($(gettext "public key %s has been revoked"))" "$pubkey" >&2
;;
"bad")
printf ' (%s)' "$(gettext "bad signature from public key") $pubkey" >&2
;;
"error")
printf ' (%s)' "$(gettext "error during signature verification")" >&2
;;
esac
errors=1
else
if (( ${#validpgpkeys[@]} == 0 && !trusted )); then
printf "%s ($(gettext "the public key %s is not trusted"))" $(gettext "FAILED") "$fingerprint" >&2
errors=1
elif (( ${#validpgpkeys[@]} > 0 )) && ! in_array "$fingerprint" "${validpgpkeys[@]}"; then
printf "%s (%s %s)" "$(gettext "FAILED")" "$(gettext "invalid public key")" "$fingerprint"
errors=1
else
printf '%s' "$(gettext "Passed")" >&2
case "$status" in
"expired")
printf ' (%s)' "$(gettext "WARNING:") $(gettext "the signature has expired.")" >&2
warnings=1
;;
"expiredkey")
printf ' (%s)' "$(gettext "WARNING:") $(gettext "the key has expired.")" >&2
warnings=1
;;
esac
fi
fi
printf '\n' >&2
done
rm -f "$statusfile"
if (( errors )); then
error "$(gettext "One or more PGP signatures could not be verified!")"
exit 1
fi
if (( warnings )); then
warning "$(gettext "Warnings have occurred while verifying the signatures.")"
plain "$(gettext "Please make sure you really trust them.")"
fi
}
parse_gpg_statusfile() {
local type arg1 arg6 arg10
while read -r _ type arg1 _ _ _ _ arg6 _ _ _ arg10 _; do
case "$type" in
GOODSIG)
pubkey=$arg1
success=1
status="good"
;;
EXPSIG)
pubkey=$arg1
success=1
status="expired"
;;
EXPKEYSIG)
pubkey=$arg1
success=1
status="expiredkey"
;;
REVKEYSIG)
pubkey=$arg1
success=0
status="revokedkey"
;;
BADSIG)
pubkey=$arg1
success=0
status="bad"
;;
ERRSIG)
pubkey=$arg1
success=0
if [[ $arg6 == 9 ]]; then
status="missingkey"
else
status="error"
fi
;;
VALIDSIG)
if [[ $arg10 ]]; then
# If the file was signed with a subkey, arg10 contains
# the fingerprint of the primary key
fingerprint=$arg10
else
fingerprint=$arg1
fi
;;
TRUST_UNDEFINED|TRUST_NEVER)
trusted=0
;;
TRUST_MARGINAL|TRUST_FULLY|TRUST_ULTIMATE)
trusted=1
;;
esac
done < "$1"
}
source_has_signatures() {
local file all_sources
get_all_sources_for_arch 'all_sources'
for file in "${all_sources[@]}"; do
if [[ ${file%%::*} = *.@(sig?(n)|asc) ]]; then
return 0
fi
done
return 1
}

View File

@ -2,7 +2,7 @@
# #
# pkgbuild.sh - functions to extract information from PKGBUILD files # pkgbuild.sh - functions to extract information from PKGBUILD files
# #
# Copyright (c) 2014-2016 Pacman Development Team <pacman-dev@archlinux.org> # Copyright (c) 2009-2016 Pacman Development Team <pacman-dev@archlinux.org>
# #
# This program is free software; you can redistribute it and/or modify # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
@ -189,3 +189,21 @@ get_all_sources_for_arch() {
array_build "$1" "aggregate" array_build "$1" "aggregate"
} }
get_integlist() {
local integ
local integlist=()
for integ in "${known_hash_algos[@]}"; do
local sumname="${integ}sums[@]"
if [[ -n ${!sumname} ]]; then
integlist+=("$integ")
fi
done
if (( ${#integlist[@]} > 0 )); then
printf "%s\n" "${integlist[@]}"
else
printf "%s\n" "${INTEGRITY_CHECK[@]}"
fi
}

View File

@ -204,18 +204,6 @@ missing_source_file() {
exit 1 # $E_MISSING_FILE exit 1 # $E_MISSING_FILE
} }
source_has_signatures() {
local file all_sources
get_all_sources_for_arch 'all_sources'
for file in "${all_sources[@]}"; do
if [[ ${file%%::*} = *.@(sig?(n)|asc) ]]; then
return 0
fi
done
return 1
}
run_pacman() { run_pacman() {
local cmd local cmd
if [[ $1 != -@(T|Qq) ]]; then if [[ $1 != -@(T|Qq) ]]; then
@ -332,399 +320,6 @@ remove_deps() {
fi fi
} }
get_integlist() {
local integ
local integlist=()
for integ in "${known_hash_algos[@]}"; do
local sumname="${integ}sums[@]"
if [[ -n ${!sumname} ]]; then
integlist+=("$integ")
fi
done
if (( ${#integlist[@]} > 0 )); then
printf "%s\n" "${integlist[@]}"
else
printf "%s\n" "${INTEGRITY_CHECK[@]}"
fi
}
generate_one_checksum() {
local integ=$1 arch=$2 sources numsrc indentsz idx
if [[ $arch ]]; then
array_build sources "source_$arch"
else
array_build sources 'source'
fi
numsrc=${#sources[*]}
if (( numsrc == 0 )); then
return
fi
if [[ $arch ]]; then
printf "%ssums_%s=(%n" "$integ" "$arch" indentsz
else
printf "%ssums=(%n" "$integ" indentsz
fi
for (( idx = 0; idx < numsrc; ++idx )); do
local netfile=${sources[idx]}
local proto sum
proto="$(get_protocol "$netfile")"
case $proto in
bzr*|git*|hg*|svn*)
sum="SKIP"
;;
*)
if [[ $netfile != *.@(sig?(n)|asc) ]]; then
local file
file="$(get_filepath "$netfile")" || missing_source_file "$netfile"
sum="$(openssl dgst -${integ} "$file")"
sum=${sum##* }
else
sum="SKIP"
fi
;;
esac
# indent checksum on lines after the first
printf "%*s%s" $(( idx ? indentsz : 0 )) '' "'$sum'"
# print a newline on lines before the last
(( idx < (numsrc - 1) )) && echo
done
echo ")"
}
generate_checksums() {
msg "$(gettext "Generating checksums for source files...")"
if ! type -p openssl >/dev/null; then
error "$(gettext "Cannot find the %s binary required for generating sourcefile checksums.")" "openssl"
exit 1 # $E_MISSING_PROGRAM
fi
local integlist
if (( $# == 0 )); then
IFS=$'\n' read -rd '' -a integlist < <(get_integlist)
else
integlist=("$@")
fi
local integ
for integ in "${integlist[@]}"; do
if ! in_array "$integ" "${known_hash_algos[@]}"; then
error "$(gettext "Invalid integrity algorithm '%s' specified.")" "$integ"
exit 1 # $E_CONFIG_ERROR
fi
generate_one_checksum "$integ"
for a in "${arch[@]}"; do
generate_one_checksum "$integ" "$a"
done
done
}
verify_integrity_one() {
local source_name=$1 integ=$2 expectedsum=$3
local file="$(get_filename "$source_name")"
printf ' %s ... ' "$file" >&2
if [[ $expectedsum = 'SKIP' ]]; then
printf '%s\n' "$(gettext "Skipped")" >&2
return
fi
if ! file="$(get_filepath "$file")"; then
printf '%s\n' "$(gettext "NOT FOUND")" >&2
return 1
fi
local realsum="$(openssl dgst -${integ} "$file")"
realsum="${realsum##* }"
if [[ ${expectedsum,,} = "$realsum" ]]; then
printf '%s\n' "$(gettext "Passed")" >&2
else
printf '%s\n' "$(gettext "FAILED")" >&2
return 1
fi
return 0
}
verify_integrity_sums() {
local integ=$1 arch=$2 integrity_sums=() sources=() srcname
if [[ $arch ]]; then
array_build integrity_sums "${integ}sums_$arch"
srcname=source_$arch
else
array_build integrity_sums "${integ}sums"
srcname=source
fi
array_build sources "$srcname"
if (( ${#integrity_sums[@]} == 0 && ${#sources[@]} == 0 )); then
return 1
fi
if (( ${#integrity_sums[@]} == ${#sources[@]} )); then
msg "$(gettext "Validating %s files with %s...")" "$srcname" "${integ}sums"
local idx errors=0
for (( idx = 0; idx < ${#sources[*]}; idx++ )); do
verify_integrity_one "${sources[idx]}" "$integ" "${integrity_sums[idx]}" || errors=1
done
if (( errors )); then
error "$(gettext "One or more files did not pass the validity check!")"
exit 1 # TODO: error code
fi
elif (( ${#integrity_sums[@]} )); then
error "$(gettext "Integrity checks (%s) differ in size from the source array.")" "$integ"
exit 1 # TODO: error code
else
return 1
fi
}
check_checksums() {
local integ a
declare -A correlation
(( SKIPCHECKSUMS )) && return 0
# Initialize a map which we'll use to verify that every source array has at
# least some kind of checksum array associated with it.
(( ${#source[*]} )) && correlation['source']=1
case $1 in
all)
for a in "${arch[@]}"; do
array_build _ source_"$a" && correlation["source_$a"]=1
done
;;
*)
array_build _ source_"$CARCH" && correlation["source_$CARCH"]=1
;;
esac
for integ in "${known_hash_algos[@]}"; do
verify_integrity_sums "$integ" && unset "correlation[source]"
case $1 in
all)
for a in "${arch[@]}"; do
verify_integrity_sums "$integ" "$a" && unset "correlation[source_$a]"
done
;;
*)
verify_integrity_sums "$integ" "$CARCH" && unset "correlation[source_$CARCH]"
;;
esac
done
if (( ${#correlation[*]} )); then
error "$(gettext "Integrity checks are missing for: %s")" "${!correlation[*]}"
exit 1 # TODO: error code
fi
}
parse_gpg_statusfile() {
local type arg1 arg6 arg10
while read -r _ type arg1 _ _ _ _ arg6 _ _ _ arg10 _; do
case "$type" in
GOODSIG)
pubkey=$arg1
success=1
status="good"
;;
EXPSIG)
pubkey=$arg1
success=1
status="expired"
;;
EXPKEYSIG)
pubkey=$arg1
success=1
status="expiredkey"
;;
REVKEYSIG)
pubkey=$arg1
success=0
status="revokedkey"
;;
BADSIG)
pubkey=$arg1
success=0
status="bad"
;;
ERRSIG)
pubkey=$arg1
success=0
if [[ $arg6 == 9 ]]; then
status="missingkey"
else
status="error"
fi
;;
VALIDSIG)
if [[ $arg10 ]]; then
# If the file was signed with a subkey, arg10 contains
# the fingerprint of the primary key
fingerprint=$arg10
else
fingerprint=$arg1
fi
;;
TRUST_UNDEFINED|TRUST_NEVER)
trusted=0
;;
TRUST_MARGINAL|TRUST_FULLY|TRUST_ULTIMATE)
trusted=1
;;
esac
done < "$1"
}
check_pgpsigs() {
(( SKIPPGPCHECK )) && return 0
! source_has_signatures && return 0
msg "$(gettext "Verifying source file signatures with %s...")" "gpg"
local file ext decompress found pubkey success status fingerprint trusted
local warning=0
local errors=0
local statusfile=$(mktemp)
local all_sources
case $1 in
all)
get_all_sources 'all_sources'
;;
*)
get_all_sources_for_arch 'all_sources'
;;
esac
for file in "${all_sources[@]}"; do
file="$(get_filename "$file")"
if [[ $file != *.@(sig?(n)|asc) ]]; then
continue
fi
printf " %s ... " "${file%.*}" >&2
if ! file="$(get_filepath "$file")"; then
printf '%s\n' "$(gettext "SIGNATURE NOT FOUND")" >&2
errors=1
continue
fi
found=0
for ext in "" gz bz2 xz lrz lzo Z; do
if sourcefile="$(get_filepath "${file%.*}${ext:+.$ext}")"; then
found=1
break;
fi
done
if (( ! found )); then
printf '%s\n' "$(gettext "SOURCE FILE NOT FOUND")" >&2
errors=1
continue
fi
case "$ext" in
gz) decompress="gzip -c -d -f" ;;
bz2) decompress="bzip2 -c -d -f" ;;
xz) decompress="xz -c -d" ;;
lrz) decompress="lrzip -q -d" ;;
lzo) decompress="lzop -c -d -q" ;;
Z) decompress="uncompress -c -f" ;;
"") decompress="cat" ;;
esac
$decompress < "$sourcefile" | gpg --quiet --batch --status-file "$statusfile" --verify "$file" - 2> /dev/null
# these variables are assigned values in parse_gpg_statusfile
success=0
status=
pubkey=
fingerprint=
trusted=
parse_gpg_statusfile "$statusfile"
if (( ! $success )); then
printf '%s' "$(gettext "FAILED")" >&2
case "$status" in
"missingkey")
printf ' (%s)' "$(gettext "unknown public key") $pubkey" >&2
;;
"revokedkey")
printf " ($(gettext "public key %s has been revoked"))" "$pubkey" >&2
;;
"bad")
printf ' (%s)' "$(gettext "bad signature from public key") $pubkey" >&2
;;
"error")
printf ' (%s)' "$(gettext "error during signature verification")" >&2
;;
esac
errors=1
else
if (( ${#validpgpkeys[@]} == 0 && !trusted )); then
printf "%s ($(gettext "the public key %s is not trusted"))" $(gettext "FAILED") "$fingerprint" >&2
errors=1
elif (( ${#validpgpkeys[@]} > 0 )) && ! in_array "$fingerprint" "${validpgpkeys[@]}"; then
printf "%s (%s %s)" "$(gettext "FAILED")" "$(gettext "invalid public key")" "$fingerprint"
errors=1
else
printf '%s' "$(gettext "Passed")" >&2
case "$status" in
"expired")
printf ' (%s)' "$(gettext "WARNING:") $(gettext "the signature has expired.")" >&2
warnings=1
;;
"expiredkey")
printf ' (%s)' "$(gettext "WARNING:") $(gettext "the key has expired.")" >&2
warnings=1
;;
esac
fi
fi
printf '\n' >&2
done
rm -f "$statusfile"
if (( errors )); then
error "$(gettext "One or more PGP signatures could not be verified!")"
exit 1
fi
if (( warnings )); then
warning "$(gettext "Warnings have occurred while verifying the signatures.")"
plain "$(gettext "Please make sure you really trust them.")"
fi
}
check_source_integrity() {
if (( SKIPCHECKSUMS && SKIPPGPCHECK )); then
warning "$(gettext "Skipping all source file integrity checks.")"
elif (( SKIPCHECKSUMS )); then
warning "$(gettext "Skipping verification of source file checksums.")"
check_pgpsigs "$@"
elif (( SKIPPGPCHECK )); then
warning "$(gettext "Skipping verification of source file PGP signatures.")"
check_checksums "$@"
else
check_checksums "$@"
check_pgpsigs "$@"
fi
}
error_function() { error_function() {
if [[ -p $logpipe ]]; then if [[ -p $logpipe ]]; then
rm "$logpipe" rm "$logpipe"
@ -1192,29 +787,6 @@ create_debug_package() {
create_package create_package
} }
create_signature() {
if [[ $SIGNPKG != 'y' ]]; then
return
fi
local ret=0
local filename="$1"
msg "$(gettext "Signing package...")"
local SIGNWITHKEY=""
if [[ -n $GPGKEY ]]; then
SIGNWITHKEY="-u ${GPGKEY}"
fi
gpg --detach-sign --use-agent ${SIGNWITHKEY} --no-armor "$filename" &>/dev/null || ret=$?
if (( ! ret )); then
msg2 "$(gettext "Created signature file %s.")" "$filename.sig"
else
warning "$(gettext "Failed to sign package file.")"
fi
}
create_srcpackage() { create_srcpackage() {
local ret=0 local ret=0
msg "$(gettext "Creating source package...")" msg "$(gettext "Creating source package...")"

View File

@ -8,6 +8,11 @@ scripts/pacman-key.sh.in
scripts/pacman-optimize.sh.in scripts/pacman-optimize.sh.in
scripts/pkgdelta.sh.in scripts/pkgdelta.sh.in
scripts/repo-add.sh.in scripts/repo-add.sh.in
scripts/libmakepkg/integrity.sh
scripts/libmakepkg/integrity/generate_checksum.sh
scripts/libmakepkg/integrity/generate_signature.sh
scripts/libmakepkg/integrity/verify_checksum.sh
scripts/libmakepkg/integrity/verify_signature.sh
scripts/libmakepkg/lint_package.sh.in scripts/libmakepkg/lint_package.sh.in
scripts/libmakepkg/lint_package/build_references.sh.in scripts/libmakepkg/lint_package/build_references.sh.in
scripts/libmakepkg/lint_package/missing_backup.sh.in scripts/libmakepkg/lint_package/missing_backup.sh.in