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 <sandals@crustytoothpaste.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
1fb5cf0da6
commit
482c119186
@ -764,7 +764,7 @@ static void prepare_push_cert_sha1(struct child_process *proc)
|
||||
|
||||
memset(&sigcheck, '\0', sizeof(sigcheck));
|
||||
|
||||
bogs = parse_signature(push_cert.buf, push_cert.len);
|
||||
bogs = parse_signed_buffer(push_cert.buf, push_cert.len);
|
||||
check_signature(push_cert.buf, bogs, push_cert.buf + bogs,
|
||||
push_cert.len - bogs, &sigcheck);
|
||||
|
||||
@ -2050,7 +2050,7 @@ static void queue_commands_from_cert(struct command **tail,
|
||||
die("malformed push certificate %.*s", 100, push_cert->buf);
|
||||
else
|
||||
boc += 2;
|
||||
eoc = push_cert->buf + parse_signature(push_cert->buf, push_cert->len);
|
||||
eoc = push_cert->buf + parse_signed_buffer(push_cert->buf, push_cert->len);
|
||||
|
||||
while (boc < eoc) {
|
||||
const char *eol = memchr(boc, '\n', eoc - boc);
|
||||
|
@ -174,11 +174,17 @@ static void write_tag_body(int fd, const struct object_id *oid)
|
||||
{
|
||||
unsigned long size;
|
||||
enum object_type type;
|
||||
char *buf, *sp;
|
||||
char *buf, *sp, *orig;
|
||||
struct strbuf payload = STRBUF_INIT;
|
||||
struct strbuf signature = STRBUF_INIT;
|
||||
|
||||
buf = read_object_file(oid, &type, &size);
|
||||
orig = buf = read_object_file(oid, &type, &size);
|
||||
if (!buf)
|
||||
return;
|
||||
if (parse_signature(buf, size, &payload, &signature)) {
|
||||
buf = payload.buf;
|
||||
size = payload.len;
|
||||
}
|
||||
/* skip header */
|
||||
sp = strstr(buf, "\n\n");
|
||||
|
||||
@ -187,9 +193,11 @@ static void write_tag_body(int fd, const struct object_id *oid)
|
||||
return;
|
||||
}
|
||||
sp += 2; /* skip the 2 LFs */
|
||||
write_or_die(fd, sp, parse_signature(sp, buf + size - sp));
|
||||
write_or_die(fd, sp, buf + size - sp);
|
||||
|
||||
free(buf);
|
||||
free(orig);
|
||||
strbuf_release(&payload);
|
||||
strbuf_release(&signature);
|
||||
}
|
||||
|
||||
static int build_tag_object(struct strbuf *buf, int sign, struct object_id *result)
|
||||
|
9
commit.c
9
commit.c
@ -1136,8 +1136,10 @@ static void handle_signed_tag(struct commit *parent, struct commit_extra_header
|
||||
struct merge_remote_desc *desc;
|
||||
struct commit_extra_header *mergetag;
|
||||
char *buf;
|
||||
unsigned long size, len;
|
||||
unsigned long size;
|
||||
enum object_type type;
|
||||
struct strbuf payload = STRBUF_INIT;
|
||||
struct strbuf signature = STRBUF_INIT;
|
||||
|
||||
desc = merge_remote_util(parent);
|
||||
if (!desc || !desc->obj)
|
||||
@ -1145,8 +1147,7 @@ static void handle_signed_tag(struct commit *parent, struct commit_extra_header
|
||||
buf = read_object_file(&desc->obj->oid, &type, &size);
|
||||
if (!buf || type != OBJ_TAG)
|
||||
goto free_return;
|
||||
len = parse_signature(buf, size);
|
||||
if (size == len)
|
||||
if (!parse_signature(buf, size, &payload, &signature))
|
||||
goto free_return;
|
||||
/*
|
||||
* 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
|
||||
|
||||
**tail = mergetag;
|
||||
*tail = &mergetag->next;
|
||||
strbuf_release(&payload);
|
||||
strbuf_release(&signature);
|
||||
return;
|
||||
|
||||
free_return:
|
||||
|
@ -509,22 +509,28 @@ static void fmt_merge_msg_sigs(struct strbuf *out)
|
||||
for (i = 0; i < origins.nr; i++) {
|
||||
struct object_id *oid = origins.items[i].util;
|
||||
enum object_type type;
|
||||
unsigned long size, len;
|
||||
unsigned long size;
|
||||
char *buf = read_object_file(oid, &type, &size);
|
||||
char *origbuf = buf;
|
||||
unsigned long len = size;
|
||||
struct signature_check sigc = { NULL };
|
||||
struct strbuf sig = STRBUF_INIT;
|
||||
struct strbuf payload = STRBUF_INIT, sig = STRBUF_INIT;
|
||||
|
||||
if (!buf || type != OBJ_TAG)
|
||||
goto next;
|
||||
len = parse_signature(buf, size);
|
||||
|
||||
if (size == len)
|
||||
; /* merely annotated */
|
||||
else if (check_signature(buf, len, buf + len, size - len, &sigc) &&
|
||||
!sigc.gpg_output)
|
||||
strbuf_addstr(&sig, "gpg verification failed.\n");
|
||||
else
|
||||
strbuf_addstr(&sig, sigc.gpg_output);
|
||||
if (!parse_signature(buf, size, &payload, &sig))
|
||||
;/* merely annotated */
|
||||
else {
|
||||
buf = payload.buf;
|
||||
len = payload.len;
|
||||
if (check_signature(payload.buf, payload.len, sig.buf,
|
||||
sig.len, &sigc) &&
|
||||
!sigc.gpg_output)
|
||||
strbuf_addstr(&sig, "gpg verification failed.\n");
|
||||
else
|
||||
strbuf_addstr(&sig, sigc.gpg_output);
|
||||
}
|
||||
signature_check_clear(&sigc);
|
||||
|
||||
if (!tag_number++) {
|
||||
@ -547,9 +553,10 @@ static void fmt_merge_msg_sigs(struct strbuf *out)
|
||||
strlen(origins.items[i].string));
|
||||
fmt_tag_signature(&tagbuf, &sig, buf, len);
|
||||
}
|
||||
strbuf_release(&payload);
|
||||
strbuf_release(&sig);
|
||||
next:
|
||||
free(buf);
|
||||
free(origbuf);
|
||||
}
|
||||
if (tagbuf.len) {
|
||||
strbuf_addch(out, '\n');
|
||||
|
@ -345,7 +345,7 @@ void print_signature_buffer(const struct signature_check *sigc, unsigned flags)
|
||||
fputs(output, stderr);
|
||||
}
|
||||
|
||||
size_t parse_signature(const char *buf, size_t size)
|
||||
size_t parse_signed_buffer(const char *buf, size_t size)
|
||||
{
|
||||
size_t len = 0;
|
||||
size_t match = size;
|
||||
@ -361,6 +361,17 @@ size_t parse_signature(const char *buf, size_t size)
|
||||
return match;
|
||||
}
|
||||
|
||||
int parse_signature(const char *buf, size_t size, struct strbuf *payload, struct strbuf *signature)
|
||||
{
|
||||
size_t match = parse_signed_buffer(buf, size);
|
||||
if (match != size) {
|
||||
strbuf_add(payload, buf, match);
|
||||
strbuf_add(signature, buf + match, size - match);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void set_signing_key(const char *key)
|
||||
{
|
||||
free(configured_signing_key);
|
||||
|
@ -37,13 +37,20 @@ struct signature_check {
|
||||
|
||||
void signature_check_clear(struct signature_check *sigc);
|
||||
|
||||
/*
|
||||
* Look at a GPG signed tag object. If such a signature exists, store it in
|
||||
* signature and the signed content in payload. Return 1 if a signature was
|
||||
* found, and 0 otherwise.
|
||||
*/
|
||||
int parse_signature(const char *buf, size_t size, struct strbuf *payload, struct strbuf *signature);
|
||||
|
||||
/*
|
||||
* Look at GPG signed content (e.g. a signed tag object), whose
|
||||
* payload is followed by a detached signature on it. Return the
|
||||
* offset where the embedded detached signature begins, or the end of
|
||||
* the data when there is no such signature.
|
||||
*/
|
||||
size_t parse_signature(const char *buf, size_t size);
|
||||
size_t parse_signed_buffer(const char *buf, size_t size);
|
||||
|
||||
/*
|
||||
* Create a detached signature for the contents of "buffer" and append
|
||||
|
13
log-tree.c
13
log-tree.c
@ -548,7 +548,8 @@ static int show_one_mergetag(struct commit *commit,
|
||||
struct strbuf verify_message;
|
||||
struct signature_check sigc = { 0 };
|
||||
int status, nth;
|
||||
size_t payload_size;
|
||||
struct strbuf payload = STRBUF_INIT;
|
||||
struct strbuf signature = STRBUF_INIT;
|
||||
|
||||
hash_object_file(the_hash_algo, extra->value, extra->len,
|
||||
type_name(OBJ_TAG), &oid);
|
||||
@ -571,13 +572,11 @@ static int show_one_mergetag(struct commit *commit,
|
||||
strbuf_addf(&verify_message,
|
||||
"parent #%d, tagged '%s'\n", nth + 1, tag->tag);
|
||||
|
||||
payload_size = parse_signature(extra->value, extra->len);
|
||||
status = -1;
|
||||
if (extra->len > payload_size) {
|
||||
if (parse_signature(extra->value, extra->len, &payload, &signature)) {
|
||||
/* could have a good signature */
|
||||
status = check_signature(extra->value, payload_size,
|
||||
extra->value + payload_size,
|
||||
extra->len - payload_size, &sigc);
|
||||
status = check_signature(payload.buf, payload.len,
|
||||
signature.buf, signature.len, &sigc);
|
||||
if (sigc.gpg_output)
|
||||
strbuf_addstr(&verify_message, sigc.gpg_output);
|
||||
else
|
||||
@ -588,6 +587,8 @@ static int show_one_mergetag(struct commit *commit,
|
||||
|
||||
show_sig_lines(opt, status, verify_message.buf);
|
||||
strbuf_release(&verify_message);
|
||||
strbuf_release(&payload);
|
||||
strbuf_release(&signature);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
18
ref-filter.c
18
ref-filter.c
@ -1215,7 +1215,13 @@ static void find_subpos(const char *buf,
|
||||
size_t *nonsiglen,
|
||||
const char **sig, size_t *siglen)
|
||||
{
|
||||
struct strbuf payload = STRBUF_INIT;
|
||||
struct strbuf signature = STRBUF_INIT;
|
||||
const char *eol;
|
||||
const char *end = buf + strlen(buf);
|
||||
const char *sigstart;
|
||||
|
||||
|
||||
/* skip past header until we hit empty line */
|
||||
while (*buf && *buf != '\n') {
|
||||
eol = strchrnul(buf, '\n');
|
||||
@ -1228,14 +1234,15 @@ static void find_subpos(const char *buf,
|
||||
buf++;
|
||||
|
||||
/* parse signature first; we might not even have a subject line */
|
||||
*sig = buf + parse_signature(buf, strlen(buf));
|
||||
*siglen = strlen(*sig);
|
||||
parse_signature(buf, end - buf, &payload, &signature);
|
||||
*sig = strbuf_detach(&signature, siglen);
|
||||
sigstart = buf + parse_signed_buffer(buf, strlen(buf));
|
||||
|
||||
/* subject is first non-empty line */
|
||||
*sub = buf;
|
||||
/* subject goes to first empty line before signature begins */
|
||||
if ((eol = strstr(*sub, "\n\n"))) {
|
||||
eol = eol < *sig ? eol : *sig;
|
||||
eol = eol < sigstart ? eol : sigstart;
|
||||
/* check if message uses CRLF */
|
||||
} else if (! (eol = strstr(*sub, "\r\n\r\n"))) {
|
||||
/* treat whole message as subject */
|
||||
@ -1253,7 +1260,7 @@ static void find_subpos(const char *buf,
|
||||
buf++;
|
||||
*body = buf;
|
||||
*bodylen = strlen(buf);
|
||||
*nonsiglen = *sig - buf;
|
||||
*nonsiglen = sigstart - buf;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1291,6 +1298,7 @@ static void grab_sub_body_contents(struct atom_value *val, int deref, void *buf)
|
||||
struct used_atom *atom = &used_atom[i];
|
||||
const char *name = atom->name;
|
||||
struct atom_value *v = &val[i];
|
||||
|
||||
if (!!deref != (*name == '*'))
|
||||
continue;
|
||||
if (deref)
|
||||
@ -1336,7 +1344,9 @@ static void grab_sub_body_contents(struct atom_value *val, int deref, void *buf)
|
||||
v->s = strbuf_detach(&s, NULL);
|
||||
} else if (atom->u.contents.option == C_BARE)
|
||||
v->s = xstrdup(subpos);
|
||||
|
||||
}
|
||||
free((void *)sigpos);
|
||||
}
|
||||
|
||||
/*
|
||||
|
15
tag.c
15
tag.c
@ -13,26 +13,27 @@ const char *tag_type = "tag";
|
||||
static int run_gpg_verify(const char *buf, unsigned long size, unsigned flags)
|
||||
{
|
||||
struct signature_check sigc;
|
||||
size_t payload_size;
|
||||
struct strbuf payload = STRBUF_INIT;
|
||||
struct strbuf signature = STRBUF_INIT;
|
||||
int ret;
|
||||
|
||||
memset(&sigc, 0, sizeof(sigc));
|
||||
|
||||
payload_size = parse_signature(buf, size);
|
||||
|
||||
if (size == payload_size) {
|
||||
if (!parse_signature(buf, size, &payload, &signature)) {
|
||||
if (flags & GPG_VERIFY_VERBOSE)
|
||||
write_in_full(1, buf, payload_size);
|
||||
write_in_full(1, buf, size);
|
||||
return error("no signature found");
|
||||
}
|
||||
|
||||
ret = check_signature(buf, payload_size, buf + payload_size,
|
||||
size - payload_size, &sigc);
|
||||
ret = check_signature(payload.buf, payload.len, signature.buf,
|
||||
signature.len, &sigc);
|
||||
|
||||
if (!(flags & GPG_VERIFY_OMIT_STATUS))
|
||||
print_signature_buffer(&sigc, flags);
|
||||
|
||||
signature_check_clear(&sigc);
|
||||
strbuf_release(&payload);
|
||||
strbuf_release(&signature);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user