Move commit GPG signature verification to commit.c
Signed-off-by: Sebastian Götte <jaseg@physik-pool.tu-berlin.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
		
				
					committed by
					
						
						Junio C Hamano
					
				
			
			
				
	
			
			
			
						parent
						
							8617715cc0
						
					
				
				
					commit
					ffb6d7d5c9
				
			
							
								
								
									
										59
									
								
								commit.c
									
									
									
									
									
								
							
							
						
						
									
										59
									
								
								commit.c
									
									
									
									
									
								
							@ -1041,6 +1041,65 @@ free_return:
 | 
				
			|||||||
	free(buf);
 | 
						free(buf);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct {
 | 
				
			||||||
 | 
						char result;
 | 
				
			||||||
 | 
						const char *check;
 | 
				
			||||||
 | 
					} sigcheck_gpg_status[] = {
 | 
				
			||||||
 | 
						{ 'G', "\n[GNUPG:] GOODSIG " },
 | 
				
			||||||
 | 
						{ 'B', "\n[GNUPG:] BADSIG " },
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void parse_gpg_output(struct signature_check *sigc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						const char *buf = sigc->gpg_status;
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < ARRAY_SIZE(sigcheck_gpg_status); i++) {
 | 
				
			||||||
 | 
							const char *found = strstr(buf, sigcheck_gpg_status[i].check);
 | 
				
			||||||
 | 
							const char *next;
 | 
				
			||||||
 | 
							if (!found)
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
							sigc->result = sigcheck_gpg_status[i].result;
 | 
				
			||||||
 | 
							found += strlen(sigcheck_gpg_status[i].check);
 | 
				
			||||||
 | 
							sigc->key = xmemdupz(found, 16);
 | 
				
			||||||
 | 
							found += 17;
 | 
				
			||||||
 | 
							next = strchrnul(found, '\n');
 | 
				
			||||||
 | 
							sigc->signer = xmemdupz(found, next - found);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void check_commit_signature(const struct commit* commit, struct signature_check *sigc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct strbuf payload = STRBUF_INIT;
 | 
				
			||||||
 | 
						struct strbuf signature = STRBUF_INIT;
 | 
				
			||||||
 | 
						struct strbuf gpg_output = STRBUF_INIT;
 | 
				
			||||||
 | 
						struct strbuf gpg_status = STRBUF_INIT;
 | 
				
			||||||
 | 
						int status;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sigc->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, &gpg_status);
 | 
				
			||||||
 | 
						if (status && !gpg_output.len)
 | 
				
			||||||
 | 
							goto out;
 | 
				
			||||||
 | 
						sigc->gpg_output = strbuf_detach(&gpg_output, NULL);
 | 
				
			||||||
 | 
						sigc->gpg_status = strbuf_detach(&gpg_status, NULL);
 | 
				
			||||||
 | 
						parse_gpg_output(sigc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 out:
 | 
				
			||||||
 | 
						strbuf_release(&gpg_status);
 | 
				
			||||||
 | 
						strbuf_release(&gpg_output);
 | 
				
			||||||
 | 
						strbuf_release(&payload);
 | 
				
			||||||
 | 
						strbuf_release(&signature);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void append_merge_tag_headers(struct commit_list *parents,
 | 
					void append_merge_tag_headers(struct commit_list *parents,
 | 
				
			||||||
			      struct commit_extra_header ***tail)
 | 
								      struct commit_extra_header ***tail)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										10
									
								
								commit.h
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								commit.h
									
									
									
									
									
								
							@ -5,6 +5,7 @@
 | 
				
			|||||||
#include "tree.h"
 | 
					#include "tree.h"
 | 
				
			||||||
#include "strbuf.h"
 | 
					#include "strbuf.h"
 | 
				
			||||||
#include "decorate.h"
 | 
					#include "decorate.h"
 | 
				
			||||||
 | 
					#include "gpg-interface.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct commit_list {
 | 
					struct commit_list {
 | 
				
			||||||
	struct commit *item;
 | 
						struct commit *item;
 | 
				
			||||||
@ -232,4 +233,13 @@ extern void print_commit_list(struct commit_list *list,
 | 
				
			|||||||
			      const char *format_cur,
 | 
								      const char *format_cur,
 | 
				
			||||||
			      const char *format_last);
 | 
								      const char *format_last);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Check the signature of the given commit. The result of the check is stored in
 | 
				
			||||||
 | 
					 * sig->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, sig->gpg_status, sig->signer
 | 
				
			||||||
 | 
					 * and sig->key.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					extern void check_commit_signature(const struct commit* commit, struct signature_check *sigc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* COMMIT_H */
 | 
					#endif /* COMMIT_H */
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,17 @@
 | 
				
			|||||||
#ifndef GPG_INTERFACE_H
 | 
					#ifndef GPG_INTERFACE_H
 | 
				
			||||||
#define GPG_INTERFACE_H
 | 
					#define GPG_INTERFACE_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct signature_check {
 | 
				
			||||||
 | 
						char *gpg_output;
 | 
				
			||||||
 | 
						char *gpg_status;
 | 
				
			||||||
 | 
						char result; /* 0 (not checked),
 | 
				
			||||||
 | 
							      * N (checked but no further result),
 | 
				
			||||||
 | 
							      * G (good)
 | 
				
			||||||
 | 
							      * B (bad) */
 | 
				
			||||||
 | 
						char *signer;
 | 
				
			||||||
 | 
						char *key;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern int sign_buffer(struct strbuf *buffer, struct strbuf *signature, const char *signing_key);
 | 
					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, struct strbuf *gpg_status);
 | 
					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);
 | 
				
			||||||
extern int git_gpg_config(const char *, const char *, void *);
 | 
					extern int git_gpg_config(const char *, const char *, void *);
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										91
									
								
								pretty.c
									
									
									
									
									
								
							
							
						
						
									
										91
									
								
								pretty.c
									
									
									
									
									
								
							@ -766,14 +766,7 @@ struct format_commit_context {
 | 
				
			|||||||
	const struct pretty_print_context *pretty_ctx;
 | 
						const struct pretty_print_context *pretty_ctx;
 | 
				
			||||||
	unsigned commit_header_parsed:1;
 | 
						unsigned commit_header_parsed:1;
 | 
				
			||||||
	unsigned commit_message_parsed:1;
 | 
						unsigned commit_message_parsed:1;
 | 
				
			||||||
	unsigned commit_signature_parsed:1;
 | 
						struct signature_check signature_check;
 | 
				
			||||||
	struct {
 | 
					 | 
				
			||||||
		char *gpg_output;
 | 
					 | 
				
			||||||
		char *gpg_status;
 | 
					 | 
				
			||||||
		char good_bad;
 | 
					 | 
				
			||||||
		char *signer;
 | 
					 | 
				
			||||||
		char *key;
 | 
					 | 
				
			||||||
	} signature;
 | 
					 | 
				
			||||||
	char *message;
 | 
						char *message;
 | 
				
			||||||
	size_t width, indent1, indent2;
 | 
						size_t width, indent1, indent2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -956,64 +949,6 @@ static void rewrap_message_tail(struct strbuf *sb,
 | 
				
			|||||||
	c->indent2 = new_indent2;
 | 
						c->indent2 = new_indent2;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct {
 | 
					 | 
				
			||||||
	char result;
 | 
					 | 
				
			||||||
	const char *check;
 | 
					 | 
				
			||||||
} signature_check[] = {
 | 
					 | 
				
			||||||
	{ 'G', "\n[GNUPG:] GOODSIG " },
 | 
					 | 
				
			||||||
	{ 'B', "\n[GNUPG:] BADSIG " },
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void parse_signature_lines(struct format_commit_context *ctx)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	const char *buf = ctx->signature.gpg_status;
 | 
					 | 
				
			||||||
	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);
 | 
					 | 
				
			||||||
		ctx->signature.key = xmemdupz(found, 16);
 | 
					 | 
				
			||||||
		found += 17;
 | 
					 | 
				
			||||||
		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;
 | 
					 | 
				
			||||||
	struct strbuf gpg_status = 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, &gpg_status);
 | 
					 | 
				
			||||||
	if (status && !gpg_output.len)
 | 
					 | 
				
			||||||
		goto out;
 | 
					 | 
				
			||||||
	ctx->signature.gpg_output = strbuf_detach(&gpg_output, NULL);
 | 
					 | 
				
			||||||
	ctx->signature.gpg_status = strbuf_detach(&gpg_status, NULL);
 | 
					 | 
				
			||||||
	parse_signature_lines(ctx);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 out:
 | 
					 | 
				
			||||||
	strbuf_release(&gpg_status);
 | 
					 | 
				
			||||||
	strbuf_release(&gpg_output);
 | 
					 | 
				
			||||||
	strbuf_release(&payload);
 | 
					 | 
				
			||||||
	strbuf_release(&signature);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int format_reflog_person(struct strbuf *sb,
 | 
					static int format_reflog_person(struct strbuf *sb,
 | 
				
			||||||
				char part,
 | 
									char part,
 | 
				
			||||||
				struct reflog_walk_info *log,
 | 
									struct reflog_walk_info *log,
 | 
				
			||||||
@ -1199,27 +1134,27 @@ static size_t format_commit_one(struct strbuf *sb, const char *placeholder,
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (placeholder[0] == 'G') {
 | 
						if (placeholder[0] == 'G') {
 | 
				
			||||||
		if (!c->commit_signature_parsed)
 | 
							if (!c->signature_check.result)
 | 
				
			||||||
			parse_commit_signature(c);
 | 
								check_commit_signature(c->commit, &(c->signature_check));
 | 
				
			||||||
		switch (placeholder[1]) {
 | 
							switch (placeholder[1]) {
 | 
				
			||||||
		case 'G':
 | 
							case 'G':
 | 
				
			||||||
			if (c->signature.gpg_output)
 | 
								if (c->signature_check.gpg_output)
 | 
				
			||||||
				strbuf_addstr(sb, c->signature.gpg_output);
 | 
									strbuf_addstr(sb, c->signature_check.gpg_output);
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		case '?':
 | 
							case '?':
 | 
				
			||||||
			switch (c->signature.good_bad) {
 | 
								switch (c->signature_check.result) {
 | 
				
			||||||
			case 'G':
 | 
								case 'G':
 | 
				
			||||||
			case 'B':
 | 
								case 'B':
 | 
				
			||||||
				strbuf_addch(sb, c->signature.good_bad);
 | 
									strbuf_addch(sb, c->signature_check.result);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		case 'S':
 | 
							case 'S':
 | 
				
			||||||
			if (c->signature.signer)
 | 
								if (c->signature_check.signer)
 | 
				
			||||||
				strbuf_addstr(sb, c->signature.signer);
 | 
									strbuf_addstr(sb, c->signature_check.signer);
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		case 'K':
 | 
							case 'K':
 | 
				
			||||||
			if (c->signature.key)
 | 
								if (c->signature_check.key)
 | 
				
			||||||
				strbuf_addstr(sb, c->signature.key);
 | 
									strbuf_addstr(sb, c->signature_check.key);
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return 2;
 | 
							return 2;
 | 
				
			||||||
@ -1357,8 +1292,8 @@ void format_commit_message(const struct commit *commit,
 | 
				
			|||||||
	rewrap_message_tail(sb, &context, 0, 0, 0);
 | 
						rewrap_message_tail(sb, &context, 0, 0, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	logmsg_free(context.message, commit);
 | 
						logmsg_free(context.message, commit);
 | 
				
			||||||
	free(context.signature.gpg_output);
 | 
						free(context.signature_check.gpg_output);
 | 
				
			||||||
	free(context.signature.signer);
 | 
						free(context.signature_check.signer);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void pp_header(const struct pretty_print_context *pp,
 | 
					static void pp_header(const struct pretty_print_context *pp,
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user