git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
From: Alexander 'z33ky' Hirsch <1zeeky@gmail.com>
To: git@vger.kernel.org
Cc: "brian m. carlson" <sandals@crustytoothpaste.net>
Subject: [PATCH] rebase: add --verify-signatures
Date: Thu, 10 Dec 2015 14:03:48 +0100	[thread overview]
Message-ID: <20151210130228.GA22641@netblarch.tu-darmstadt.de> (raw)

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@gmail.com>
---

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

             reply	other threads:[~2015-12-10 12:56 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-12-10 13:03 Alexander 'z33ky' Hirsch [this message]
2015-12-10 19:11 ` [PATCH] rebase: add --verify-signatures Junio C Hamano
2015-12-10 19:53   ` Junio C Hamano
2015-12-16 13:39     ` Alexander 'z33ky' Hirsch
2015-12-16 18:12       ` Junio C Hamano
2015-12-17  1:04         ` Alexander 'z33ky' Hirsch
2015-12-17 18:22           ` Junio C Hamano
     [not found]             ` <20151221140414.GA3422@netblarch.tu-darmstadt.de>
     [not found]               ` <xmqqvb7re55d.fsf@gitster.mtv.corp.google.com>
2015-12-22 23:12                 ` Alexander 'z33ky' Hirsch

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: http://vger.kernel.org/majordomo-info.html

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20151210130228.GA22641@netblarch.tu-darmstadt.de \
    --to=1zeeky@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=sandals@crustytoothpaste.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).