summaryrefslogtreecommitdiff
path: root/builtin/receive-pack.c
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2014-08-14 22:59:21 (GMT)
committerJunio C Hamano <gitster@pobox.com>2014-09-15 20:23:28 (GMT)
commitd05b9618ce42e85936176537f939a4eb85d4d65e (patch)
tree729f418364ffd20640fe5da3159e6c673c0c2769 /builtin/receive-pack.c
parenta85b377d0419a9dfaca8af2320cc33b051cbed04 (diff)
downloadgit-d05b9618ce42e85936176537f939a4eb85d4d65e.zip
git-d05b9618ce42e85936176537f939a4eb85d4d65e.tar.gz
git-d05b9618ce42e85936176537f939a4eb85d4d65e.tar.bz2
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>
Diffstat (limited to 'builtin/receive-pack.c')
-rw-r--r--builtin/receive-pack.c31
1 files changed, 31 insertions, 0 deletions
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index 610b085..c0a3189 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -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;
}
}