Revert "gpg-interface: prefer check_signature() for GPG verification"

This reverts commit 72b006f4bf, which
breaks the end-user experience when merging a signed tag without
having the public key.  We should report "can't check because we
have no public key", but the code with this change claimed that
there was no signature.
This commit is contained in:
Junio C Hamano 2020-02-28 09:43:17 -08:00
parent 72b006f4bf
commit 0106b1d4be
4 changed files with 75 additions and 72 deletions

View File

@ -495,7 +495,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)
@ -504,12 +503,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);
signature_check_clear(&sigc);
} else
strbuf_addstr(&sig, "gpg verification failed.\n"); 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

@ -207,55 +207,6 @@ found_duplicate_status:
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)
{ {
@ -400,3 +351,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

@ -46,6 +46,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

@ -448,22 +448,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);
} }
@ -496,7 +496,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;
@ -525,13 +524,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 */
} }