[PATCH] rebase: add --verify-signatures

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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



[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]