Skip to content

Commit b771d8d

Browse files
committed
Merge branch 'mg/gpg-interface-using-status' into maint
Verification of signed tags were not done correctly when not in C or en/US locale. * mg/gpg-interface-using-status: pretty: make %GK output the signing key for signed commits pretty: parse the gpg status lines rather than the output gpg_interface: allow to request status return log-tree: rely upon the check in the gpg_interface gpg-interface: check good signature in a reliable way
2 parents 14c79b1 + 0174eea commit b771d8d

File tree

7 files changed

+46
-25
lines changed

7 files changed

+46
-25
lines changed

Documentation/pretty-formats.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ The placeholders are:
133133
- '%GG': raw verification message from GPG for a signed commit
134134
- '%G?': show either "G" for Good or "B" for Bad for a signed commit
135135
- '%GS': show the name of the signer for a signed commit
136+
- '%GK': show the key used to sign a signed commit
136137
- '%gD': reflog selector, e.g., `refs/stash@{1}`
137138
- '%gd': shortened reflog selector, e.g., `stash@{1}`
138139
- '%gn': reflog identity name

builtin/fmt-merge-msg.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -492,7 +492,7 @@ static void fmt_merge_msg_sigs(struct strbuf *out)
492492

493493
if (size == len)
494494
; /* merely annotated */
495-
else if (verify_signed_buffer(buf, len, buf + len, size - len, &sig)) {
495+
else if (verify_signed_buffer(buf, len, buf + len, size - len, &sig, NULL)) {
496496
if (!sig.len)
497497
strbuf_addstr(&sig, "gpg verification failed.\n");
498498
}

builtin/verify-tag.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ static int run_gpg_verify(const char *buf, unsigned long size, int verbose)
2929
if (size == len)
3030
return error("no signature found");
3131

32-
return verify_signed_buffer(buf, len, buf + len, size - len, NULL);
32+
return verify_signed_buffer(buf, len, buf + len, size - len, NULL, NULL);
3333
}
3434

3535
static int verify_tag(const char *name, int verbose)

