Browse Source

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

"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"
maint
Junio C Hamano 5 years ago
parent
commit
4e730fcd18
  1. 11
      builtin/fmt-merge-msg.c
  2. 97
      gpg-interface.c
  3. 9
      gpg-interface.h
  4. 30
      log-tree.c

11
builtin/fmt-merge-msg.c

@ -494,7 +494,6 @@ static void fmt_merge_msg_sigs(struct strbuf *out) @@ -494,7 +494,6 @@ static void fmt_merge_msg_sigs(struct strbuf *out)
enum object_type type;
unsigned long size, len;
char *buf = read_object_file(oid, &type, &size);
struct signature_check sigc = { 0 };
struct strbuf sig = STRBUF_INIT;

if (!buf || type != OBJ_TAG)
@ -503,12 +502,10 @@ static void fmt_merge_msg_sigs(struct strbuf *out) @@ -503,12 +502,10 @@ static void fmt_merge_msg_sigs(struct strbuf *out)

if (size == len)
; /* merely annotated */
else if (!check_signature(buf, len, buf + len, size - len,
&sigc)) {
strbuf_addstr(&sig, sigc.gpg_output);
signature_check_clear(&sigc);
} else
strbuf_addstr(&sig, "gpg verification failed.\n");
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);

97
gpg-interface.c

@ -207,55 +207,6 @@ found_duplicate_status: @@ -207,55 +207,6 @@ found_duplicate_status:
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,
size_t slen, struct signature_check *sigc)
{
@ -400,3 +351,51 @@ int sign_buffer(struct strbuf *buffer, struct strbuf *signature, const char *sig @@ -400,3 +351,51 @@ int sign_buffer(struct strbuf *buffer, struct strbuf *signature, const char *sig

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;
}

9
gpg-interface.h

@ -46,6 +46,15 @@ size_t parse_signature(const char *buf, size_t size); @@ -46,6 +46,15 @@ size_t parse_signature(const char *buf, size_t size);
int sign_buffer(struct strbuf *buffer, struct strbuf *signature,
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 *);
void set_signing_key(const char *);
const char *get_signing_key(void);

30
log-tree.c

@ -449,22 +449,22 @@ static void show_signature(struct rev_info *opt, struct commit *commit) @@ -449,22 +449,22 @@ static void show_signature(struct rev_info *opt, struct commit *commit)
{
struct strbuf payload = STRBUF_INIT;
struct strbuf signature = STRBUF_INIT;
struct signature_check sigc = { 0 };
struct strbuf gpg_output = STRBUF_INIT;
int status;

if (parse_signed_commit(commit, &payload, &signature) <= 0)
goto out;

status = check_signature(payload.buf, payload.len, signature.buf,
signature.len, &sigc);
if (status && sigc.result == 'N')
show_sig_lines(opt, status, "No signature\n");
else {
show_sig_lines(opt, status, sigc.gpg_output);
signature_check_clear(&sigc);
}
status = verify_signed_buffer(payload.buf, payload.len,
signature.buf, signature.len,
&gpg_output, NULL);
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);
}
@ -497,7 +497,6 @@ static int show_one_mergetag(struct commit *commit, @@ -497,7 +497,6 @@ static int show_one_mergetag(struct commit *commit,
struct object_id oid;
struct tag *tag;
struct strbuf verify_message;
struct signature_check sigc = { 0 };
int status, nth;
size_t payload_size, gpg_message_offset;

@ -526,13 +525,12 @@ static int show_one_mergetag(struct commit *commit, @@ -526,13 +525,12 @@ static int show_one_mergetag(struct commit *commit,
status = -1;
if (extra->len > payload_size) {
/* could have a good signature */
if (!check_signature(extra->value, payload_size,
extra->value + payload_size,
extra->len - payload_size, &sigc)) {
strbuf_addstr(&verify_message, sigc.gpg_output);
signature_check_clear(&sigc);
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)
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 */
}

Loading…
Cancel
Save