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 void prepare_push_cert_sha1(struct child_process *proc) { static int already_done; if (!push_cert.len) return; if (!already_done) { struct strbuf gpg_output = STRBUF_INIT; struct strbuf gpg_status = STRBUF_INIT; int bogs /* beginning_of_gpg_sig */; already_done = 1; if (write_sha1_file(push_cert.buf, push_cert.len, "blob", push_cert_sha1)) hashclr(push_cert_sha1); memset(&sigcheck, '\0', sizeof(sigcheck)); sigcheck.result = 'N'; bogs = parse_signature(push_cert.buf, push_cert.len); if (verify_signed_buffer(push_cert.buf, bogs, push_cert.buf + bogs, push_cert.len - bogs, &gpg_output, &gpg_status) < 0) { ; /* error running gpg */ } else { sigcheck.payload = push_cert.buf; sigcheck.gpg_output = gpg_output.buf; sigcheck.gpg_status = gpg_status.buf; parse_gpg_output(&sigcheck); } strbuf_release(&gpg_output); strbuf_release(&gpg_status); nonce_status = check_nonce(push_cert.buf, bogs); } if (!is_null_sha1(push_cert_sha1)) { argv_array_pushf(&proc->env_array, "GIT_PUSH_CERT=%s", sha1_to_hex(push_cert_sha1)); argv_array_pushf(&proc->env_array, "GIT_PUSH_CERT_SIGNER=%s", sigcheck.signer ? sigcheck.signer : ""); argv_array_pushf(&proc->env_array, "GIT_PUSH_CERT_KEY=%s", sigcheck.key ? sigcheck.key : ""); argv_array_pushf(&proc->env_array, "GIT_PUSH_CERT_STATUS=%c", sigcheck.result); if (push_cert_nonce) { argv_array_pushf(&proc->env_array, "GIT_PUSH_CERT_NONCE=%s", push_cert_nonce); argv_array_pushf(&proc->env_array, "GIT_PUSH_CERT_NONCE_STATUS=%s", nonce_status); if (nonce_status == NONCE_SLOP) argv_array_pushf(&proc->env_array, "GIT_PUSH_CERT_NONCE_SLOP=%ld", nonce_stamp_slop); } } }
static void fmt_merge_msg_sigs(struct strbuf *out) { int i, tag_number = 0, first_tag = 0; struct strbuf tagbuf = STRBUF_INIT; for (i = 0; i < origins.nr; i++) { unsigned char *sha1 = origins.items[i].util; enum object_type type; unsigned long size, len; char *buf = read_sha1_file(sha1, &type, &size); struct strbuf sig = STRBUF_INIT; if (!buf || type != OBJ_TAG) goto next; len = parse_signature(buf, size); if (size == len) ; /* merely annotated */ else if (verify_signed_buffer(buf, len, buf + len, size - len, &sig, NULL)) { if (!sig.len) strbuf_addstr(&sig, "gpg verification failed.\n"); } if (!tag_number++) { fmt_tag_signature(&tagbuf, &sig, buf, len); first_tag = i; } else { if (tag_number == 2) { struct strbuf tagline = STRBUF_INIT; strbuf_addch(&tagline, '\n'); strbuf_add_commented_lines(&tagline, origins.items[first_tag].string, strlen(origins.items[first_tag].string)); strbuf_insert(&tagbuf, 0, tagline.buf, tagline.len); strbuf_release(&tagline); } strbuf_addch(&tagbuf, '\n'); strbuf_add_commented_lines(&tagbuf, origins.items[i].string, strlen(origins.items[i].string)); fmt_tag_signature(&tagbuf, &sig, buf, len); } strbuf_release(&sig); next: free(buf); } if (tagbuf.len) { strbuf_addch(out, '\n'); strbuf_addbuf(out, &tagbuf); } strbuf_release(&tagbuf); }
static int run_gpg_verify(const char *buf, unsigned long size, int verbose) { int len; len = parse_signature(buf, size); if (verbose) write_in_full(1, buf, len); if (size == len) return error("no signature found"); return verify_signed_buffer(buf, len, buf + len, size - len, NULL); }
static void show_one_mergetag(struct rev_info *opt, struct commit_extra_header *extra, struct commit *commit) { unsigned char sha1[20]; struct tag *tag; struct strbuf verify_message; int status, nth; size_t payload_size, gpg_message_offset; hash_sha1_file(extra->value, extra->len, typename(OBJ_TAG), sha1); tag = lookup_tag(sha1); if (!tag) return; /* error message already given */ strbuf_init(&verify_message, 256); if (parse_tag_buffer(tag, extra->value, extra->len)) strbuf_addstr(&verify_message, "malformed mergetag\n"); else if (is_common_merge(commit) && !hashcmp(tag->tagged->sha1, commit->parents->next->item->object.sha1)) strbuf_addf(&verify_message, "merged tag '%s'\n", tag->tag); else if ((nth = which_parent(tag->tagged->sha1, commit)) < 0) strbuf_addf(&verify_message, "tag %s names a non-parent %s\n", tag->tag, tag->tagged->sha1); else strbuf_addf(&verify_message, "parent #%d, tagged '%s'\n", nth + 1, tag->tag); gpg_message_offset = verify_message.len; payload_size = parse_signature(extra->value, extra->len); if ((extra->len <= payload_size) || (verify_signed_buffer(extra->value, payload_size, extra->value + payload_size, extra->len - payload_size, &verify_message) && verify_message.len <= gpg_message_offset)) { strbuf_addstr(&verify_message, "No signature\n"); status = -1; } else if (strstr(verify_message.buf + gpg_message_offset, ": Good signature from ")) status = 0; else status = -1; show_sig_lines(opt, status, verify_message.buf); strbuf_release(&verify_message); }
static void show_one_mergetag(struct commit *commit, struct commit_extra_header *extra, void *data) { struct rev_info *opt = (struct rev_info *)data; unsigned char sha1[20]; struct tag *tag; struct strbuf verify_message; int status, nth; size_t payload_size, gpg_message_offset; hash_sha1_file(extra->value, extra->len, typename(OBJ_TAG), sha1); tag = lookup_tag(sha1); if (!tag) return; /* error message already given */ strbuf_init(&verify_message, 256); if (parse_tag_buffer(tag, extra->value, extra->len)) strbuf_addstr(&verify_message, "malformed mergetag\n"); else if (is_common_merge(commit) && !oidcmp(&tag->tagged->oid, &commit->parents->next->item->object.oid)) strbuf_addf(&verify_message, "merged tag '%s'\n", tag->tag); else if ((nth = which_parent(tag->tagged->oid.hash, commit)) < 0) strbuf_addf(&verify_message, "tag %s names a non-parent %s\n", tag->tag, tag->tagged->oid.hash); else strbuf_addf(&verify_message, "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) { /* could have a good signature */ if (!verify_signed_buffer(extra->value, payload_size, extra->value + payload_size, extra->len - payload_size, &verify_message, NULL)) status = 0; /* good */ else if (verify_message.len <= gpg_message_offset) strbuf_addstr(&verify_message, "No signature\n"); /* otherwise we couldn't verify, which is shown as bad */ } show_sig_lines(opt, status, verify_message.buf); strbuf_release(&verify_message); }
static void show_signature(struct rev_info *opt, struct commit *commit) { struct strbuf payload = STRBUF_INIT; struct strbuf signature = STRBUF_INIT; struct strbuf gpg_output = STRBUF_INIT; int status; 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) strbuf_addstr(&gpg_output, "No signature\n"); show_sig_lines(opt, status, gpg_output.buf); out: strbuf_release(&gpg_output); strbuf_release(&payload); strbuf_release(&signature); }
int check_signature(const char *payload, size_t plen, const char *signature, size_t slen, struct signature_check *sigc) { struct strbuf gpg_output = STRBUF_INIT; struct strbuf gpg_status = STRBUF_INIT; int status; sigc->result = 'N'; status = verify_signed_buffer(payload, plen, signature, slen, &gpg_output, &gpg_status); if (status && !gpg_output.len) goto out; sigc->payload = xmemdupz(payload, plen); 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); return sigc->result != 'G' && sigc->result != 'U'; }