Skip to content

Commit 482c119

Browse files
bk2204gitster
authored andcommitted
gpg-interface: improve interface for parsing tags
We have a function which parses a buffer with a signature at the end, parse_signature, and this function is used for signed tags. However, we'll need to store values for multiple algorithms, and we'll do this by using a header for the non-default algorithm. Adjust the parse_signature interface to store the parsed data in two strbufs and turn the existing function into parse_signed_buffer. The latter is still used in places where we know we always have a signed buffer, such as push certs. Adjust all the callers to deal with this new interface. Signed-off-by: brian m. carlson <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 1fb5cf0 commit 482c119

File tree

9 files changed

+87
-39
lines changed

9 files changed

+87
-39
lines changed

builtin/receive-pack.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -764,7 +764,7 @@ static void prepare_push_cert_sha1(struct child_process *proc)
764764

765765
memset(&sigcheck, '\0', sizeof(sigcheck));
766766

767-
bogs = parse_signature(push_cert.buf, push_cert.len);
767+
bogs = parse_signed_buffer(push_cert.buf, push_cert.len);
768768
check_signature(push_cert.buf, bogs, push_cert.buf + bogs,
769769
push_cert.len - bogs, &sigcheck);
770770

@@ -2050,7 +2050,7 @@ static void queue_commands_from_cert(struct command **tail,
20502050
die("malformed push certificate %.*s", 100, push_cert->buf);
20512051
else
20522052
boc += 2;
2053-
eoc = push_cert->buf + parse_signature(push_cert->buf, push_cert->len);
2053+
eoc = push_cert->buf + parse_signed_buffer(push_cert->buf, push_cert->len);
20542054

20552055
while (boc < eoc) {
20562056
const char *eol = memchr(boc, '\n', eoc - boc);

builtin/tag.c

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -174,11 +174,17 @@ static void write_tag_body(int fd, const struct object_id *oid)
174174
{
175175
unsigned long size;
176176
enum object_type type;
177-
char *buf, *sp;
177+
char *buf, *sp, *orig;
178+
struct strbuf payload = STRBUF_INIT;
179+
struct strbuf signature = STRBUF_INIT;
178180

179-
buf = read_object_file(oid, &type, &size);
181+
orig = buf = read_object_file(oid, &type, &size);
180182
if (!buf)
181183
return;
184+
if (parse_signature(buf, size, &payload, &signature)) {
185+
buf = payload.buf;
186+
size = payload.len;
187+
}
182188
/* skip header */
183189
sp = strstr(buf, "\n\n");
184190

@@ -187,9 +193,11 @@ static void write_tag_body(int fd, const struct object_id *oid)
187193
return;
188194
}
189195
sp += 2; /* skip the 2 LFs */
190-
write_or_die(fd, sp, parse_signature(sp, buf + size - sp));
196+
write_or_die(fd, sp, buf + size - sp);
191197

192-
free(buf);
198+
free(orig);
199+
strbuf_release(&payload);
200+
strbuf_release(&signature);
193201
}
194202

195203
static int build_tag_object(struct strbuf *buf, int sign, struct object_id *result)

commit.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1136,17 +1136,18 @@ static void handle_signed_tag(struct commit *parent, struct commit_extra_header
11361136
struct merge_remote_desc *desc;
11371137
struct commit_extra_header *mergetag;
11381138
char *buf;
1139-
unsigned long size, len;
1139+
unsigned long size;
11401140
enum object_type type;
1141+
struct strbuf payload = STRBUF_INIT;
1142+
struct strbuf signature = STRBUF_INIT;
11411143

11421144
desc = merge_remote_util(parent);
11431145
if (!desc || !desc->obj)
11441146
return;
11451147
buf = read_object_file(&desc->obj->oid, &type, &size);
11461148
if (!buf || type != OBJ_TAG)
11471149
goto free_return;
1148-
len = parse_signature(buf, size);
1149-
if (size == len)
1150+
if (!parse_signature(buf, size, &payload, &signature))
11501151
goto free_return;
11511152
/*
11521153
* We could verify this signature and either omit the tag when
@@ -1165,6 +1166,8 @@ static void handle_signed_tag(struct commit *parent, struct commit_extra_header
11651166

11661167
**tail = mergetag;
11671168
*tail = &mergetag->next;
1169+
strbuf_release(&payload);
1170+
strbuf_release(&signature);
11681171
return;
11691172

11701173
free_return:

fmt-merge-msg.c

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -509,22 +509,28 @@ static void fmt_merge_msg_sigs(struct strbuf *out)
509509
for (i = 0; i < origins.nr; i++) {
510510
struct object_id *oid = origins.items[i].util;
511511
enum object_type type;
512-
unsigned long size, len;
512+
unsigned long size;
513513
char *buf = read_object_file(oid, &type, &size);
514+
char *origbuf = buf;
515+
unsigned long len = size;
514516
struct signature_check sigc = { NULL };
515-
struct strbuf sig = STRBUF_INIT;
517+
struct strbuf payload = STRBUF_INIT, sig = STRBUF_INIT;
516518

517519
if (!buf || type != OBJ_TAG)
518520
goto next;
519-
len = parse_signature(buf, size);
520521

521-
if (size == len)
522-
; /* merely annotated */
523-
else if (check_signature(buf, len, buf + len, size - len, &sigc) &&
524-
!sigc.gpg_output)
525-
strbuf_addstr(&sig, "gpg verification failed.\n");
526-
else
527-
strbuf_addstr(&sig, sigc.gpg_output);
522+
if (!parse_signature(buf, size, &payload, &sig))
523+
;/* merely annotated */
524+
else {
525+
buf = payload.buf;
526+
len = payload.len;
527+
if (check_signature(payload.buf, payload.len, sig.buf,
528+
sig.len, &sigc) &&
529+
!sigc.gpg_output)
530+
strbuf_addstr(&sig, "gpg verification failed.\n");
531+
else
532+
strbuf_addstr(&sig, sigc.gpg_output);
533+
}
528534
signature_check_clear(&sigc);
529535

530536
if (!tag_number++) {
@@ -547,9 +553,10 @@ static void fmt_merge_msg_sigs(struct strbuf *out)
547553
strlen(origins.items[i].string));
548554
fmt_tag_signature(&tagbuf, &sig, buf, len);
549555
}
556+
strbuf_release(&payload);
550557
strbuf_release(&sig);
551558
next:
552-
free(buf);
559+
free(origbuf);
553560
}
554561
if (tagbuf.len) {
555562
strbuf_addch(out, '\n');

gpg-interface.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,7 @@ void print_signature_buffer(const struct signature_check *sigc, unsigned flags)
345345
fputs(output, stderr);
346346
}
347347

