receive-pack: GPG-validate push certificates
Reusing the GPG signature check helpers we already have, verify
the signature in receive-pack and give the results to the hooks
via GIT_PUSH_CERT_{SIGNER,KEY,STATUS} environment variables.
Policy decisions, such as accepting or rejecting a good signature by
a key that is not fully trusted, is left to the hook and kept
outside of the core.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
@ -15,6 +15,8 @@
|
||||
#include "connected.h"
|
||||
#include "argv-array.h"
|
||||
#include "version.h"
|
||||
#include "tag.h"
|
||||
#include "gpg-interface.h"
|
||||
|
||||
static const char receive_pack_usage[] = "git receive-pack <git-dir>";
|
||||
|
||||
@ -49,6 +51,7 @@ static const char *alt_shallow_file;
|
||||
static int accept_push_cert = 1;
|
||||
static struct strbuf push_cert = STRBUF_INIT;
|
||||
static unsigned char push_cert_sha1[20];
|
||||
static struct signature_check sigcheck;
|
||||
|
||||
static enum deny_action parse_deny_action(const char *var, const char *value)
|
||||
{
|
||||
@ -277,12 +280,40 @@ static void prepare_push_cert_sha1(struct child_process *proc)
|
||||
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);
|
||||
}
|
||||
if (!is_null_sha1(push_cert_sha1)) {
|
||||
argv_array_pushf(&env, "GIT_PUSH_CERT=%s", sha1_to_hex(push_cert_sha1));
|
||||
argv_array_pushf(&env, "GIT_PUSH_CERT_SIGNER=%s",
|
||||
sigcheck.signer ? sigcheck.signer : "");
|
||||
argv_array_pushf(&env, "GIT_PUSH_CERT_KEY=%s",
|
||||
sigcheck.key ? sigcheck.key : "");
|
||||
argv_array_pushf(&env, "GIT_PUSH_CERT_STATUS=%c", sigcheck.result);
|
||||
|
||||
proc->env = env.argv;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user