merge/pull Check for untrusted good GPG signatures

When --verify-signatures is specified, abort the merge in case a good GPG signature from an untrusted key is encountered. Signed-off-by: Sebastian Götte <jaseg@physik-pool.tu-berlin.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Sebastian Götte committed Mar 31, 2013 at 18:02 UTC eb307ae7bb78ccde4e2ac69f302ccf8834883628
10 files changed +29 -12
Documentation/merge-options.txt
+2 -2
@@ -85,8 +85,8 @@ option can be used to override --squash.
85
86 --verify-signatures::
87 --no-verify-signatures::
88 - Verify that the commits being merged have good GPG signatures and abort the
89 - merge in case they do not.
88 + Verify that the commits being merged have good and trusted GPG signatures
89 + and abort the merge in case they do not.
90
91 --summary::
92 --no-summary::
builtin/merge.c
+3
@@ -1248,6 +1248,9 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
1248 switch (signature_check.result) {
1249 case 'G':
1250 break;
1251 + case 'U':
1252 + die(_("Commit %s has an untrusted GPG signature, "
1253 + "allegedly by %s."), hex, signature_check.signer);
1254 case 'B':
1255 die(_("Commit %s has a bad GPG signature "
1256 "allegedly by %s."), hex, signature_check.signer);
commit.c
+9 -5
@@ -1047,6 +1047,8 @@ static struct {
1047 } sigcheck_gpg_status[] = {
1048 { 'G', "\n[GNUPG:] GOODSIG " },
1049 { 'B', "\n[GNUPG:] BADSIG " },
1050 + { 'U', "\n[GNUPG:] TRUST_NEVER" },
1051 + { 'U', "\n[GNUPG:] TRUST_UNDEFINED" },
1052 };
1053
1054 static void parse_gpg_output(struct signature_check *sigc)
@@ -1068,11 +1070,13 @@ static void parse_gpg_output(struct signature_check *sigc)
1070 found += strlen(sigcheck_gpg_status[i].check);
1071 }
1072 sigc->result = sigcheck_gpg_status[i].result;
1071 - sigc->key = xmemdupz(found, 16);
1072 - found += 17;
1073 - next = strchrnul(found, '\n');
1074 - sigc->signer = xmemdupz(found, next - found);
1075 - break;
1073 + /* The trust messages are not followed by key/signer information */
1074 + if (sigc->result != 'U') {
1075 + sigc->key = xmemdupz(found, 16);
1076 + found += 17;
1077 + next = strchrnul(found, '\n');
1078 + sigc->signer = xmemdupz(found, next - found);
1079 + }
1080 }
1081 }
1082
commit.h
+5 -5
@@ -234,11 +234,11 @@ extern void print_commit_list(struct commit_list *list,
234 const char *format_last);
235
236 /*
237 - * Check the signature of the given commit. The result of the check is stored in
238 - * sig->result, 'G' for a good signature, 'B' for a bad signature and 'N'
239 - * for no signature at all.
240 - * This may allocate memory for sig->gpg_output, sig->gpg_status, sig->signer
241 - * and sig->key.
237 + * Check the signature of the given commit. The result of the check is stored
238 + * in sig->check_result, 'G' for a good signature, 'U' for a good signature
239 + * from an untrusted signer, 'B' for a bad signature and 'N' for no signature
240 + * at all. This may allocate memory for sig->gpg_output, sig->gpg_status,
241 + * sig->signer and sig->key.
242 */
243 extern void check_commit_signature(const struct commit* commit, struct signature_check *sigc);
244
gpg-interface.h
+1
@@ -6,6 +6,7 @@ struct signature_check {
6 char *gpg_status;
7 char result; /* 0 (not checked),
8 * N (checked but no further result),
9 + * U (untrusted good),
10 * G (good)
11 * B (bad) */
12 char *signer;
t/lib-gpg/pubring.gpg
Binary files a/t/lib-gpg/pubring.gpg and b/t/lib-gpg/pubring.gpg differ
t/lib-gpg/random_seed
Binary files a/t/lib-gpg/random_seed and b/t/lib-gpg/random_seed differ
t/lib-gpg/secring.gpg
Binary files a/t/lib-gpg/secring.gpg and b/t/lib-gpg/secring.gpg differ
t/lib-gpg/trustdb.gpg
Binary files a/t/lib-gpg/trustdb.gpg and b/t/lib-gpg/trustdb.gpg differ
t/t7612-merge-verify-signatures.sh
+9
@@ -27,6 +27,10 @@ test_expect_success GPG 'create signed commits' '
27 git hash-object -w -t commit forged >forged.commit &&
28 git checkout initial &&
29
30 + git checkout -b side-untrusted &&
31 + echo 3 >baz && git add baz &&
32 + test_tick && git commit -SB7227189 -m "untrusted on side"
33 +
34 git checkout master
35 '
36
@@ -40,6 +44,11 @@ test_expect_success GPG 'merge commit with bad signature with verification' '
44 test_i18ngrep "has a bad GPG signature" mergeerror
45 '
46
47 +test_expect_success GPG 'merge commit with untrusted signature with verification' '
48 + test_must_fail git merge --ff-only --verify-signatures side-untrusted 2>mergeerror &&
49 + test_i18ngrep "has an untrusted GPG signature" mergeerror
50 +'
51 +
52 test_expect_success GPG 'merge signed commit with verification' '
53 git merge --verbose --ff-only --verify-signatures side-signed >mergeoutput &&
54 test_i18ngrep "has a good GPG signature" mergeoutput