@matheusbsbs / matheus-bagliano / commits / 54887b4689
Fork 0

gpg-interface: add minTrustLevel as a configuration option

Previously, signature verification for merge and pull operations checked if the key had a trust-level of either TRUST_NEVER or TRUST_UNDEFINED in verify_merge_signature(). If that was the case, the process die()d. The other code paths that did signature verification relied entirely on the return code from check_commit_signature(). And signatures made with a good key, irregardless of its trust level, was considered valid by check_commit_signature(). This difference in behavior might induce users to erroneously assume that the trust level of a key in their keyring is always considered by Git, even for operations where it is not (e.g. during a verify-commit or verify-tag). The way it worked was by gpg-interface.c storing the result from the key/signature status *and* the lowest-two trust levels in the `result` member of the signature_check structure (the last of these status lines that were encountered got written to `result`). These are documented in GPG under the subsection `General status codes` and `Key related`, respectively [1]. The GPG documentation says the following on the TRUST_ status codes [1]: """ These are several similar status codes: - TRUST_UNDEFINED <error_token> - TRUST_NEVER <error_token> - TRUST_MARGINAL [0 [<validation_model>]] - TRUST_FULLY [0 [<validation_model>]] - TRUST_ULTIMATE [0 [<validation_model>]] For good signatures one of these status lines are emitted to indicate the validity of the key used to create the signature. The error token values are currently only emitted by gpgsm. """ My interpretation is that the trust level is conceptionally different from the validity of the key and/or signature. That seems to also have been the assumption of the old code in check_signature() where a result of 'G' (as in GOODSIG) and 'U' (as in TRUST_NEVER or TRUST_UNDEFINED) were both considered a success. The two cases where a result of 'U' had special meaning were in verify_merge_signature() (where this caused git to die()) and in format_commit_one() (where it affected the output of the %G? format specifier). I think it makes sense to refactor the processing of TRUST_ status lines such that users can configure a minimum trust level that is enforced globally, rather than have individual parts of git (e.g. merge) do it themselves (except for a grace period with backward compatibility). I also think it makes sense to not store the trust level in the same struct member as the key/signature status. While the presence of a TRUST_ status code does imply that the signature is good (see the first paragraph in the included snippet above), as far as I can tell, the order of the status lines from GPG isn't well-defined; thus it would seem plausible that the trust level could be overwritten with the key/signature status if they were stored in the same member of the signature_check structure. This patch introduces a new configuration option: gpg.minTrustLevel. It consolidates trust-level verification to gpg-interface.c and adds a new `trust_level` member to the signature_check structure. Backward-compatibility is maintained by introducing a special case in verify_merge_signature() such that if no user-configurable gpg.minTrustLevel is set, then the old behavior of rejecting TRUST_UNDEFINED and TRUST_NEVER is enforced. If, on the other hand, gpg.minTrustLevel is set, then that value overrides the old behavior. Similarly, the %G? format specifier will continue show 'U' for signatures made with a key that has a trust level of TRUST_UNDEFINED or TRUST_NEVER, even though the 'U' character no longer exist in the `result` member of the signature_check structure. A new format specifier, %GT, is also introduced for users that want to show all possible trust levels for a signature. Another approach would have been to simply drop the trust-level requirement in verify_merge_signature(). This would also have made the behavior consistent with other parts of git that perform signature verification. However, requiring a minimum trust level for signing keys does seem to have a real-world use-case. For example, the build system used by the Qubes OS project currently parses the raw output from verify-tag in order to assert a minimum trust level for keys used to sign git tags [2]. [1] https://git.gnupg.org/cgi-bin/gitweb.cgi?p=gnupg.git;a=blob;f=doc/doc/DETAILS;h=bd00006e933ac56719b1edd2478ecd79273eae72;hb=refs/heads/master [2] https://github.com/QubesOS/qubes-builder/blob/9674c1991deef45b1a1b1c71fddfab14ba50dccf/scripts/verify-git-tag#L43 Signed-off-by: Hans Jerry Illikainen <hji@dyntopia.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Hans Jerry Illikainen committed Dec 27, 2019 at 13:55 UTC 54887b46890582e60fcb8ee1f287f62870c2ac0f
13 files changed +319 -23
Documentation/config/gpg.txt
+15
@@ -18,3 +18,18 @@ gpg.<format>.program::
18 chose. (see `gpg.program` and `gpg.format`) `gpg.program` can still
19 be used as a legacy synonym for `gpg.openpgp.program`. The default
20 value for `gpg.x509.program` is "gpgsm".
21 +
22 +gpg.minTrustLevel::
23 + Specifies a minimum trust level for signature verification. If
24 + this option is unset, then signature verification for merge
25 + operations require a key with at least `marginal` trust. Other
26 + operations that perform signature verification require a key
27 + with at least `undefined` trust. Setting this option overrides
28 + the required trust-level for all operations. Supported values,
29 + in increasing order of significance:
30 ++
31 +* `undefined`
32 +* `never`
33 +* `marginal`
34 +* `fully`
35 +* `ultimate`
Documentation/pretty-formats.txt
+1
@@ -213,6 +213,7 @@ endif::git-rev-list[]
213 '%GF':: show the fingerprint of the key used to sign a signed commit
214 '%GP':: show the fingerprint of the primary key whose subkey was used
215 to sign a signed commit
216 +'%GT':: show the trust level for the key used to sign a signed commit
217 '%gD':: reflog selector, e.g., `refs/stash@{1}` or `refs/stash@{2
218 minutes ago}`; the format follows the rules described for the
219 `-g` option. The portion before the `@` is the refname as
builtin/merge.c
+7 -2
@@ -62,6 +62,7 @@ static int show_diffstat = 1, shortlog_len = -1, squash;
62 static int option_commit = -1;
63 static int option_edit = -1;
64 static int allow_trivial = 1, have_message, verify_signatures;
65 +static int check_trust_level = 1;
66 static int overwrite_ignore = 1;
67 static struct strbuf merge_msg = STRBUF_INIT;
68 static struct strategy **use_strategies;
@@ -631,6 +632,8 @@ static int git_merge_config(const char *k, const char *v, void *cb)
632 } else if (!strcmp(k, "commit.gpgsign")) {
633 sign_commit = git_config_bool(k, v) ? "" : NULL;
634 return 0;
635 + } else if (!strcmp(k, "gpg.mintrustlevel")) {
636 + check_trust_level = 0;
637 }
638
639 status = fmt_merge_msg_config(k, v, cb);
@@ -1397,7 +1400,8 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
1400 die(_("Can merge only exactly one commit into empty head"));
1401
1402 if (verify_signatures)
1400 - verify_merge_signature(remoteheads->item, verbosity);
1403 + verify_merge_signature(remoteheads->item, verbosity,
1404 + check_trust_level);
1405
1406 remote_head_oid = &remoteheads->item->object.oid;
1407 read_empty(remote_head_oid, 0);
@@ -1420,7 +1424,8 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
1424
1425 if (verify_signatures) {
1426 for (p = remoteheads; p; p = p->next) {
1423 - verify_merge_signature(p->item, verbosity);
1427 + verify_merge_signature(p->item, verbosity,
1428 + check_trust_level);
1429 }
1430 }
1431
builtin/pull.c
+12 -1
@@ -107,6 +107,7 @@ static char *opt_ff;
107 static char *opt_verify_signatures;
108 static int opt_autostash = -1;
109 static int config_autostash;
110 +static int check_trust_level = 1;
111 static struct argv_array opt_strategies = ARGV_ARRAY_INIT;
112 static struct argv_array opt_strategy_opts = ARGV_ARRAY_INIT;
113 static char *opt_gpg_sign;
@@ -355,6 +356,8 @@ static enum rebase_type config_get_rebase(void)
356 */
357 static int git_pull_config(const char *var, const char *value, void *cb)
358 {
359 + int status;
360 +
361 if (!strcmp(var, "rebase.autostash")) {
362 config_autostash = git_config_bool(var, value);
363 return 0;
@@ -362,7 +365,14 @@ static int git_pull_config(const char *var, const char *value, void *cb)
365 recurse_submodules = git_config_bool(var, value) ?
366 RECURSE_SUBMODULES_ON : RECURSE_SUBMODULES_OFF;
367 return 0;
368 + } else if (!strcmp(var, "gpg.mintrustlevel")) {
369 + check_trust_level = 0;
370 }
371 +
372 + status = git_gpg_config(var, value, cb);
373 + if (status)
374 + return status;
375 +
376 return git_default_config(var, value, cb);
377 }
378
@@ -587,7 +597,8 @@ static int pull_into_void(const struct object_id *merge_head,
597 die(_("unable to access commit %s"),
598 oid_to_hex(merge_head));
599
590 - verify_merge_signature(commit, opt_verbosity);
600 + verify_merge_signature(commit, opt_verbosity,
601 + check_trust_level);
602 }
603
604 /*
commit.c
+7 -5
@@ -1136,21 +1136,23 @@ int check_commit_signature(const struct commit *commit, struct signature_check *
1136 return ret;
1137 }
1138
1139 -void verify_merge_signature(struct commit *commit, int verbosity)
1139 +void verify_merge_signature(struct commit *commit, int verbosity,
1140 + int check_trust)
1141 {
1142 char hex[GIT_MAX_HEXSZ + 1];
1143 struct signature_check signature_check;
1144 + int ret;
1145 memset(&signature_check, 0, sizeof(signature_check));
1146
1145 - check_commit_signature(commit, &signature_check);
1147 + ret = check_commit_signature(commit, &signature_check);
1148
1149 find_unique_abbrev_r(hex, &commit->object.oid, DEFAULT_ABBREV);
1150 switch (signature_check.result) {
1151 case 'G':
1152 + if (ret || (check_trust && signature_check.trust_level < TRUST_MARGINAL))
1153 + die(_("Commit %s has an untrusted GPG signature, "
1154 + "allegedly by %s."), hex, signature_check.signer);
1155 break;
1151 - case 'U':
1152 - die(_("Commit %s has an untrusted GPG signature, "
1153 - "allegedly by %s."), hex, signature_check.signer);
1156 case 'B':
1157 die(_("Commit %s has a bad GPG signature "
1158 "allegedly by %s."), hex, signature_check.signer);
commit.h
+11 -1
@@ -383,8 +383,18 @@ int compare_commits_by_author_date(const void *a_, const void *b_, void *unused)
383 * Verify a single commit with check_commit_signature() and die() if it is not
384 * a good signature. This isn't really suitable for general use, but is a
385 * helper to implement consistent logic for pull/merge --verify-signatures.
386 + *
387 + * The check_trust parameter is meant for backward-compatibility. The GPG
388 + * interface verifies key trust with a default trust level that is below the
389 + * default trust level for merge operations. Its value should be non-zero if
390 + * the user hasn't set a minimum trust level explicitly in their configuration.
391 + *
392 + * If the user has set a minimum trust level, then that value should be obeyed
393 + * and check_trust should be zero, even if the configured trust level is below
394 + * the default trust level for merges.
395 */
387 -void verify_merge_signature(struct commit *commit, int verbose);
396 +void verify_merge_signature(struct commit *commit, int verbose,
397 + int check_trust);
398
399 int compare_commits_by_commit_date(const void *a_, const void *b_, void *unused);
400 int compare_commits_by_gen_then_commit_date(const void *a_, const void *b_, void *unused);
gpg-interface.c
+79 -12
@@ -7,6 +7,8 @@
7 #include "tempfile.h"
8
9 static char *configured_signing_key;
10 +static enum signature_trust_level configured_min_trust_level = TRUST_UNDEFINED;
11 +
12 struct gpg_format {
13 const char *name;
14 const char *program;
@@ -85,6 +87,8 @@ void signature_check_clear(struct signature_check *sigc)
87 #define GPG_STATUS_UID (1<<2)
88 /* The status includes key fingerprints */
89 #define GPG_STATUS_FINGERPRINT (1<<3)
90 +/* The status includes trust level */
91 +#define GPG_STATUS_TRUST_LEVEL (1<<4)
92
93 /* Short-hand for standard exclusive *SIG status with keyid & UID */
94 #define GPG_STATUS_STDSIG (GPG_STATUS_EXCLUSIVE|GPG_STATUS_KEYID|GPG_STATUS_UID)
@@ -96,13 +100,23 @@ static struct {
100 } sigcheck_gpg_status[] = {
101 { 'G', "GOODSIG ", GPG_STATUS_STDSIG },
102 { 'B', "BADSIG ", GPG_STATUS_STDSIG },
99 - { 'U', "TRUST_NEVER", 0 },
100 - { 'U', "TRUST_UNDEFINED", 0 },
103 { 'E', "ERRSIG ", GPG_STATUS_EXCLUSIVE|GPG_STATUS_KEYID },
104 { 'X', "EXPSIG ", GPG_STATUS_STDSIG },
105 { 'Y', "EXPKEYSIG ", GPG_STATUS_STDSIG },
106 { 'R', "REVKEYSIG ", GPG_STATUS_STDSIG },
107 { 0, "VALIDSIG ", GPG_STATUS_FINGERPRINT },
108 + { 0, "TRUST_", GPG_STATUS_TRUST_LEVEL },
109 +};
110 +
111 +static struct {
112 + const char *key;
113 + enum signature_trust_level value;
114 +} sigcheck_gpg_trust_level[] = {
115 + { "UNDEFINED", TRUST_UNDEFINED },
116 + { "NEVER", TRUST_NEVER },
117 + { "MARGINAL", TRUST_MARGINAL },
118 + { "FULLY", TRUST_FULLY },
119 + { "ULTIMATE", TRUST_ULTIMATE },
120 };
121
122 static void replace_cstring(char **field, const char *line, const char *next)
@@ -115,6 +129,20 @@ static void replace_cstring(char **field, const char *line, const char *next)
129 *field = NULL;
130 }
131
132 +static int parse_gpg_trust_level(const char *level,
133 + enum signature_trust_level *res)
134 +{
135 + size_t i;
136 +
137 + for (i = 0; i < ARRAY_SIZE(sigcheck_gpg_trust_level); i++) {
138 + if (!strcmp(sigcheck_gpg_trust_level[i].key, level)) {
139 + *res = sigcheck_gpg_trust_level[i].value;
140 + return 0;
141 + }
142 + }
143 + return 1;
144 +}
145 +
146 static void parse_gpg_output(struct signature_check *sigc)
147 {
148 const char *buf = sigc->gpg_status;
@@ -136,9 +164,18 @@ static void parse_gpg_output(struct signature_check *sigc)
164 /* Iterate over all search strings */
165 for (i = 0; i < ARRAY_SIZE(sigcheck_gpg_status); i++) {
166 if (skip_prefix(line, sigcheck_gpg_status[i].check, &line)) {
167 + /*
168 + * GOODSIG, BADSIG etc. can occur only once for
169 + * each signature. Therefore, if we had more
170 + * than one then we're dealing with multiple
171 + * signatures. We don't support them
172 + * currently, and they're rather hard to
173 + * create, so something is likely fishy and we
174 + * should reject them altogether.
175 + */
176 if (sigcheck_gpg_status[i].flags & GPG_STATUS_EXCLUSIVE) {
177 if (seen_exclusive_status++)
141 - goto found_duplicate_status;
178 + goto error;
179 }
180
181 if (sigcheck_gpg_status[i].result)
@@ -154,6 +191,25 @@ static void parse_gpg_output(struct signature_check *sigc)
191 replace_cstring(&sigc->signer, line, next);
192 }
193 }
194 +
195 + /* Do we have trust level? */
196 + if (sigcheck_gpg_status[i].flags & GPG_STATUS_TRUST_LEVEL) {
197 + /*
198 + * GPG v1 and v2 differs in how the
199 + * TRUST_ lines are written. Some
200 + * trust lines contain no additional
201 + * space-separated information for v1.
202 + */
203 + size_t trust_size = strcspn(line, " \n");
204 + char *trust = xmemdupz(line, trust_size);
205 +
206 + if (parse_gpg_trust_level(trust, &sigc->trust_level)) {
207 + free(trust);
208 + goto error;
209 + }
210 + free(trust);
211 + }
212 +
213 /* Do we have fingerprint? */
214 if (sigcheck_gpg_status[i].flags & GPG_STATUS_FINGERPRINT) {
215 const char *limit;
@@ -191,14 +247,7 @@ static void parse_gpg_output(struct signature_check *sigc)
247 }
248 return;
249
194 -found_duplicate_status:
195 - /*
196 - * GOODSIG, BADSIG etc. can occur only once for each signature.
197 - * Therefore, if we had more than one then we're dealing with multiple
198 - * signatures. We don't support them currently, and they're rather
199 - * hard to create, so something is likely fishy and we should reject
200 - * them altogether.
201 - */
250 +error:
251 sigc->result = 'E';
252 /* Clear partial data to avoid confusion */
253 FREE_AND_NULL(sigc->primary_key_fingerprint);
@@ -215,6 +264,7 @@ int check_signature(const char *payload, size_t plen, const char *signature,
264 int status;
265
266 sigc->result = 'N';
267 + sigc->trust_level = -1;
268
269 status = verify_signed_buffer(payload, plen, signature, slen,
270 &gpg_output, &gpg_status);
@@ -224,7 +274,8 @@ int check_signature(const char *payload, size_t plen, const char *signature,
274 sigc->gpg_output = strbuf_detach(&gpg_output, NULL);
275 sigc->gpg_status = strbuf_detach(&gpg_status, NULL);
276 parse_gpg_output(sigc);
227 - status |= sigc->result != 'G' && sigc->result != 'U';
277 + status |= sigc->result != 'G';
278 + status |= sigc->trust_level < configured_min_trust_level;
279
280 out:
281 strbuf_release(&gpg_status);
@@ -271,6 +322,8 @@ int git_gpg_config(const char *var, const char *value, void *cb)
322 {
323 struct gpg_format *fmt = NULL;
324 char *fmtname = NULL;
325 + char *trust;
326 + int ret;
327
328 if (!strcmp(var, "user.signingkey")) {
329 if (!value)
@@ -290,6 +343,20 @@ int git_gpg_config(const char *var, const char *value, void *cb)
343 return 0;
344 }
345
346 + if (!strcmp(var, "gpg.mintrustlevel")) {
347 + if (!value)
348 + return config_error_nonbool(var);
349 +
350 + trust = xstrdup_toupper(value);
351 + ret = parse_gpg_trust_level(trust, &configured_min_trust_level);
352 + free(trust);
353 +
354 + if (ret)
355 + return error("unsupported value for %s: %s", var,
356 + value);
357 + return 0;
358 + }
359 +
360 if (!strcmp(var, "gpg.program") || !strcmp(var, "gpg.openpgp.program"))
361 fmtname = "openpgp";
362
gpg-interface.h
+9 -1
@@ -7,6 +7,14 @@ struct strbuf;
7 #define GPG_VERIFY_RAW 2
8 #define GPG_VERIFY_OMIT_STATUS 4
9
10 +enum signature_trust_level {
11 + TRUST_UNDEFINED,
12 + TRUST_NEVER,
13 + TRUST_MARGINAL,
14 + TRUST_FULLY,
15 + TRUST_ULTIMATE,
16 +};
17 +
18 struct signature_check {
19 char *payload;
20 char *gpg_output;
@@ -16,7 +24,6 @@ struct signature_check {
24 * possible "result":
25 * 0 (not checked)
26 * N (checked but no further result)
19 - * U (untrusted good)
27 * G (good)
28 * B (bad)
29 */
@@ -25,6 +32,7 @@ struct signature_check {
32 char *key;
33 char *fingerprint;
34 char *primary_key_fingerprint;
35 + enum signature_trust_level trust_level;
36 };
37
38 void signature_check_clear(struct signature_check *sigc);
pretty.c
+29 -1
@@ -1303,9 +1303,18 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
1303 case '?':
1304 switch (c->signature_check.result) {
1305 case 'G':
1306 + switch (c->signature_check.trust_level) {
1307 + case TRUST_UNDEFINED:
1308 + case TRUST_NEVER:
1309 + strbuf_addch(sb, 'U');
1310 + break;
1311 + default:
1312 + strbuf_addch(sb, 'G');
1313 + break;
1314 + }
1315 + break;
1316 case 'B':
1317 case 'E':
1308 - case 'U':
1318 case 'N':
1319 case 'X':
1320 case 'Y':
@@ -1329,6 +1338,25 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
1338 if (c->signature_check.primary_key_fingerprint)
1339 strbuf_addstr(sb, c->signature_check.primary_key_fingerprint);
1340 break;
1341 + case 'T':
1342 + switch (c->signature_check.trust_level) {
1343 + case TRUST_UNDEFINED:
1344 + strbuf_addstr(sb, "undefined");
1345 + break;
1346 + case TRUST_NEVER:
1347 + strbuf_addstr(sb, "never");
1348 + break;
1349 + case TRUST_MARGINAL:
1350 + strbuf_addstr(sb, "marginal");
1351 + break;
1352 + case TRUST_FULLY:
1353 + strbuf_addstr(sb, "fully");
1354 + break;
1355 + case TRUST_ULTIMATE:
1356 + strbuf_addstr(sb, "ultimate");
1357 + break;
1358 + }
1359 + break;
1360 default:
1361 return 0;
1362 }
t/t5573-pull-verify-signatures.sh
+64
@@ -60,6 +60,27 @@ test_expect_success GPG 'pull commit with untrusted signature with --verify-sign
60 test_i18ngrep "has an untrusted GPG signature" pullerror
61 '
62
63 +test_expect_success GPG 'pull commit with untrusted signature with --verify-signatures and minTrustLevel=ultimate' '
64 + test_when_finished "git reset --hard && git checkout initial" &&
65 + test_config gpg.minTrustLevel ultimate &&
66 + test_must_fail git pull --ff-only --verify-signatures untrusted 2>pullerror &&
67 + test_i18ngrep "has an untrusted GPG signature" pullerror
68 +'
69 +
70 +test_expect_success GPG 'pull commit with untrusted signature with --verify-signatures and minTrustLevel=marginal' '
71 + test_when_finished "git reset --hard && git checkout initial" &&
72 + test_config gpg.minTrustLevel marginal &&
73 + test_must_fail git pull --ff-only --verify-signatures untrusted 2>pullerror &&
74 + test_i18ngrep "has an untrusted GPG signature" pullerror
75 +'
76 +
77 +test_expect_success GPG 'pull commit with untrusted signature with --verify-signatures and minTrustLevel=undefined' '
78 + test_when_finished "git reset --hard && git checkout initial" &&
79 + test_config gpg.minTrustLevel undefined &&
80 + git pull --ff-only --verify-signatures untrusted >pulloutput &&
81 + test_i18ngrep "has a good GPG signature" pulloutput
82 +'
83 +
84 test_expect_success GPG 'pull signed commit with --verify-signatures' '
85 test_when_finished "git reset --hard && git checkout initial" &&
86 git pull --verify-signatures signed >pulloutput &&
@@ -79,10 +100,53 @@ test_expect_success GPG 'pull commit with bad signature with --no-verify-signatu
100 '
101
102 test_expect_success GPG 'pull unsigned commit into unborn branch' '
103 + test_when_finished "rm -rf empty-repo" &&
104 git init empty-repo &&
105 test_must_fail \
106 git -C empty-repo pull --verify-signatures .. 2>pullerror &&
107 test_i18ngrep "does not have a GPG signature" pullerror
108 '
109
110 +test_expect_success GPG 'pull commit into unborn branch with bad signature and --verify-signatures' '
111 + test_when_finished "rm -rf empty-repo" &&
112 + git init empty-repo &&
113 + test_must_fail \
114 + git -C empty-repo pull --ff-only --verify-signatures ../bad 2>pullerror &&
115 + test_i18ngrep "has a bad GPG signature" pullerror
116 +'
117 +
118 +test_expect_success GPG 'pull commit into unborn branch with untrusted signature and --verify-signatures' '
119 + test_when_finished "rm -rf empty-repo" &&
120 + git init empty-repo &&
121 + test_must_fail \
122 + git -C empty-repo pull --ff-only --verify-signatures ../untrusted 2>pullerror &&
123 + test_i18ngrep "has an untrusted GPG signature" pullerror
124 +'
125 +
126 +test_expect_success GPG 'pull commit into unborn branch with untrusted signature and --verify-signatures and minTrustLevel=ultimate' '
127 + test_when_finished "rm -rf empty-repo" &&
128 + git init empty-repo &&
129 + test_config_global gpg.minTrustLevel ultimate &&
130 + test_must_fail \
131 + git -C empty-repo pull --ff-only --verify-signatures ../untrusted 2>pullerror &&
132 + test_i18ngrep "has an untrusted GPG signature" pullerror
133 +'
134 +
135 +test_expect_success GPG 'pull commit into unborn branch with untrusted signature and --verify-signatures and minTrustLevel=marginal' '
136 + test_when_finished "rm -rf empty-repo" &&
137 + git init empty-repo &&
138 + test_config_global gpg.minTrustLevel marginal &&
139 + test_must_fail \
140 + git -C empty-repo pull --ff-only --verify-signatures ../untrusted 2>pullerror &&
141 + test_i18ngrep "has an untrusted GPG signature" pullerror
142 +'
143 +
144 +test_expect_success GPG 'pull commit into unborn branch with untrusted signature and --verify-signatures and minTrustLevel=undefined' '
145 + test_when_finished "rm -rf empty-repo" &&
146 + git init empty-repo &&
147 + test_config_global gpg.minTrustLevel undefined &&
148 + git -C empty-repo pull --ff-only --verify-signatures ../untrusted >pulloutput &&
149 + test_i18ngrep "has a good GPG signature" pulloutput
150 +'
151 +
152 test_done
t/t7030-verify-tag.sh
+24
@@ -86,6 +86,30 @@ test_expect_success GPGSM 'verify and show signatures x509' '
86 echo ninth-signed-x509 OK
87 '
88
89 +test_expect_success GPGSM 'verify and show signatures x509 with low minTrustLevel' '
90 + test_config gpg.minTrustLevel undefined &&
91 + git verify-tag ninth-signed-x509 2>actual &&
92 + grep "Good signature from" actual &&
93 + ! grep "BAD signature from" actual &&
94 + echo ninth-signed-x509 OK
95 +'
96 +
97 +test_expect_success GPGSM 'verify and show signatures x509 with matching minTrustLevel' '
98 + test_config gpg.minTrustLevel fully &&
99 + git verify-tag ninth-signed-x509 2>actual &&
100 + grep "Good signature from" actual &&
101 + ! grep "BAD signature from" actual &&
102 + echo ninth-signed-x509 OK
103 +'
104 +
105 +test_expect_success GPGSM 'verify and show signatures x509 with high minTrustLevel' '
106 + test_config gpg.minTrustLevel ultimate &&
107 + test_must_fail git verify-tag ninth-signed-x509 2>actual &&
108 + grep "Good signature from" actual &&
109 + ! grep "BAD signature from" actual &&
110 + echo ninth-signed-x509 OK
111 +'
112 +
113 test_expect_success GPG 'detect fudged signature' '
114 git cat-file tag seventh-signed >raw &&
115 sed -e "/^tag / s/seventh/7th forged/" raw >forged1 &&
t/t7510-signed-commit.sh
+39
@@ -109,6 +109,21 @@ test_expect_success GPG 'verify-commit exits success on untrusted signature' '
109 grep "not certified" actual
110 '
111
112 +test_expect_success GPG 'verify-commit exits success with matching minTrustLevel' '
113 + test_config gpg.minTrustLevel ultimate &&
114 + git verify-commit sixth-signed
115 +'
116 +
117 +test_expect_success GPG 'verify-commit exits success with low minTrustLevel' '
118 + test_config gpg.minTrustLevel fully &&
119 + git verify-commit sixth-signed
120 +'
121 +
122 +test_expect_success GPG 'verify-commit exits failure with high minTrustLevel' '
123 + test_config gpg.minTrustLevel ultimate &&
124 + test_must_fail git verify-commit eighth-signed-alt
125 +'
126 +
127 test_expect_success GPG 'verify signatures with --raw' '
128 (
129 for commit in initial second merge fourth-signed fifth-signed sixth-signed seventh-signed
@@ -219,6 +234,30 @@ test_expect_success GPG 'show untrusted signature with custom format' '
234 test_cmp expect actual
235 '
236
237 +test_expect_success GPG 'show untrusted signature with undefined trust level' '
238 + cat >expect <<-\EOF &&
239 + undefined
240 + 65A0EEA02E30CAD7
241 + Eris Discordia <discord@example.net>
242 + F8364A59E07FFE9F4D63005A65A0EEA02E30CAD7
243 + D4BE22311AD3131E5EDA29A461092E85B7227189
244 + EOF
245 + git log -1 --format="%GT%n%GK%n%GS%n%GF%n%GP" eighth-signed-alt >actual &&
246 + test_cmp expect actual
247 +'
248 +
249 +test_expect_success GPG 'show untrusted signature with ultimate trust level' '
250 + cat >expect <<-\EOF &&
251 + ultimate
252 + 13B6F51ECDDE430D
253 + C O Mitter <committer@example.com>
254 + 73D758744BE721698EC54E8713B6F51ECDDE430D
255 + 73D758744BE721698EC54E8713B6F51ECDDE430D
256 + EOF
257 + git log -1 --format="%GT%n%GK%n%GS%n%GF%n%GP" sixth-signed >actual &&
258 + test_cmp expect actual
259 +'
260 +
261 test_expect_success GPG 'show unknown signature with custom format' '
262 cat >expect <<-\EOF &&
263 E
t/t7612-merge-verify-signatures.sh
+22
@@ -66,6 +66,20 @@ test_expect_success GPG 'merge commit with untrusted signature with verification
66 test_i18ngrep "has an untrusted GPG signature" mergeerror
67 '
68
69 +test_expect_success GPG 'merge commit with untrusted signature with verification and high minTrustLevel' '
70 + test_when_finished "git reset --hard && git checkout initial" &&
71 + test_config gpg.minTrustLevel marginal &&
72 + test_must_fail git merge --ff-only --verify-signatures side-untrusted 2>mergeerror &&
73 + test_i18ngrep "has an untrusted GPG signature" mergeerror
74 +'
75 +
76 +test_expect_success GPG 'merge commit with untrusted signature with verification and low minTrustLevel' '
77 + test_when_finished "git reset --hard && git checkout initial" &&
78 + test_config gpg.minTrustLevel undefined &&
79 + git merge --ff-only --verify-signatures side-untrusted >mergeoutput &&
80 + test_i18ngrep "has a good GPG signature" mergeoutput
81 +'
82 +
83 test_expect_success GPG 'merge commit with untrusted signature with merge.verifySignatures=true' '
84 test_when_finished "git reset --hard && git checkout initial" &&
85 test_config merge.verifySignatures true &&
@@ -73,6 +87,14 @@ test_expect_success GPG 'merge commit with untrusted signature with merge.verify
87 test_i18ngrep "has an untrusted GPG signature" mergeerror
88 '
89
90 +test_expect_success GPG 'merge commit with untrusted signature with merge.verifySignatures=true and minTrustLevel' '
91 + test_when_finished "git reset --hard && git checkout initial" &&
92 + test_config merge.verifySignatures true &&
93 + test_config gpg.minTrustLevel marginal &&
94 + test_must_fail git merge --ff-only side-untrusted 2>mergeerror &&
95 + test_i18ngrep "has an untrusted GPG signature" mergeerror
96 +'
97 +
98 test_expect_success GPG 'merge signed commit with verification' '
99 test_when_finished "git reset --hard && git checkout initial" &&
100 git merge --verbose --ff-only --verify-signatures side-signed >mergeoutput &&