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>

Sebastian Götte committed Mar 31, 2013 at 18:00 UTC ffb6d7d5c99e4097e512def20b0133b7ee900953
4 files changed +93 -78
commit.c
+59
@@ -1041,6 +1041,65 @@ free_return:
1041 free(buf);
1042 }
1043
1044 +static struct {
1045 + char result;
1046 + const char *check;
1047 +} sigcheck_gpg_status[] = {
1048 + { 'G', "\n[GNUPG:] GOODSIG " },
1049 + { 'B', "\n[GNUPG:] BADSIG " },
1050 +};
1051 +
1052 +static void parse_gpg_output(struct signature_check *sigc)
1053 +{
1054 + const char *buf = sigc->gpg_status;
1055 + int i;
1056 +
1057 + for (i = 0; i < ARRAY_SIZE(sigcheck_gpg_status); i++) {
1058 + const char *found = strstr(buf, sigcheck_gpg_status[i].check);
1059 + const char *next;
1060 + if (!found)
1061 + continue;
1062 + sigc->result = sigcheck_gpg_status[i].result;
1063 + found += strlen(sigcheck_gpg_status[i].check);
1064 + sigc->key = xmemdupz(found, 16);
1065 + found += 17;
1066 + next = strchrnul(found, '\n');
1067 + sigc->signer = xmemdupz(found, next - found);
1068 + break;
1069 + }
1070 +}
1071 +
1072 +void check_commit_signature(const struct commit* commit, struct signature_check *sigc)
1073 +{
1074 + struct strbuf payload = STRBUF_INIT;
1075 + struct strbuf signature = STRBUF_INIT;
1076 + struct strbuf gpg_output = STRBUF_INIT;
1077 + struct strbuf gpg_status = STRBUF_INIT;
1078 + int status;
1079 +
1080 + sigc->result = 'N';
1081 +
1082 + if (parse_signed_commit(commit->object.sha1,
1083 + &payload, &signature) <= 0)
1084 + goto out;
1085 + status = verify_signed_buffer(payload.buf, payload.len,
1086 + signature.buf, signature.len,
1087 + &gpg_output, &gpg_status);
1088 + if (status && !gpg_output.len)
1089 + goto out;
1090 + sigc->gpg_output = strbuf_detach(&gpg_output, NULL);
1091 + sigc->gpg_status = strbuf_detach(&gpg_status, NULL);
1092 + parse_gpg_output(sigc);
1093 +
1094 + out:
1095 + strbuf_release(&gpg_status);
1096 + strbuf_release(&gpg_output);
1097 + strbuf_release(&payload);
1098 + strbuf_release(&signature);
1099 +}
1100 +
1101 +
1102 +
1103 void append_merge_tag_headers(struct commit_list *parents,
1104 struct commit_extra_header ***tail)
1105 {
commit.h
+10
@@ -5,6 +5,7 @@
5 #include "tree.h"
6 #include "strbuf.h"
7 #include "decorate.h"
8 +#include "gpg-interface.h"
9
10 struct commit_list {
11 struct commit *item;
@@ -232,4 +233,13 @@ extern void print_commit_list(struct commit_list *list,
233 const char *format_cur,
234 const char *format_last);
235
236 +/*
237 + * Check the signature of the given commit. The result of the check is stored in
238 + * sig->result, 'G' for a good signature, 'B' for a bad signature and 'N'
239 + * for no signature at all.
240 + * This may allocate memory for sig->gpg_output, sig->gpg_status, sig->signer
241 + * and sig->key.
242 + */
243 +extern void check_commit_signature(const struct commit* commit, struct signature_check *sigc);
244 +
245 #endif /* COMMIT_H */
gpg-interface.h
+11
@@ -1,6 +1,17 @@
1 #ifndef GPG_INTERFACE_H
2 #define GPG_INTERFACE_H
3
4 +struct signature_check {
5 + char *gpg_output;
6 + char *gpg_status;
7 + char result; /* 0 (not checked),
8 + * N (checked but no further result),
9 + * G (good)
10 + * B (bad) */
11 + char *signer;
12 + char *key;
13 +};
14 +
15 extern int sign_buffer(struct strbuf *buffer, struct strbuf *signature, const char *signing_key);
16 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);
17 extern int git_gpg_config(const char *, const char *, void *);
pretty.c
+13 -78
@@ -766,14 +766,7 @@ struct format_commit_context {
766 const struct pretty_print_context *pretty_ctx;
767 unsigned commit_header_parsed:1;
768 unsigned commit_message_parsed:1;
769 - unsigned commit_signature_parsed:1;
770 - struct {
771 - char *gpg_output;
772 - char *gpg_status;
773 - char good_bad;
774 - char *signer;
775 - char *key;
776 - } signature;
769 + struct signature_check signature_check;
770 char *message;
771 size_t width, indent1, indent2;
772
@@ -956,64 +949,6 @@ static void rewrap_message_tail(struct strbuf *sb,
949 c->indent2 = new_indent2;
950 }
951
959 -static struct {
960 - char result;
961 - const char *check;
962 -} signature_check[] = {
963 - { 'G', "\n[GNUPG:] GOODSIG " },
964 - { 'B', "\n[GNUPG:] BADSIG " },
965 -};
966 -
967 -static void parse_signature_lines(struct format_commit_context *ctx)
968 -{
969 - const char *buf = ctx->signature.gpg_status;
970 - int i;
971 -
972 - for (i = 0; i < ARRAY_SIZE(signature_check); i++) {
973 - const char *found = strstr(buf, signature_check[i].check);
974 - const char *next;
975 - if (!found)
976 - continue;
977 - ctx->signature.good_bad = signature_check[i].result;
978 - found += strlen(signature_check[i].check);
979 - ctx->signature.key = xmemdupz(found, 16);
980 - found += 17;
981 - next = strchrnul(found, '\n');
982 - ctx->signature.signer = xmemdupz(found, next - found);
983 - break;
984 - }
985 -}
986 -
987 -static void parse_commit_signature(struct format_commit_context *ctx)
988 -{
989 - struct strbuf payload = STRBUF_INIT;
990 - struct strbuf signature = STRBUF_INIT;
991 - struct strbuf gpg_output = STRBUF_INIT;
992 - struct strbuf gpg_status = STRBUF_INIT;
993 - int status;
994 -
995 - ctx->commit_signature_parsed = 1;
996 -
997 - if (parse_signed_commit(ctx->commit->object.sha1,
998 - &payload, &signature) <= 0)
999 - goto out;
1000 - status = verify_signed_buffer(payload.buf, payload.len,
1001 - signature.buf, signature.len,
1002 - &gpg_output, &gpg_status);
1003 - if (status && !gpg_output.len)
1004 - goto out;
1005 - ctx->signature.gpg_output = strbuf_detach(&gpg_output, NULL);
1006 - ctx->signature.gpg_status = strbuf_detach(&gpg_status, NULL);
1007 - parse_signature_lines(ctx);
1008 -
1009 - out:
1010 - strbuf_release(&gpg_status);
1011 - strbuf_release(&gpg_output);
1012 - strbuf_release(&payload);
1013 - strbuf_release(&signature);
1014 -}
1015 -
1016 -
952 static int format_reflog_person(struct strbuf *sb,
953 char part,
954 struct reflog_walk_info *log,
@@ -1199,27 +1134,27 @@ static size_t format_commit_one(struct strbuf *sb, const char *placeholder,
1134 }
1135
1136 if (placeholder[0] == 'G') {
1202 - if (!c->commit_signature_parsed)
1203 - parse_commit_signature(c);
1137 + if (!c->signature_check.result)
1138 + check_commit_signature(c->commit, &(c->signature_check));
1139 switch (placeholder[1]) {
1140 case 'G':
1206 - if (c->signature.gpg_output)
1207 - strbuf_addstr(sb, c->signature.gpg_output);
1141 + if (c->signature_check.gpg_output)
1142 + strbuf_addstr(sb, c->signature_check.gpg_output);
1143 break;
1144 case '?':
1210 - switch (c->signature.good_bad) {
1145 + switch (c->signature_check.result) {
1146 case 'G':
1147 case 'B':
1213 - strbuf_addch(sb, c->signature.good_bad);
1148 + strbuf_addch(sb, c->signature_check.result);
1149 }
1150 break;
1151 case 'S':
1217 - if (c->signature.signer)
1218 - strbuf_addstr(sb, c->signature.signer);
1152 + if (c->signature_check.signer)
1153 + strbuf_addstr(sb, c->signature_check.signer);
1154 break;
1155 case 'K':
1221 - if (c->signature.key)
1222 - strbuf_addstr(sb, c->signature.key);
1156 + if (c->signature_check.key)
1157 + strbuf_addstr(sb, c->signature_check.key);
1158 break;
1159 }
1160 return 2;
@@ -1357,8 +1292,8 @@ void format_commit_message(const struct commit *commit,
1292 rewrap_message_tail(sb, &context, 0, 0, 0);
1293
1294 logmsg_free(context.message, commit);
1360 - free(context.signature.gpg_output);
1361 - free(context.signature.signer);
1295 + free(context.signature_check.gpg_output);
1296 + free(context.signature_check.signer);
1297 }
1298
1299 static void pp_header(const struct pretty_print_context *pp,