diff --git a/contrib/verify-commits/gpg.sh b/contrib/verify-commits/gpg.sh index 09ff23754..4df8bee3b 100755 --- a/contrib/verify-commits/gpg.sh +++ b/contrib/verify-commits/gpg.sh @@ -8,7 +8,12 @@ VALID=false REVSIG=false IFS=' ' -for LINE in $(echo "$INPUT" | gpg --trust-model always "$@" 2>/dev/null); do +if [ "$BITCOIN_VERIFY_COMMITS_ALLOW_SHA1" = 1 ]; then + GPG_RES="$(echo "$INPUT" | gpg --trust-model always "$@" 2>/dev/null)" +else + GPG_RES="$(echo "$INPUT" | gpg --trust-model always --weak-digest sha1 "$@" 2>/dev/null)" +fi +for LINE in $(echo "$GPG_RES"); do case "$LINE" in "[GNUPG:] VALIDSIG "*) while read KEY; do diff --git a/contrib/verify-commits/trusted-sha512-root-commit b/contrib/verify-commits/trusted-sha512-root-commit new file mode 100644 index 000000000..189dc215e --- /dev/null +++ b/contrib/verify-commits/trusted-sha512-root-commit @@ -0,0 +1 @@ +b00ba6251f71fa1edaabdf809514e1bc3c67862e diff --git a/contrib/verify-commits/verify-commits.sh b/contrib/verify-commits/verify-commits.sh index b2cebdf1a..55eccf588 100755 --- a/contrib/verify-commits/verify-commits.sh +++ b/contrib/verify-commits/verify-commits.sh @@ -9,7 +9,10 @@ DIR=$(dirname "$0") [ "/${DIR#/}" != "$DIR" ] && DIR=$(dirname "$(pwd)/$0") +echo "Using verify-commits data from ${DIR}" + VERIFIED_ROOT=$(cat "${DIR}/trusted-git-root") +VERIFIED_SHA512_ROOT=$(cat "${DIR}/trusted-sha512-root-commit") REVSIG_ALLOWED=$(cat "${DIR}/allow-revsig-commits") HAVE_FAILED=false @@ -17,18 +20,73 @@ IS_SIGNED () { if [ $1 = $VERIFIED_ROOT ]; then return 0; fi + + VERIFY_TREE=$2 + NO_SHA1=$3 + if [ $1 = $VERIFIED_SHA512_ROOT ]; then + if [ "$VERIFY_TREE" = "1" ]; then + echo "All Tree-SHA512s matched up to $VERIFIED_SHA512_ROOT" > /dev/stderr + fi + VERIFY_TREE=0 + NO_SHA1=0 + fi + + if [ "$NO_SHA1" = "1" ]; then + export BITCOIN_VERIFY_COMMITS_ALLOW_SHA1=0 + else + export BITCOIN_VERIFY_COMMITS_ALLOW_SHA1=1 + fi + if [ "${REVSIG_ALLOWED#*$1}" != "$REVSIG_ALLOWED" ]; then export BITCOIN_VERIFY_COMMITS_ALLOW_REVSIG=1 else export BITCOIN_VERIFY_COMMITS_ALLOW_REVSIG=0 fi + if ! git -c "gpg.program=${DIR}/gpg.sh" verify-commit $1 > /dev/null 2>&1; then return 1; fi + + if [ "$VERIFY_TREE" = 1 ]; then + IFS_CACHE="$IFS" + IFS=' +' + for LINE in $(git ls-tree --full-tree -r $1); do + case "$LINE" in + "12"*) + echo "Repo contains symlinks" > /dev/stderr + IFS="$IFS_CACHE" + return 1 + ;; + esac + done + IFS="$IFS_CACHE" + + FILE_HASHES="" + for FILE in $(git ls-tree --full-tree -r --name-only $1 | LANG=C sort); do + HASH=$(git cat-file blob $1:"$FILE" | sha512sum | { read FIRST OTHER; echo $FIRST; } ) + [ "$FILE_HASHES" != "" ] && FILE_HASHES="$FILE_HASHES"$'\n' + FILE_HASHES="$FILE_HASHES$HASH $FILE" + done + HASH_MATCHES=0 + MSG="$(git show -s --format=format:%B $1 | tail -n1)" + + case "$MSG -" in + "Tree-SHA512: $(echo "$FILE_HASHES" | sha512sum)") + HASH_MATCHES=1;; + esac + + if [ "$HASH_MATCHES" = "0" ]; then + echo "Tree-SHA512 did not match for commit $1" > /dev/stderr + HAVE_FAILED=true + return 1 + fi + fi + local PARENTS PARENTS=$(git show -s --format=format:%P $1) for PARENT in $PARENTS; do - if IS_SIGNED $PARENT; then + if IS_SIGNED $PARENT $VERIFY_TREE $NO_SHA1; then return 0; fi break @@ -50,7 +108,13 @@ else TEST_COMMIT="$1" fi -IS_SIGNED "$TEST_COMMIT" +DO_CHECKOUT_TEST=0 +if [ x"$2" = "x--tree-checks" ]; then + DO_CHECKOUT_TEST=1 + +fi + +IS_SIGNED "$TEST_COMMIT" "$DO_CHECKOUT_TEST" 1 RES=$? if [ "$RES" = 1 ]; then if ! "$HAVE_FAILED"; then