348-
size_t parse_signature(const char *buf, size_t size)
348+
size_t parse_signed_buffer(const char *buf, size_t size)
349349
{
350350
size_t len = 0;
351351
size_t match = size;
@@ -361,6 +361,17 @@ size_t parse_signature(const char *buf, size_t size)
361361
return match;
362362
}
363363

364+
int parse_signature(const char *buf, size_t size, struct strbuf *payload, struct strbuf *signature)
365+
{
366+
size_t match = parse_signed_buffer(buf, size);
367+
if (match != size) {
368+
strbuf_add(payload, buf, match);
369+
strbuf_add(signature, buf + match, size - match);
370+
return 1;
371+
}
372+
return 0;
373+
}
374+
364375
void set_signing_key(const char *key)
365376
{
366377
free(configured_signing_key);

gpg-interface.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,20 @@ struct signature_check {
3737

3838
void signature_check_clear(struct signature_check *sigc);
3939

40+
/*
41+
* Look at a GPG signed tag object. If such a signature exists, store it in
42+
* signature and the signed content in payload. Return 1 if a signature was
43+
* found, and 0 otherwise.
44+
*/
45+
int parse_signature(const char *buf, size_t size, struct strbuf *payload, struct strbuf *signature);
46+
4047
/*
4148
* Look at GPG signed content (e.g. a signed tag object), whose
4249
* payload is followed by a detached signature on it. Return the
4350
* offset where the embedded detached signature begins, or the end of
4451
* the data when there is no such signature.
4552
*/
46-
size_t parse_signature(const char *buf, size_t size);
53+
size_t parse_signed_buffer(const char *buf, size_t size);
4754

4855
/*
4956
* Create a detached signature for the contents of "buffer" and append

log-tree.c

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -548,7 +548,8 @@ static int show_one_mergetag(struct commit *commit,
548548
struct strbuf verify_message;
549549
struct signature_check sigc = { 0 };
550550
int status, nth;
551-
size_t payload_size;
551+
struct strbuf payload = STRBUF_INIT;
552+
struct strbuf signature = STRBUF_INIT;
552553

553554
hash_object_file(the_hash_algo, extra->value, extra->len,
554555
type_name(OBJ_TAG), &oid);
@@ -571,13 +572,11 @@ static int show_one_mergetag(struct commit *commit,
571572
strbuf_addf(&verify_message,
572573
"parent #%d, tagged '%s'\n", nth + 1, tag->tag);
573574

574-
payload_size = parse_signature(extra->value, extra->len);
575575
status = -1;
576-
if (extra->len > payload_size) {
576+
if (parse_signature(extra->value, extra->len, &payload, &signature)) {
577577
/* could have a good signature */
578-
status = check_signature(extra->value, payload_size,
579-
extra->value + payload_size,
580-
extra->len - payload_size, &sigc);
578+
status = check_signature(payload.buf, payload.len,
579+
signature.buf, signature.len, &sigc);
581580
if (sigc.gpg_output)
582581
strbuf_addstr(&verify_message, sigc.gpg_output);
583582
else
@@ -588,6 +587,8 @@ static int show_one_mergetag(struct commit *commit,
588587

589588
show_sig_lines(opt, status, verify_message.buf);
590589
strbuf_release(&verify_message);
590+
strbuf_release(&payload);
591+
strbuf_release(&signature);
591592
return 0;
592593
}
593594

ref-filter.c

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1215,7 +1215,13 @@ static void find_subpos(const char *buf,
12151215
size_t *nonsiglen,
12161216
const char **sig, size_t *siglen)
12171217
{
1218+
struct strbuf payload = STRBUF_INIT;
1219+
struct strbuf signature = STRBUF_INIT;
12181220
const char *eol;
1221+
const char *end = buf + strlen(buf);
1222+
const char *sigstart;
1223+
1224+
12191225
/* skip past header until we hit empty line */
12201226
while (*buf && *buf != '\n') {
12211227
eol = strchrnul(buf, '\n');
@@ -1228,14 +1234,15 @@ static void find_subpos(const char *buf,
12281234
buf++;
12291235

12301236
/* parse signature first; we might not even have a subject line */
1231-
*sig = buf + parse_signature(buf, strlen(buf));
1232-
*siglen = strlen(*sig);
1237+
parse_signature(buf, end - buf, &payload, &signature);
1238+
*sig = strbuf_detach(&signature, siglen);
1239+
sigstart = buf + parse_signed_buffer(buf, strlen(buf));
12331240

12341241
/* subject is first non-empty line */
12351242
*sub = buf;
12361243
/* subject goes to first empty line before signature begins */
12371244
if ((eol = strstr(*sub, "\n\n"))) {
1238-
eol = eol < *sig ? eol : *sig;
1245+
eol = eol < sigstart ? eol : sigstart;
12391246
/* check if message uses CRLF */
12401247
} else if (! (eol = strstr(*sub, "\r\n\r\n"))) {
12411248
/* treat whole message as subject */
@@ -1253,7 +1260,7 @@ static void find_subpos(const char *buf,
12531260
buf++;
12541261
*body = buf;
12551262
*bodylen = strlen(buf);
1256-
*nonsiglen = *sig - buf;
1263+
*nonsiglen = sigstart - buf;
12571264
}
12581265

12591266
/*
@@ -1291,6 +1298,7 @@ static void grab_sub_body_contents(struct atom_value *val, int deref, void *buf)
12911298
struct used_atom *atom = &used_atom[i];
12921299
const char *name = atom->name;
12931300
struct atom_value *v = &val[i];
1301+
12941302
if (!!deref != (*name == '*'))
12951303
continue;
12961304
if (deref)
@@ -1336,7 +1344,9 @@ static void grab_sub_body_contents(struct atom_value *val, int deref, void *buf)
13361344
v->s = strbuf_detach(&s, NULL);
13371345
} else if (atom->u.contents.option == C_BARE)
13381346
v->s = xstrdup(subpos);
1347+
13391348
}
1349+
free((void *)sigpos);
13401350
}
13411351

13421352
/*

tag.c

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,26 +13,27 @@ const char *tag_type = "tag";
1313
static int run_gpg_verify(const char *buf, unsigned long size, unsigned flags)
1414
{
1515
struct signature_check sigc;
16-
size_t payload_size;
16+
struct strbuf payload = STRBUF_INIT;
17+
struct strbuf signature = STRBUF_INIT;
1718
int ret;
1819

1920
memset(&sigc, 0, sizeof(sigc));
2021

21-
payload_size = parse_signature(buf, size);
22-
23-
if (size == payload_size) {
22+
if (!parse_signature(buf, size, &payload, &signature)) {
2423
if (flags & GPG_VERIFY_VERBOSE)
25-
write_in_full(1, buf, payload_size);
24+
write_in_full(1, buf, size);
2625
return error("no signature found");
2726
}
2827

29-
ret = check_signature(buf, payload_size, buf + payload_size,
30-
size - payload_size, &sigc);
28+
ret = check_signature(payload.buf, payload.len, signature.buf,
29+
signature.len, &sigc);
3130

3231
if (!(flags & GPG_VERIFY_OMIT_STATUS))
3332
print_signature_buffer(&sigc, flags);
3433

3534
signature_check_clear(&sigc);
35+
strbuf_release(&payload);
36+
strbuf_release(&signature);
3637
return ret;
3738
}
3839

0 commit comments

Comments
 (0)