diff options
author | Luke Dashjr <luke-jr+git@utopios.org> | 2016-08-09 05:45:50 +0000 |
---|---|---|
committer | Luke Dashjr <luke-jr+git@utopios.org> | 2016-08-09 05:45:50 +0000 |
commit | df634908ba758232413c50e8f1f7a80d546d777b (patch) | |
tree | 92cccae378b192f5f70986d2167209cbfd24ae08 /contrib/verify-commits | |
parent | e98e3dde6a976a2c8f266ee963d6931fd4b37262 (diff) | |
parent | e4382fbef56a0e04b0ed834e8b3a3a16f81db149 (diff) |
Merge tag 'branch-0.13' into bugfix_gitdir
Diffstat (limited to 'contrib/verify-commits')
-rw-r--r-- | contrib/verify-commits/README.md | 26 | ||||
-rw-r--r-- | contrib/verify-commits/allow-revsig-commits | 0 | ||||
-rwxr-xr-x | contrib/verify-commits/gpg.sh | 33 | ||||
-rwxr-xr-x | contrib/verify-commits/pre-push-hook.sh | 16 | ||||
-rw-r--r-- | contrib/verify-commits/trusted-git-root | 1 | ||||
-rw-r--r-- | contrib/verify-commits/trusted-keys | 4 | ||||
-rwxr-xr-x | contrib/verify-commits/verify-commits.sh | 58 |
7 files changed, 138 insertions, 0 deletions
diff --git a/contrib/verify-commits/README.md b/contrib/verify-commits/README.md new file mode 100644 index 0000000000..e9e3f65da2 --- /dev/null +++ b/contrib/verify-commits/README.md @@ -0,0 +1,26 @@ +Tooling for verification of PGP signed commits +---------------------------------------------- + +This is an incomplete work in progress, but currently includes a pre-push hook +script (`pre-push-hook.sh`) for maintainers to ensure that their own commits +are PGP signed (nearly always merge commits), as well as a script to verify +commits against a trusted keys list. + + +Using verify-commits.sh safely +------------------------------ + +Remember that you can't use an untrusted script to verify itself. This means +that checking out code, then running `verify-commits.sh` against `HEAD` is +_not_ safe, because the version of `verify-commits.sh` that you just ran could +be backdoored. Instead, you need to use a trusted version of verify-commits +prior to checkout to make sure you're checking out only code signed by trusted +keys: + + git fetch origin && \ + ./contrib/verify-commits/verify-commits.sh origin/master && \ + git checkout origin/master + +Note that the above isn't a good UI/UX yet, and needs significant improvements +to make it more convenient and reduce the chance of errors; pull-reqs +improving this process would be much appreciated. diff --git a/contrib/verify-commits/allow-revsig-commits b/contrib/verify-commits/allow-revsig-commits new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/contrib/verify-commits/allow-revsig-commits diff --git a/contrib/verify-commits/gpg.sh b/contrib/verify-commits/gpg.sh new file mode 100755 index 0000000000..375d711725 --- /dev/null +++ b/contrib/verify-commits/gpg.sh @@ -0,0 +1,33 @@ +#!/bin/sh +INPUT=$(cat /dev/stdin) +VALID=false +REVSIG=false +IFS=' +' +for LINE in $(echo "$INPUT" | gpg --trust-model always "$@" 2>/dev/null); do + case "$LINE" in + "[GNUPG:] VALIDSIG "*) + while read KEY; do + case "$LINE" in "[GNUPG:] VALIDSIG $KEY "*) VALID=true;; esac + done < ./contrib/verify-commits/trusted-keys + ;; + "[GNUPG:] REVKEYSIG "*) + [ "$BITCOIN_VERIFY_COMMITS_ALLOW_REVSIG" != 1 ] && exit 1 + while read KEY; do + case "$LINE" in "[GNUPG:] REVKEYSIG ${KEY#????????????????????????} "*) + REVSIG=true + GOODREVSIG="[GNUPG:] GOODSIG ${KEY#????????????????????????} " + esac + done < ./contrib/verify-commits/trusted-keys + ;; + esac +done +if ! $VALID; then + exit 1 +fi +if $VALID && $REVSIG; then + echo "$INPUT" | gpg --trust-model always "$@" | grep "\[GNUPG:\] \(NEWSIG\|SIG_ID\|VALIDSIG\)" 2>/dev/null + echo "$GOODREVSIG" +else + echo "$INPUT" | gpg --trust-model always "$@" 2>/dev/null +fi diff --git a/contrib/verify-commits/pre-push-hook.sh b/contrib/verify-commits/pre-push-hook.sh new file mode 100755 index 0000000000..c57222818a --- /dev/null +++ b/contrib/verify-commits/pre-push-hook.sh @@ -0,0 +1,16 @@ +#!/bin/bash +if ! [[ "$2" =~ ^(git@)?(www.)?github.com(:|/)bitcoin/bitcoin(.git)?$ ]]; then + exit 0 +fi + +while read LINE; do + set -- A $LINE + if [ "$4" != "refs/heads/master" ]; then + continue + fi + if ! ./contrib/verify-commits/verify-commits.sh $3 > /dev/null 2>&1; then + echo "ERROR: A commit is not signed, can't push" + ./contrib/verify-commits/verify-commits.sh + exit 1 + fi +done < /dev/stdin diff --git a/contrib/verify-commits/trusted-git-root b/contrib/verify-commits/trusted-git-root new file mode 100644 index 0000000000..c60f8ab695 --- /dev/null +++ b/contrib/verify-commits/trusted-git-root @@ -0,0 +1 @@ +82bcf405f6db1d55b684a1f63a4aabad376cdad7 diff --git a/contrib/verify-commits/trusted-keys b/contrib/verify-commits/trusted-keys new file mode 100644 index 0000000000..75242c2a97 --- /dev/null +++ b/contrib/verify-commits/trusted-keys @@ -0,0 +1,4 @@ +71A3B16735405025D447E8F274810B012346C9A6 +3F1888C6DCA92A6499C4911FDBA1A67379A1A931 +32EE5C4C3FA15CCADB46ABE529D4BCB6416F53EC +FE09B823E6D83A3BC7983EAA2D7F2372E50FE137 diff --git a/contrib/verify-commits/verify-commits.sh b/contrib/verify-commits/verify-commits.sh new file mode 100755 index 0000000000..5219331e2e --- /dev/null +++ b/contrib/verify-commits/verify-commits.sh @@ -0,0 +1,58 @@ +#!/bin/sh +# Not technically POSIX-compliant due to use of "local", but almost every +# shell anyone uses today supports it, so its probably fine + +DIR=$(dirname "$0") +[ "/${DIR#/}" != "$DIR" ] && DIR=$(dirname "$(pwd)/$0") + +VERIFIED_ROOT=$(cat "${DIR}/trusted-git-root") +REVSIG_ALLOWED=$(cat "${DIR}/allow-revsig-commits") + +HAVE_FAILED=false +IS_SIGNED () { + if [ $1 = $VERIFIED_ROOT ]; then + return 0; + 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 + local PARENTS + PARENTS=$(git show -s --format=format:%P $1) + for PARENT in $PARENTS; do + if IS_SIGNED $PARENT > /dev/null; then + return 0; + fi + done + if ! "$HAVE_FAILED"; then + echo "No parent of $1 was signed with a trusted key!" > /dev/stderr + echo "Parents are:" > /dev/stderr + for PARENT in $PARENTS; do + git show -s $PARENT > /dev/stderr + done + HAVE_FAILED=true + fi + return 1; +} + +if [ x"$1" = "x" ]; then + TEST_COMMIT="HEAD" +else + TEST_COMMIT="$1" +fi + +IS_SIGNED "$TEST_COMMIT" +RES=$? +if [ "$RES" = 1 ]; then + if ! "$HAVE_FAILED"; then + echo "$TEST_COMMIT was not signed with a trusted key!" + fi +else + echo "There is a valid path from $TEST_COMMIT to $VERIFIED_ROOT where all commits are signed!" +fi + +exit $RES |