Merge branch 'hi/gpg-use-check-signature'

"git merge signed-tag" while lacking the public key started to say
"No signature", which was utterly wrong.  This regression has been
reverted.

* hi/gpg-use-check-signature:
  Revert "gpg-interface: prefer check_signature() for GPG verification"
This commit is contained in:
Junio C Hamano 2020-03-05 10:43:05 -08:00
commit e63cefb024
4 changed files with 75 additions and 72 deletions

View File

@ -494,7 +494,6 @@ static void fmt_merge_msg_sigs(struct strbuf *out)
enum object_type type; enum object_type type;
unsigned long size, len; unsigned long size, len;
char *buf = read_object_file(oid, &type, &size); char *buf = read_object_file(oid, &type, &size);
struct signature_check sigc = { 0 };
struct strbuf sig = STRBUF_INIT; struct strbuf sig = STRBUF_INIT;
if (!buf || type != OBJ_TAG) if (!buf || type != OBJ_TAG)
@ -503,12 +502,10 @@ static void fmt_merge_msg_sigs(struct strbuf *out)
if (size == len) if (size == len)
; /* merely annotated */ ; /* merely annotated */
else if (!check_signature(buf, len, buf + len, size - len, else if (verify_signed_buffer(buf, len, buf + len, size - len, &sig, NULL)) {
&sigc)) { if (!sig.len)
strbuf_addstr(&sig, sigc.gpg_output); strbuf_addstr(&sig, "gpg verification failed.\n");
signature_check_clear(&sigc); }
} else
strbuf_addstr(&sig, "gpg verification failed.\n");
if (!tag_number++) { if (!tag_number++) {
fmt_tag_signature(&tagbuf, &sig, buf, len); fmt_tag_signature(&tagbuf, &sig, buf, len);

View File

@ -256,55 +256,6 @@ error:
FREE_AND_NULL(sigc->key); FREE_AND_NULL(sigc->key);
} }
static 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)
{
struct child_process gpg = CHILD_PROCESS_INIT;
struct gpg_format *fmt;
struct tempfile *temp;
int ret;
struct strbuf buf = STRBUF_INIT;
temp = mks_tempfile_t(".git_vtag_tmpXXXXXX");
if (!temp)
return error_errno(_("could not create temporary file"));
if (write_in_full(temp->fd, signature, signature_size) < 0 ||
close_tempfile_gently(temp) < 0) {
error_errno(_("failed writing detached signature to '%s'"),
temp->filename.buf);
delete_tempfile(&temp);
return -1;
}
fmt = get_format_by_sig(signature);
if (!fmt)
BUG("bad signature '%s'", signature);
argv_array_push(&gpg.args, fmt->program);
argv_array_pushv(&gpg.args, fmt->verify_args);
argv_array_pushl(&gpg.args,
"--status-fd=1",
"--verify", temp->filename.buf, "-",
NULL);
if (!gpg_status)
gpg_status = &buf;
sigchain_push(SIGPIPE, SIG_IGN);
ret = pipe_command(&gpg, payload, payload_size,
gpg_status, 0, gpg_output, 0);
sigchain_pop(SIGPIPE);
delete_tempfile(&temp);
ret |= !strstr(gpg_status->buf, "\n[GNUPG:] GOODSIG ");
strbuf_release(&buf); /* no matter it was used or not */
return ret;
}
int check_signature(const char *payload, size_t plen, const char *signature, int check_signature(const char *payload, size_t plen, const char *signature,
size_t slen, struct signature_check *sigc) size_t slen, struct signature_check *sigc)
{ {
@ -467,3 +418,51 @@ int sign_buffer(struct strbuf *buffer, struct strbuf *signature, const char *sig
return 0; return 0;
} }
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)
{
struct child_process gpg = CHILD_PROCESS_INIT;
struct gpg_format *fmt;
struct tempfile *temp;
int ret;
struct strbuf buf = STRBUF_INIT;
temp = mks_tempfile_t(".git_vtag_tmpXXXXXX");
if (!temp)
return error_errno(_("could not create temporary file"));
if (write_in_full(temp->fd, signature, signature_size) < 0 ||
close_tempfile_gently(temp) < 0) {
error_errno(_("failed writing detached signature to '%s'"),
temp->filename.buf);
delete_tempfile(&temp);
return -1;
}
fmt = get_format_by_sig(signature);
if (!fmt)
BUG("bad signature '%s'", signature);
argv_array_push(&gpg.args, fmt->program);
argv_array_pushv(&gpg.args, fmt->verify_args);
argv_array_pushl(&gpg.args,
"--status-fd=1",
"--verify", temp->filename.buf, "-",
NULL);
if (!gpg_status)
gpg_status = &buf;
sigchain_push(SIGPIPE, SIG_IGN);
ret = pipe_command(&gpg, payload, payload_size,
gpg_status, 0, gpg_output, 0);
sigchain_pop(SIGPIPE);
delete_tempfile(&temp);
ret |= !strstr(gpg_status->buf, "\n[GNUPG:] GOODSIG ");
strbuf_release(&buf); /* no matter it was used or not */
return ret;
}

