This option works analogous to --verify-signatures for git-merge by checking that the commits, that are rebased onto, have good GPG signatures. Additionally, git-pull now forwards --verify-signatures to rebase as well. Signed-off-by: Alexander 'z33ky' Hirsch <1zeeky@xxxxxxxxx> --- I'm unsure if the opt_verify_signatures check in builtin/pull.c should be moved up to the "/* Shared options */" now. The output strings from the GPG check are identical to the ones in builtin/merge.c; I am unsure about the implications for l10n. The test is mostly copied from t7612-merge-verify-signatures.sh. Documentation/git-rebase.txt | 6 ++++ builtin/pull.c | 2 ++ git-rebase.sh | 44 +++++++++++++++++++++++++ t/t3427-rebase-verify-signatures.sh | 65 +++++++++++++++++++++++++++++++++++++ 4 files changed, 117 insertions(+) create mode 100755 t/t3427-rebase-verify-signatures.sh diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt index 6cca8bb..959b12b 100644 --- a/Documentation/git-rebase.txt +++ b/Documentation/git-rebase.txt @@ -292,6 +292,12 @@ which makes little sense. specified, `-s recursive`. Note the reversal of 'ours' and 'theirs' as noted above for the `-m` option. +--verify-signatures:: +--no-verify-signatures:: + Verify that the commits in the branch the rebase is onto, but not + present in the working branch, have good GPG signatures and abort the + operation in case they do not. + -S[<keyid>]:: --gpg-sign[=<keyid>]:: GPG-sign commits. The `keyid` argument is optional and diff --git a/builtin/pull.c b/builtin/pull.c index bf3fd3f..37ec0f8 100644 --- a/builtin/pull.c +++ b/builtin/pull.c @@ -774,6 +774,8 @@ static int run_rebase(const unsigned char *curr_head, argv_array_push(&args, "--preserve-merges"); if (opt_diffstat) argv_array_push(&args, opt_diffstat); + if (opt_verify_signatures) + argv_array_push(&args, opt_verify_signatures); argv_array_pushv(&args, opt_strategies.argv); argv_array_pushv(&args, opt_strategy_opts.argv); if (opt_gpg_sign) diff --git a/git-rebase.sh b/git-rebase.sh index af7ba5f..dcfbc3a 100755 --- a/git-rebase.sh +++ b/git-rebase.sh @@ -38,6 +38,7 @@ whitespace=! passed to 'git apply' ignore-whitespace! passed to 'git apply' C=! passed to 'git apply' S,gpg-sign? GPG-sign commits +verify-signatures verify that the commits of onto have valid GPG signatures Actions: continue! continue abort! abort and check out the original branch @@ -88,6 +89,7 @@ autosquash= keep_empty= test "$(git config --bool rebase.autosquash)" = "true" && autosquash=t gpg_sign_opt= +verify_signatures= read_basic_state () { test -f "$state_dir/head-name" && @@ -339,6 +341,12 @@ do --gpg-sign=*) gpg_sign_opt="-S${1#--gpg-sign=}" ;; + --verify-signatures) + verify_signatures=t + ;; + --no-verify-signatures) + verify_signatures= + ;; --) shift break @@ -594,6 +602,42 @@ then fi fi +if test "$verify_signatures" +then + if test -n "$rebase_root" + then + foreign_revisions="$orig_head..$onto" + else + foreign_revisions="$orig_head..${restrict_revision-$upstream}" + fi + + for cmt in $(git rev-list --reverse "$foreign_revisions") + do + if ! git log -1 --pretty=format:'%G?%n%GS' "$cmt" | + ( + read cmt_sig + read cmt_signer + case "$cmt_sig" in + 'G') + ;; + 'U') + die "$(gettext "Commit $cmt has an untrusted GPG signature, allegedly by $cmt_signer.")" + ;; + 'B') + die "$(gettext "Commit $cmt has a bad GPG signature allegedly by $cmt_signer.")" + ;; + *) #'N' + die "$(gettext "Commit $cmt does not have a GPG signature.")" + ;; + esac + test "$verbose" && test 'G' = "$cmt_sig" && echo "Commit $cmt has a good GPG signature by $cmt_signer." + ) + then + exit 1 + fi + done +fi + # If a hook exists, give it a chance to interrupt run_pre_rebase_hook "$upstream_arg" "$@" diff --git a/t/t3427-rebase-verify-signatures.sh b/t/t3427-rebase-verify-signatures.sh new file mode 100755 index 0000000..1bd0a4d --- /dev/null +++ b/t/t3427-rebase-verify-signatures.sh @@ -0,0 +1,65 @@ +#!/bin/sh + +test_description='rebase signature verification tests' +. ./test-lib.sh +. "$TEST_DIRECTORY/lib-gpg.sh" + +test_expect_success GPG 'create signed commits' ' + echo 1 >file && git add file && + test_tick && git commit -m initial && + git tag initial && + + git checkout -b side-signed && + echo 3 >elif && git add elif && + test_tick && git commit -S -m "signed on side" && + git checkout initial && + + git checkout -b side-unsigned && + echo 3 >foo && git add foo && + test_tick && git commit -m "unsigned on side" && + git checkout initial && + + git checkout -b side-bad && + echo 3 >bar && git add bar && + test_tick && git commit -S -m "bad on side" && + git cat-file commit side-bad >raw && + sed -e "s/bad/forged bad/" raw >forged && + git hash-object -w -t commit forged >forged.commit && + git checkout initial && + + git checkout -b side-untrusted && + echo 3 >baz && git add baz && + test_tick && git commit -SB7227189 -m "untrusted on side" && + + git checkout master +' + +test_expect_success GPG 'rebase unsigned commit with verification' ' + test_must_fail git rebase --verify-signatures side-unsigned 2>rebaseerror && + test_i18ngrep "does not have a GPG signature" rebaseerror +' + +test_expect_success GPG 'rebase commit with bad signature with verification' ' + test_must_fail git rebase --verify-signatures $(cat forged.commit) 2>rebaseerror && + test_i18ngrep "has a bad GPG signature" rebaseerror +' + +test_expect_success GPG 'rebase commit with untrusted signature with verification' ' + test_must_fail git rebase --verify-signatures side-untrusted 2>rebaseerror && + test_i18ngrep "has an untrusted GPG signature" rebaseerror +' + +test_expect_success GPG 'rebase signed commit with verification' ' + git rebase --verbose --verify-signatures side-signed >rebaseoutput && + test_i18ngrep "has a good GPG signature" rebaseoutput +' + +test_expect_success GPG 'rebase commit with bad signature without verification (implicit)' ' + git rebase $(cat forged.commit) +' + +test_expect_success GPG 'rebase commit with bad signature without verification (explicit)' ' + git rebase --no-verify-signatures $(cat forged.commit) +' + +test_done -- 2.6.3 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html