gpg-interface.c

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,15 +96,18 @@ int sign_buffer(struct strbuf *buffer, struct strbuf *signature, const char *sig
9696
/*
9797
* Run "gpg" to see if the payload matches the detached signature.
9898
* gpg_output, when set, receives the diagnostic output from GPG.
99+
* gpg_status, when set, receives the status output from GPG.
99100
*/
100101
int verify_signed_buffer(const char *payload, size_t payload_size,
101102
const char *signature, size_t signature_size,
102-
struct strbuf *gpg_output)
103+
struct strbuf *gpg_output, struct strbuf *gpg_status)
103104
{
104105
struct child_process gpg;
105-
const char *args_gpg[] = {NULL, "--verify", "FILE", "-", NULL};
106+
const char *args_gpg[] = {NULL, "--status-fd=1", "--verify", "FILE", "-", NULL};
106107
char path[PATH_MAX];
107108
int fd, ret;
109+
struct strbuf buf = STRBUF_INIT;
110+
struct strbuf *pbuf = &buf;
108111

109112
args_gpg[0] = gpg_program;
110113
fd = git_mkstemp(path, PATH_MAX, ".git_vtag_tmpXXXXXX");
@@ -119,9 +122,10 @@ int verify_signed_buffer(const char *payload, size_t payload_size,
119122
memset(&gpg, 0, sizeof(gpg));
120123
gpg.argv = args_gpg;
121124
gpg.in = -1;
125+
gpg.out = -1;
122126
if (gpg_output)
123127
gpg.err = -1;
124-
args_gpg[2] = path;
128+
args_gpg[3] = path;
125129
if (start_command(&gpg)) {
126130
unlink(path);
127131
return error(_("could not run gpg."));
@@ -134,9 +138,17 @@ int verify_signed_buffer(const char *payload, size_t payload_size,
134138
strbuf_read(gpg_output, gpg.err, 0);
135139
close(gpg.err);
136140
}
141+
if (gpg_status)
142+
pbuf = gpg_status;
143+
strbuf_read(pbuf, gpg.out, 0);
144+
close(gpg.out);
145+
137146
ret = finish_command(&gpg);
138147

139148
unlink_or_warn(path);
140149

150+
ret |= !strstr(pbuf->buf, "\n[GNUPG:] GOODSIG ");
151+
strbuf_release(&buf); /* no matter it was used or not */
152+
141153
return ret;
142154
}

gpg-interface.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#define GPG_INTERFACE_H
33

44
extern int sign_buffer(struct strbuf *buffer, struct strbuf *signature, const char *signing_key);
5-
extern int verify_signed_buffer(const char *payload, size_t payload_size, const char *signature, size_t signature_size, struct strbuf *gpg_output);
5+
extern int verify_signed_buffer(const char *payload, size_t payload_size, const char *signature, size_t signature_size, struct strbuf *gpg_output, struct strbuf *gpg_status);
66
extern int git_gpg_config(const char *, const char *, void *);
77
extern void set_signing_key(const char *);
88
extern const char *get_signing_key(void);

log-tree.c

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -444,7 +444,7 @@ static void show_signature(struct rev_info *opt, struct commit *commit)
444444

445445
status = verify_signed_buffer(payload.buf, payload.len,
446446
signature.buf, signature.len,
447-
&gpg_output);
447+
&gpg_output, NULL);
448448
if (status && !gpg_output.len)
449449
strbuf_addstr(&gpg_output, "No signature\n");
450450

@@ -508,20 +508,17 @@ static void show_one_mergetag(struct rev_info *opt,
508508
gpg_message_offset = verify_message.len;
509509

510510
payload_size = parse_signature(extra->value, extra->len);
511-
if ((extra->len <= payload_size) ||
512-
(verify_signed_buffer(extra->value, payload_size,
513-
extra->value + payload_size,
514-
extra->len - payload_size,
515-
&verify_message) &&
516-
verify_message.len <= gpg_message_offset)) {
517-
strbuf_addstr(&verify_message, "No signature\n");
518-
status = -1;
519-
}
520-
else if (strstr(verify_message.buf + gpg_message_offset,
521-
": Good signature from "))
522-
status = 0;
523-
else
524-
status = -1;
511+
status = -1;
512+
if (extra->len > payload_size)
513+
if (verify_signed_buffer(extra->value, payload_size,
514+
extra->value + payload_size,
515+
extra->len - payload_size,
516+
&verify_message, NULL)) {
517+
if (verify_message.len <= gpg_message_offset)
518+
strbuf_addstr(&verify_message, "No signature\n");
519+
else
520+
status = 0;
521+
}
525522

526523
show_sig_lines(opt, status, verify_message.buf);
527524
strbuf_release(&verify_message);

pretty.c

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -769,8 +769,10 @@ struct format_commit_context {
769769
unsigned commit_signature_parsed:1;
770770
struct {
771771
char *gpg_output;
772+
char *gpg_status;
772773
char good_bad;
773774
char *signer;
775+
char *key;
774776
} signature;
775777
char *message;
776778
size_t width, indent1, indent2;
@@ -958,13 +960,13 @@ static struct {
958960
char result;
959961
const char *check;
960962
} signature_check[] = {
961-
{ 'G', ": Good signature from " },
962-
{ 'B', ": BAD signature from " },
963+
{ 'G', "\n[GNUPG:] GOODSIG " },
964+
{ 'B', "\n[GNUPG:] BADSIG " },
963965
};
964966

965967
static void parse_signature_lines(struct format_commit_context *ctx)
966968
{
967-
const char *buf = ctx->signature.gpg_output;
969+
const char *buf = ctx->signature.gpg_status;
968970
int i;
969971

970972
for (i = 0; i < ARRAY_SIZE(signature_check); i++) {
@@ -974,6 +976,8 @@ static void parse_signature_lines(struct format_commit_context *ctx)
974976
continue;
975977
ctx->signature.good_bad = signature_check[i].result;
976978
found += strlen(signature_check[i].check);
979+
ctx->signature.key = xmemdupz(found, 16);
980+
found += 17;
977981
next = strchrnul(found, '\n');
978982
ctx->signature.signer = xmemdupz(found, next - found);
979983
break;
@@ -985,6 +989,7 @@ static void parse_commit_signature(struct format_commit_context *ctx)
985989
struct strbuf payload = STRBUF_INIT;
986990
struct strbuf signature = STRBUF_INIT;
987991
struct strbuf gpg_output = STRBUF_INIT;
992+
struct strbuf gpg_status = STRBUF_INIT;
988993
int status;
989994

990995
ctx->commit_signature_parsed = 1;
@@ -994,13 +999,15 @@ static void parse_commit_signature(struct format_commit_context *ctx)
994999
goto out;
9951000
status = verify_signed_buffer(payload.buf, payload.len,
9961001
signature.buf, signature.len,
997-
&gpg_output);
1002+
&gpg_output, &gpg_status);
9981003
if (status && !gpg_output.len)
9991004
goto out;
10001005
ctx->signature.gpg_output = strbuf_detach(&gpg_output, NULL);
1006+
ctx->signature.gpg_status = strbuf_detach(&gpg_status, NULL);
10011007
parse_signature_lines(ctx);
10021008

10031009
out:
1010+
strbuf_release(&gpg_status);
10041011
strbuf_release(&gpg_output);
10051012
strbuf_release(&payload);
10061013
strbuf_release(&signature);
@@ -1210,6 +1217,10 @@ static size_t format_commit_one(struct strbuf *sb, const char *placeholder,
12101217
if (c->signature.signer)
12111218
strbuf_addstr(sb, c->signature.signer);
12121219
break;
1220+
case 'K':
1221+
if (c->signature.key)
1222+
strbuf_addstr(sb, c->signature.key);
1223+
break;
12131224
}
12141225
return 2;
12151226
}

0 commit comments

Comments
 (0)