зеркало из https://github.com/microsoft/git.git
ssh signing: provide a textual signing_key_id
For ssh the user.signingkey can be a filename/path or even a literal ssh pubkey. In push certs and textual output we prefer the ssh fingerprint instead. Signed-off-by: Fabian Stelzer <fs@gigacodes.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Родитель
fd9e226776
Коммит
4838f62c8c
|
@ -24,6 +24,7 @@ struct gpg_format {
|
|||
int (*sign_buffer)(struct strbuf *buffer, struct strbuf *signature,
|
||||
const char *signing_key);
|
||||
const char *(*get_default_key)(void);
|
||||
const char *(*get_key_id)(void);
|
||||
};
|
||||
|
||||
static const char *openpgp_verify_args[] = {
|
||||
|
@ -61,6 +62,8 @@ static int sign_buffer_ssh(struct strbuf *buffer, struct strbuf *signature,
|
|||
|
||||
static const char *get_default_ssh_signing_key(void);
|
||||
|
||||
static const char *get_ssh_key_id(void);
|
||||
|
||||
static struct gpg_format gpg_format[] = {
|
||||
{
|
||||
.name = "openpgp",
|
||||
|
@ -70,6 +73,7 @@ static struct gpg_format gpg_format[] = {
|
|||
.verify_signed_buffer = verify_gpg_signed_buffer,
|
||||
.sign_buffer = sign_buffer_gpg,
|
||||
.get_default_key = NULL,
|
||||
.get_key_id = NULL,
|
||||
},
|
||||
{
|
||||
.name = "x509",
|
||||
|
@ -79,6 +83,7 @@ static struct gpg_format gpg_format[] = {
|
|||
.verify_signed_buffer = verify_gpg_signed_buffer,
|
||||
.sign_buffer = sign_buffer_gpg,
|
||||
.get_default_key = NULL,
|
||||
.get_key_id = NULL,
|
||||
},
|
||||
{
|
||||
.name = "ssh",
|
||||
|
@ -88,6 +93,7 @@ static struct gpg_format gpg_format[] = {
|
|||
.verify_signed_buffer = NULL, /* TODO */
|
||||
.sign_buffer = sign_buffer_ssh,
|
||||
.get_default_key = get_default_ssh_signing_key,
|
||||
.get_key_id = get_ssh_key_id,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -484,6 +490,41 @@ int git_gpg_config(const char *var, const char *value, void *cb)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static char *get_ssh_key_fingerprint(const char *signing_key)
|
||||
{
|
||||
struct child_process ssh_keygen = CHILD_PROCESS_INIT;
|
||||
int ret = -1;
|
||||
struct strbuf fingerprint_stdout = STRBUF_INIT;
|
||||
struct strbuf **fingerprint;
|
||||
|
||||
/*
|
||||
* With SSH Signing this can contain a filename or a public key
|
||||
* For textual representation we usually want a fingerprint
|
||||
*/
|
||||
if (starts_with(signing_key, "ssh-")) {
|
||||
strvec_pushl(&ssh_keygen.args, "ssh-keygen", "-lf", "-", NULL);
|
||||
ret = pipe_command(&ssh_keygen, signing_key,
|
||||
strlen(signing_key), &fingerprint_stdout, 0,
|
||||
NULL, 0);
|
||||
} else {
|
||||
strvec_pushl(&ssh_keygen.args, "ssh-keygen", "-lf",
|
||||
configured_signing_key, NULL);
|
||||
ret = pipe_command(&ssh_keygen, NULL, 0, &fingerprint_stdout, 0,
|
||||
NULL, 0);
|
||||
}
|
||||
|
||||
if (!!ret)
|
||||
die_errno(_("failed to get the ssh fingerprint for key '%s'"),
|
||||
signing_key);
|
||||
|
||||
fingerprint = strbuf_split_max(&fingerprint_stdout, ' ', 3);
|
||||
if (!fingerprint[1])
|
||||
die_errno(_("failed to get the ssh fingerprint for key '%s'"),
|
||||
signing_key);
|
||||
|
||||
return strbuf_detach(fingerprint[1], NULL);
|
||||
}
|
||||
|
||||
/* Returns the first public key from an ssh-agent to use for signing */
|
||||
static const char *get_default_ssh_signing_key(void)
|
||||
{
|
||||
|
@ -532,6 +573,21 @@ static const char *get_default_ssh_signing_key(void)
|
|||
return default_key;
|
||||
}
|
||||
|
||||
static const char *get_ssh_key_id(void) {
|
||||
return get_ssh_key_fingerprint(get_signing_key());
|
||||
}
|
||||
|
||||
/* Returns a textual but unique representation of the signing key */
|
||||
const char *get_signing_key_id(void)
|
||||
{
|
||||
if (use_format->get_key_id) {
|
||||
return use_format->get_key_id();
|
||||
}
|
||||
|
||||
/* GPG/GPGSM only store a key id on this variable */
|
||||
return get_signing_key();
|
||||
}
|
||||
|
||||
const char *get_signing_key(void)
|
||||
{
|
||||
if (configured_signing_key)
|
||||
|
|
|
@ -64,6 +64,12 @@ int sign_buffer(struct strbuf *buffer, struct strbuf *signature,
|
|||
int git_gpg_config(const char *, const char *, void *);
|
||||
void set_signing_key(const char *);
|
||||
const char *get_signing_key(void);
|
||||
|
||||
/*
|
||||
* Returns a textual unique representation of the signing key in use
|
||||
* Either a GPG KeyID or a SSH Key Fingerprint
|
||||
*/
|
||||
const char *get_signing_key_id(void);
|
||||
int check_signature(const char *payload, size_t plen,
|
||||
const char *signature, size_t slen,
|
||||
struct signature_check *sigc);
|
||||
|
|
|
@ -341,13 +341,13 @@ static int generate_push_cert(struct strbuf *req_buf,
|
|||
{
|
||||
const struct ref *ref;
|
||||
struct string_list_item *item;
|
||||
char *signing_key = xstrdup(get_signing_key());
|
||||
char *signing_key_id = xstrdup(get_signing_key_id());
|
||||
const char *cp, *np;
|
||||
struct strbuf cert = STRBUF_INIT;
|
||||
int update_seen = 0;
|
||||
|
||||
strbuf_addstr(&cert, "certificate version 0.1\n");
|
||||
strbuf_addf(&cert, "pusher %s ", signing_key);
|
||||
strbuf_addf(&cert, "pusher %s ", signing_key_id);
|
||||
datestamp(&cert);
|
||||
strbuf_addch(&cert, '\n');
|
||||
if (args->url && *args->url) {
|
||||
|
@ -374,7 +374,7 @@ static int generate_push_cert(struct strbuf *req_buf,
|
|||
if (!update_seen)
|
||||
goto free_return;
|
||||
|
||||
if (sign_buffer(&cert, &cert, signing_key))
|
||||
if (sign_buffer(&cert, &cert, get_signing_key()))
|
||||
die(_("failed to sign the push certificate"));
|
||||
|
||||
packet_buf_write(req_buf, "push-cert%c%s", 0, cap_string);
|
||||
|
@ -386,7 +386,7 @@ static int generate_push_cert(struct strbuf *req_buf,
|
|||
packet_buf_write(req_buf, "push-cert-end\n");
|
||||
|
||||
free_return:
|
||||
free(signing_key);
|
||||
free(signing_key_id);
|
||||
strbuf_release(&cert);
|
||||
return update_seen;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче