From mboxrd@z Thu Jan 1 00:00:00 1970 From: =?ISO-8859-1?Q?Sebastian_G=F6tte?= Subject: [PATCH v2 1/4] Move commit GPG signature verification to commit.c Date: Sat, 23 Mar 2013 02:57:41 +0100 Message-ID: <514D0C15.9000100@physik.tu-berlin.de> Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: QUOTED-PRINTABLE Cc: gitster@pobox.com To: git@vger.kernel.org X-From: git-owner@vger.kernel.org Sat Mar 23 02:58:26 2013 Return-path: Envelope-to: gcvg-git-2@plane.gmane.org Received: from vger.kernel.org ([209.132.180.67]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1UJDix-0004pW-LZ for gcvg-git-2@plane.gmane.org; Sat, 23 Mar 2013 02:58:24 +0100 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1423073Ab3CWB5s convert rfc822-to-quoted-printable (ORCPT ); Fri, 22 Mar 2013 21:57:48 -0400 Received: from mail.tu-berlin.de ([130.149.7.33]:27414 "EHLO mail.tu-berlin.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1423045Ab3CWB5q (ORCPT ); Fri, 22 Mar 2013 21:57:46 -0400 X-tubIT-Incoming-IP: 130.149.58.163 Received: from mail.physik-pool.tu-berlin.de ([130.149.58.163] helo=mail.physik.tu-berlin.de) by mail.tu-berlin.de (exim-4.75/mailfrontend-2) with esmtp id 1UJDiK-0006CX-IT; Sat, 23 Mar 2013 02:57:45 +0100 Received: from [192.168.0.103] (cable-124-189.zeelandnet.nl [82.176.124.189]) (using TLSv1 with cipher DHE-RSA-CAMELLIA256-SHA (256/256 bits)) (No client certificate requested) by mail.physik.tu-berlin.de (Postfix) with ESMTPSA id 4CB8311402; Sat, 23 Mar 2013 02:57:42 +0100 (CET) User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/20130221 Thunderbird/17.0.3 Sender: git-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org Archived-At: Signed-off-by: Sebastian G=F6tte --- 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); } =20 +static struct { + char result; + const char *check; +} signature_check[] =3D { + { 'G', ": Good signature from " }, + { 'B', ": BAD signature from " }, +}; + +static void parse_signature_lines(struct signature *sig) +{ + const char *buf =3D sig->gpg_output; + int i; + + for (i =3D 0; i < ARRAY_SIZE(signature_check); i++) { + const char *found =3D strstr(buf, signature_check[i].check); + const char *next; + if (!found) + continue; + sig->check_result =3D signature_check[i].result; + found +=3D strlen(signature_check[i].check); + next =3D strchrnul(found, '\n'); + sig->signer =3D xmemdupz(found, next - found); + break; + } +} + +void check_commit_signature(const struct commit* commit, struct signat= ure *sig) +{ + struct strbuf payload =3D STRBUF_INIT; + struct strbuf signature =3D STRBUF_INIT; + struct strbuf gpg_output =3D STRBUF_INIT; + int status; + + sig->check_result =3D 'N'; + + if (parse_signed_commit(commit->object.sha1, + &payload, &signature) <=3D 0) + goto out; + status =3D verify_signed_buffer(payload.buf, payload.len, + signature.buf, signature.len, + &gpg_output); + if (status && !gpg_output.len) + goto out; + sig->gpg_output =3D 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" =20 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); =20 +/* + * 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 signatur= e 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 =20 +struct signature { + char *gpg_output; + char check_result; /* 0 (not checked), N (checked but no further resu= lt), 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_si= ze, const char *signature, size_t signature_size, struct strbuf *gpg_ou= tput); 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; =20 @@ -944,58 +939,6 @@ static void rewrap_message_tail(struct strbuf *sb, c->indent2 =3D new_indent2; } =20 -static struct { - char result; - const char *check; -} signature_check[] =3D { - { 'G', ": Good signature from " }, - { 'B', ": BAD signature from " }, -}; - -static void parse_signature_lines(struct format_commit_context *ctx) -{ - const char *buf =3D ctx->signature.gpg_output; - int i; - - for (i =3D 0; i < ARRAY_SIZE(signature_check); i++) { - const char *found =3D strstr(buf, signature_check[i].check); - const char *next; - if (!found) - continue; - ctx->signature.good_bad =3D signature_check[i].result; - found +=3D strlen(signature_check[i].check); - next =3D strchrnul(found, '\n'); - ctx->signature.signer =3D xmemdupz(found, next - found); - break; - } -} - -static void parse_commit_signature(struct format_commit_context *ctx) -{ - struct strbuf payload =3D STRBUF_INIT; - struct strbuf signature =3D STRBUF_INIT; - struct strbuf gpg_output =3D STRBUF_INIT; - int status; - - ctx->commit_signature_parsed =3D 1; - - if (parse_signed_commit(ctx->commit->object.sha1, - &payload, &signature) <=3D 0) - goto out; - status =3D verify_signed_buffer(payload.buf, payload.len, - signature.buf, signature.len, - &gpg_output); - if (status && !gpg_output.len) - goto out; - ctx->signature.gpg_output =3D strbuf_detach(&gpg_output, NULL); - parse_signature_lines(ctx); - - out: - strbuf_release(&gpg_output); - strbuf_release(&payload); - strbuf_release(&signature); -} - =20 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, } =20 if (placeholder[0] =3D=3D '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': --=20 1.8.1.5