From: "brian m. carlson" <sandals@crustytoothpaste.net>
To: <git@vger.kernel.org>
Subject: [PATCH v2 18/24] gpg-interface: improve interface for parsing tags
Date: Sat, 22 Feb 2020 20:17:43 +0000 [thread overview]
Message-ID: <20200222201749.937983-19-sandals@crustytoothpaste.net> (raw)
In-Reply-To: <20200222201749.937983-1-sandals@crustytoothpaste.net>
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,
the transition plan has SHA-256 tags using a header, which is a
materially different syntax. The current interface is not suitable for
parsing such tags.
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 want to strip off the signature
in a SHA-1 tag or 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>
---
builtin/fmt-merge-msg.c | 26 ++++++++++++++++++--------
builtin/receive-pack.c | 4 ++--
builtin/tag.c | 16 ++++++++++++----
commit.c | 9 ++++++---
gpg-interface.c | 13 ++++++++++++-
gpg-interface.h | 9 ++++++++-
log-tree.c | 14 ++++++++------
ref-filter.c | 18 ++++++++++++++----
tag.c | 15 ++++++++-------
9 files changed, 88 insertions(+), 36 deletions(-)
diff --git a/builtin/fmt-merge-msg.c b/builtin/fmt-merge-msg.c
index 05a92c59d8..29f647e2d9 100644
--- a/builtin/fmt-merge-msg.c
+++ b/builtin/fmt-merge-msg.c
@@ -472,6 +472,7 @@ static void fmt_tag_signature(struct strbuf *tagbuf,
const char *buf,
unsigned long len)
{
+
const char *tag_body = strstr(buf, "\n\n");
if (tag_body) {
tag_body += 2;
@@ -492,24 +493,31 @@ 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;
- char *buf = read_object_file(oid, &type, &size);
+ unsigned long size;
+ char *buf = read_object_file(oid, &type, &size), *orig = buf;
struct signature_check sigc = { 0 };
+ struct strbuf payload = STRBUF_INIT;
+ struct strbuf signature = STRBUF_INIT;
struct strbuf sig = STRBUF_INIT;
+ size_t len = size;
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,
+ if (!parse_signature(buf, size, &payload, &signature))
+ len = size; /* merely annotated */
+ else if (!check_signature(payload.buf, payload.len,
+ signature.buf, signature.len,
&sigc)) {
strbuf_addstr(&sig, sigc.gpg_output);
signature_check_clear(&sigc);
} else
strbuf_addstr(&sig, "gpg verification failed.\n");
+ if (payload.len) {
+ buf = payload.buf;
+ len = payload.len;
+ }
+
if (!tag_number++) {
fmt_tag_signature(&tagbuf, &sig, buf, len);
first_tag = i;
@@ -531,8 +539,10 @@ static void fmt_merge_msg_sigs(struct strbuf *out)
fmt_tag_signature(&tagbuf, &sig, buf, len);
}
strbuf_release(&sig);
+ strbuf_release(&payload);
+ strbuf_release(&signature);
next:
- free(buf);
+ free(orig);
}
if (tagbuf.len) {
strbuf_addch(out, '\n');
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index 411e0b4d99..4c814c1963 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -636,7 +636,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);
@@ -1568,7 +1568,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);
diff --git a/builtin/tag.c b/builtin/tag.c
index e0a4c25382..6b95c6a2ea 100644
--- a/builtin/tag.c
+++ b/builtin/tag.c
@@ -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)
diff --git a/commit.c b/commit.c
index 534e14f22a..d39ce5076d 100644
--- a/commit.c
+++ b/commit.c
@@ -1097,8 +1097,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)
@@ -1106,8 +1108,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
@@ -1126,6 +1127,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:
diff --git a/gpg-interface.c b/gpg-interface.c
index 2d538bcd6e..b25f5c21d8 100644
--- a/gpg-interface.c
+++ b/gpg-interface.c
@@ -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);
diff --git a/gpg-interface.h b/gpg-interface.h
index f4e9b4f371..80567e4894 100644
--- a/gpg-interface.h
+++ b/gpg-interface.h
@@ -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
diff --git a/log-tree.c b/log-tree.c
index cae38dcc66..75bd61a531 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -499,7 +499,9 @@ static int show_one_mergetag(struct commit *commit,
struct strbuf verify_message;
struct signature_check sigc = { 0 };
int status, nth;
- size_t payload_size, gpg_message_offset;
+ size_t gpg_message_offset;
+ 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);
@@ -523,13 +525,11 @@ static int show_one_mergetag(struct commit *commit,
"parent #%d, tagged '%s'\n", nth + 1, tag->tag);
gpg_message_offset = verify_message.len;
- 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 */
- if (!check_signature(extra->value, payload_size,
- extra->value + payload_size,
- extra->len - payload_size, &sigc)) {
+ if (!check_signature(payload.buf, payload.len,
+ signature.buf, signature.len, &sigc)) {
strbuf_addstr(&verify_message, sigc.gpg_output);
signature_check_clear(&sigc);
status = 0; /* good */
@@ -540,6 +540,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;
}
diff --git a/ref-filter.c b/ref-filter.c
index 6867e33648..212f1165bb 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -1161,7 +1161,13 @@ static void find_subpos(const char *buf,
unsigned long *nonsiglen,
const char **sig, unsigned long *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');
@@ -1174,13 +1180,14 @@ 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 */
- while (buf < *sig && *buf && *buf != '\n') {
+ while (buf < sigstart && *buf && *buf != '\n') {
eol = strchrnul(buf, '\n');
if (*eol)
eol++;
@@ -1196,7 +1203,7 @@ static void find_subpos(const char *buf,
buf++;
*body = buf;
*bodylen = strlen(buf);
- *nonsiglen = *sig - buf;
+ *nonsiglen = sigstart - buf;
}
/*
@@ -1234,6 +1241,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)
@@ -1273,6 +1281,8 @@ 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);
}
}
diff --git a/tag.c b/tag.c
index 71b544467e..5d04506d10 100644
--- a/tag.c
+++ b/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;
}
next prev parent reply other threads:[~2020-02-22 20:18 UTC|newest]
Thread overview: 51+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-02-22 20:17 [PATCH v2 00/24] SHA-256 stage 4 implementation, part 1/3 brian m. carlson
2020-02-22 20:17 ` [PATCH v2 01/24] builtin/pack-objects: make hash agnostic brian m. carlson
2020-02-23 21:57 ` Jeff King
2020-02-24 3:01 ` Jeff King
2020-02-24 3:42 ` brian m. carlson
2020-02-24 4:20 ` Jeff King
2020-02-22 20:17 ` [PATCH v2 02/24] hash: implement and use a context cloning function brian m. carlson
2020-02-22 20:17 ` [PATCH v2 03/24] hex: introduce parsing variants taking hash algorithms brian m. carlson
2020-02-22 20:17 ` [PATCH v2 04/24] hex: add functions to parse hex object IDs in any algorithm brian m. carlson
2020-02-22 20:17 ` [PATCH v2 05/24] repository: require a build flag to use SHA-256 brian m. carlson
2020-02-22 20:17 ` [PATCH v2 06/24] t: use hash-specific lookup tables to define test constants brian m. carlson
2020-02-22 20:17 ` [PATCH v2 07/24] t6300: abstract away SHA-1-specific constants brian m. carlson
2020-02-24 18:01 ` Junio C Hamano
2020-02-24 18:12 ` Jeff King
2020-02-24 20:41 ` Junio C Hamano
2020-02-22 20:17 ` [PATCH v2 08/24] t6300: make hash algorithm independent brian m. carlson
2020-02-22 20:17 ` [PATCH v2 09/24] t/helper/test-dump-split-index: initialize git repository brian m. carlson
2020-02-22 20:17 ` [PATCH v2 10/24] t/helper: initialize repository if necessary brian m. carlson
2020-02-24 18:05 ` Junio C Hamano
2020-02-25 0:05 ` brian m. carlson
2020-02-22 20:17 ` [PATCH v2 11/24] t/helper: make repository tests hash independent brian m. carlson
2020-02-22 20:17 ` [PATCH v2 12/24] setup: allow check_repository_format to read repository format brian m. carlson
2020-02-22 20:17 ` [PATCH v2 13/24] builtin/init-db: allow specifying hash algorithm on command line brian m. carlson
2020-02-24 18:14 ` Junio C Hamano
2020-02-25 0:11 ` brian m. carlson
2020-02-22 20:17 ` [PATCH v2 14/24] builtin/init-db: add environment variable for new repo hash brian m. carlson
2020-02-22 20:17 ` [PATCH v2 15/24] init-db: move writing repo version into a function brian m. carlson
2020-02-22 20:17 ` [PATCH v2 16/24] worktree: allow repository version 1 brian m. carlson
2020-02-22 20:17 ` [PATCH v2 17/24] commit: use expected signature header for SHA-256 brian m. carlson
2020-02-24 18:24 ` Junio C Hamano
2020-02-22 20:17 ` brian m. carlson [this message]
2020-02-24 18:26 ` [PATCH v2 18/24] gpg-interface: improve interface for parsing tags Junio C Hamano
2020-02-25 10:29 ` Johannes Schindelin
2020-02-25 19:25 ` Junio C Hamano
2020-02-26 3:05 ` brian m. carlson
2020-02-26 3:11 ` Junio C Hamano
2020-02-26 2:23 ` brian m. carlson
2020-02-27 13:24 ` Johannes Schindelin
2020-02-27 15:06 ` Junio C Hamano
2020-02-22 20:17 ` [PATCH v2 19/24] tag: store SHA-256 signatures in a header brian m. carlson
2020-02-24 18:30 ` Junio C Hamano
2020-02-22 20:17 ` [PATCH v2 20/24] fast-import: permit reading multiple marks files brian m. carlson
2020-06-05 16:14 ` Junio C Hamano
2020-06-05 16:26 ` Junio C Hamano
2020-06-05 22:39 ` brian m. carlson
2020-06-05 22:53 ` Junio C Hamano
2020-02-22 20:17 ` [PATCH v2 21/24] fast-import: add helper function for inserting mark object entries brian m. carlson
2020-02-22 20:17 ` [PATCH v2 22/24] fast-import: make find_marks work on any mark set brian m. carlson
2020-02-22 20:17 ` [PATCH v2 23/24] fast-import: add a generic function to iterate over marks brian m. carlson
2020-02-22 20:17 ` [PATCH v2 24/24] fast-import: add options for rewriting submodules brian m. carlson
2020-02-24 18:34 ` [PATCH v2 00/24] SHA-256 stage 4 implementation, part 1/3 Junio C Hamano
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: http://vger.kernel.org/majordomo-info.html
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200222201749.937983-19-sandals@crustytoothpaste.net \
--to=sandals@crustytoothpaste.net \
--cc=git@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://80x24.org/mirrors/git.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).