View File

@ -54,6 +54,15 @@ size_t parse_signature(const char *buf, size_t size);
int sign_buffer(struct strbuf *buffer, struct strbuf *signature, int sign_buffer(struct strbuf *buffer, struct strbuf *signature,
const char *signing_key); const char *signing_key);
/*
* Run "gpg" to see if the payload matches the detached signature.
* gpg_output, when set, receives the diagnostic output from GPG.
* gpg_status, when set, receives the status output from GPG.
*/
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);
int git_gpg_config(const char *, const char *, void *); int git_gpg_config(const char *, const char *, void *);
void set_signing_key(const char *); void set_signing_key(const char *);
const char *get_signing_key(void); const char *get_signing_key(void);

View File

@ -449,22 +449,22 @@ static void show_signature(struct rev_info *opt, struct commit *commit)
{ {
struct strbuf payload = STRBUF_INIT; struct strbuf payload = STRBUF_INIT;
struct strbuf signature = STRBUF_INIT; struct strbuf signature = STRBUF_INIT;
struct signature_check sigc = { 0 }; struct strbuf gpg_output = STRBUF_INIT;
int status; int status;
if (parse_signed_commit(commit, &payload, &signature) <= 0) if (parse_signed_commit(commit, &payload, &signature) <= 0)
goto out; goto out;
status = check_signature(payload.buf, payload.len, signature.buf, status = verify_signed_buffer(payload.buf, payload.len,
signature.len, &sigc); signature.buf, signature.len,
if (status && sigc.result == 'N') &gpg_output, NULL);
show_sig_lines(opt, status, "No signature\n"); if (status && !gpg_output.len)
else { strbuf_addstr(&gpg_output, "No signature\n");
show_sig_lines(opt, status, sigc.gpg_output);
signature_check_clear(&sigc); show_sig_lines(opt, status, gpg_output.buf);
}
out: out:
strbuf_release(&gpg_output);
strbuf_release(&payload); strbuf_release(&payload);
strbuf_release(&signature); strbuf_release(&signature);
} }
@ -497,7 +497,6 @@ static int show_one_mergetag(struct commit *commit,
struct object_id oid; struct object_id oid;
struct tag *tag; struct tag *tag;
struct strbuf verify_message; struct strbuf verify_message;
struct signature_check sigc = { 0 };
int status, nth; int status, nth;
size_t payload_size, gpg_message_offset; size_t payload_size, gpg_message_offset;
@ -527,13 +526,12 @@ static int show_one_mergetag(struct commit *commit,
status = -1; status = -1;
if (extra->len > payload_size) { if (extra->len > payload_size) {
/* could have a good signature */ /* could have a good signature */
if (!check_signature(extra->value, payload_size, if (!verify_signed_buffer(extra->value, payload_size,
extra->value + payload_size, extra->value + payload_size,
extra->len - payload_size, &sigc)) { extra->len - payload_size,
strbuf_addstr(&verify_message, sigc.gpg_output); &verify_message, NULL))
signature_check_clear(&sigc);
status = 0; /* good */ status = 0; /* good */
} else if (verify_message.len <= gpg_message_offset) else if (verify_message.len <= gpg_message_offset)
strbuf_addstr(&verify_message, "No signature\n"); strbuf_addstr(&verify_message, "No signature\n");
/* otherwise we couldn't verify, which is shown as bad */ /* otherwise we couldn't verify, which is shown as bad */
} }