[PATCH v2 1/4] Move commit GPG signature verification to commit.c

Subsystems: the rest

STALE3716d

3 messages, 2 authors, 2016-06-15 · open the first message on its own page

[PATCH v2 1/4] Move commit GPG signature verification to commit.c

From: Sebastian Götte <hidden>
Date: 2016-06-15 22:56:29

Signed-off-by: Sebastian Götte <redacted>
---
 commit.c        | 54 ++++++++++++++++++++++++++++++++++++++++++++++
 commit.h        |  9 ++++++++
 gpg-interface.h |  6 ++++++
 pretty.c        | 67 +++++----------------------------------------------------
 4 files changed, 74 insertions(+), 62 deletions(-)
diff --git a/commit.c b/commit.c
index e8eb0ae..d0d9135 100644
--- a/commit.c
+++ b/commit.c
@@ -1023,6 +1023,60 @@ free_return:
 	free(buf);
 }
 
+static struct {
+	char result;
+	const char *check;
+} signature_check[] = {
+	{ 'G', ": Good signature from " },
+	{ 'B', ": BAD signature from " },
+};
+
+static void parse_signature_lines(struct signature *sig)
+{
+	const char *buf = sig->gpg_output;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(signature_check); i++) {
+		const char *found = strstr(buf, signature_check[i].check);
+		const char *next;
+		if (!found)
+			continue;
+		sig->check_result = signature_check[i].result;
+		found += strlen(signature_check[i].check);
+		next = strchrnul(found, '\n');
+		sig->signer = xmemdupz(found, next - found);
+		break;
+	}
+}
+
+void check_commit_signature(const struct commit* commit, struct signature *sig)
+{
+	struct strbuf payload = STRBUF_INIT;
+	struct strbuf signature = STRBUF_INIT;
+	struct strbuf gpg_output = STRBUF_INIT;
+	int status;
+
+	sig->check_result = 'N';
+
+	if (parse_signed_commit(commit->object.sha1,
+				&payload, &signature) <= 0)
+		goto out;
+	status = verify_signed_buffer(payload.buf, payload.len,
+				      signature.buf, signature.len,
+				      &gpg_output);
+	if (status && !gpg_output.len)
+		goto out;
+	sig->gpg_output = strbuf_detach(&gpg_output, NULL);
+	parse_signature_lines(sig);
+
+ out:
+	strbuf_release(&gpg_output);
+	strbuf_release(&payload);
+	strbuf_release(&signature);
+}
+
+
+
 void append_merge_tag_headers(struct commit_list *parents,
 			      struct commit_extra_header ***tail)
 {
diff --git a/commit.h b/commit.h
index 4138bb4..eada616 100644
--- a/commit.h
+++ b/commit.h
@@ -5,6 +5,7 @@
 #include "tree.h"
 #include "strbuf.h"
 #include "decorate.h"
+#include "gpg-interface.h"
 
 struct commit_list {
 	struct commit *item;
@@ -230,4 +231,12 @@ extern void print_commit_list(struct commit_list *list,
 			      const char *format_cur,
 			      const char *format_last);
 
+/*
+ * Check the signature of the given commit. The result of the check is stored in
+ * sig->check_result, 'G' for a good signature, 'B' for a bad signature and 'N'
+ * for no signature at all.
+ * This may allocate memory for sig->gpg_output and sig->signer.
+ */
+extern void check_commit_signature(const struct commit* commit, struct signature *sig);
+
 #endif /* COMMIT_H */
diff --git a/gpg-interface.h b/gpg-interface.h
index b9c3608..c69130f 100644
--- a/gpg-interface.h
+++ b/gpg-interface.h
@@ -1,6 +1,12 @@
 #ifndef GPG_INTERFACE_H
 #define GPG_INTERFACE_H
 
+struct signature {
+	char *gpg_output;
+	char check_result; /* 0 (not checked), N (checked but no further result), G (good) or B (bad) */
+	char *signer;
+};
+
 extern int sign_buffer(struct strbuf *buffer, struct strbuf *signature, const char *signing_key);
 extern int verify_signed_buffer(const char *payload, size_t payload_size, const char *signature, size_t signature_size, struct strbuf *gpg_output);
 extern int git_gpg_config(const char *, const char *, void *);
diff --git a/pretty.c b/pretty.c
index eae57ad..0547df1 100644
--- a/pretty.c
+++ b/pretty.c
@@ -756,12 +756,7 @@ struct format_commit_context {
 	const struct pretty_print_context *pretty_ctx;
 	unsigned commit_header_parsed:1;
 	unsigned commit_message_parsed:1;
-	unsigned commit_signature_parsed:1;
-	struct {
-		char *gpg_output;
-		char good_bad;
-		char *signer;
-	} signature;
+	struct signature signature;
 	char *message;
 	size_t width, indent1, indent2;
 
@@ -944,58 +939,6 @@ static void rewrap_message_tail(struct strbuf *sb,
 	c->indent2 = new_indent2;
 }
 
-static struct {
-	char result;
-	const char *check;
-} signature_check[] = {
-	{ 'G', ": Good signature from " },
-	{ 'B', ": BAD signature from " },
-};
-
-static void parse_signature_lines(struct format_commit_context *ctx)
-{
-	const char *buf = ctx->signature.gpg_output;
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(signature_check); i++) {
-		const char *found = strstr(buf, signature_check[i].check);
-		const char *next;
-		if (!found)
-			continue;
-		ctx->signature.good_bad = signature_check[i].result;
-		found += strlen(signature_check[i].check);
-		next = strchrnul(found, '\n');
-		ctx->signature.signer = xmemdupz(found, next - found);
-		break;
-	}
-}
-
-static void parse_commit_signature(struct format_commit_context *ctx)
-{
-	struct strbuf payload = STRBUF_INIT;
-	struct strbuf signature = STRBUF_INIT;
-	struct strbuf gpg_output = STRBUF_INIT;
-	int status;
-
-	ctx->commit_signature_parsed = 1;
-
-	if (parse_signed_commit(ctx->commit->object.sha1,
-				&payload, &signature) <= 0)
-		goto out;
-	status = verify_signed_buffer(payload.buf, payload.len,
-				      signature.buf, signature.len,
-				      &gpg_output);
-	if (status && !gpg_output.len)
-		goto out;
-	ctx->signature.gpg_output = strbuf_detach(&gpg_output, NULL);
-	parse_signature_lines(ctx);
-
- out:
-	strbuf_release(&gpg_output);
-	strbuf_release(&payload);
-	strbuf_release(&signature);
-}
-
 
 static int format_reflog_person(struct strbuf *sb,
 				char part,
@@ -1182,18 +1125,18 @@ static size_t format_commit_one(struct strbuf *sb, const char *placeholder,
 	}
 
 	if (placeholder[0] == 'G') {
-		if (!c->commit_signature_parsed)
-			parse_commit_signature(c);
+		if (!c->signature.check_result)
+			check_commit_signature(c->commit, &(c->signature));
 		switch (placeholder[1]) {
 		case 'G':
 			if (c->signature.gpg_output)
 				strbuf_addstr(sb, c->signature.gpg_output);
 			break;
 		case '?':
-			switch (c->signature.good_bad) {
+			switch (c->signature.check_result) {
 			case 'G':
 			case 'B':
-				strbuf_addch(sb, c->signature.good_bad);
+				strbuf_addch(sb, c->signature.check_result);
 			}
 			break;
 		case 'S':
-- 
1.8.1.5

Re: [PATCH v2 1/4] Move commit GPG signature verification to commit.c

From: Junio C Hamano <hidden>
Date: 2016-06-15 22:56:30

Sebastian Götte [off-list ref] writes:
quoted hunk
Signed-off-by: Sebastian Götte <redacted>
---
 commit.c        | 54 ++++++++++++++++++++++++++++++++++++++++++++++
 commit.h        |  9 ++++++++
 gpg-interface.h |  6 ++++++
 pretty.c        | 67 +++++----------------------------------------------------
 4 files changed, 74 insertions(+), 62 deletions(-)
diff --git a/commit.c b/commit.c
index e8eb0ae..d0d9135 100644
--- a/commit.c
+++ b/commit.c
@@ -1023,6 +1023,60 @@ free_return:
 	free(buf);
 }
 
+static struct {
+	char result;
+	const char *check;
+} signature_check[] = {
+	{ 'G', ": Good signature from " },
+	{ 'B', ": BAD signature from " },
+};
This seems to be based on the old codebase.  4a868fd655a7 (pretty:
parse the gpg status lines rather than the output, 2013-02-14) is
already in 'master' for this cycle, and it is likely that we would
want to have the same fix for 1.8.1.x maintenance track as well.

[PATCH 0/5] Verify GPG signatures when merging and extend %G? pretty string

From: Sebastian Götte <hidden>
Date: 2016-06-15 22:56:31

Rebased it onto the current 'master'. The second patch fixes that the GPG
status parser ignores the first line of GPG status output (that would be caught
by the new merge signature verification test case).

Sebastian Götte (5):
  Move commit GPG signature verification to commit.c
  commit.c/GPG signature verification: Also look at the first GPG status
    line
  merge/pull: verify GPG signatures of commits being merged
  merge/pull Check for untrusted good GPG signatures
  pretty printing: extend %G? to include 'N' and 'U'

 Documentation/merge-options.txt    |   4 ++
 Documentation/pretty-formats.txt   |   3 +-
 builtin/merge.c                    |  35 ++++++++++++++++-
 commit.c                           |  61 +++++++++++++++++++++++++++++
 commit.h                           |  10 +++++
 git-pull.sh                        |  10 ++++-
 gpg-interface.h                    |   8 ++++
 pretty.c                           |  77 ++++---------------------------------
 t/lib-gpg/pubring.gpg              | Bin 1164 -> 2359 bytes
 t/lib-gpg/random_seed              | Bin 600 -> 600 bytes
 t/lib-gpg/secring.gpg              | Bin 1237 -> 3734 bytes
 t/lib-gpg/trustdb.gpg              | Bin 1280 -> 1360 bytes
 t/t7612-merge-verify-signatures.sh |  61 +++++++++++++++++++++++++++++
 13 files changed, 195 insertions(+), 74 deletions(-)
 create mode 100755 t/t7612-merge-verify-signatures.sh

-- 
1.8.1.5
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help