1
0
Fork 0
mirror of https://github.com/git/git.git synced 2024-10-28 04:49:43 +01:00

gpg-interface: fix misdesigned signing key interfaces

The interfaces to retrieve signing keys and their IDs are misdesigned as
they return string constants even though they indeed allocate memory,
which leads to memory leaks. Refactor the code to instead always return
allocated strings and let the callers free them accordingly.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Patrick Steinhardt 2024-09-05 12:09:07 +02:00 committed by Junio C Hamano
parent 49d47eb541
commit b8849e236f
6 changed files with 30 additions and 19 deletions

View file

@ -160,7 +160,7 @@ static int do_sign(struct strbuf *buffer, struct object_id **compat_oid,
const struct git_hash_algo *compat = the_repository->compat_hash_algo; const struct git_hash_algo *compat = the_repository->compat_hash_algo;
struct strbuf sig = STRBUF_INIT, compat_sig = STRBUF_INIT; struct strbuf sig = STRBUF_INIT, compat_sig = STRBUF_INIT;
struct strbuf compat_buf = STRBUF_INIT; struct strbuf compat_buf = STRBUF_INIT;
const char *keyid = get_signing_key(); char *keyid = get_signing_key();
int ret = -1; int ret = -1;
if (sign_buffer(buffer, &sig, keyid)) if (sign_buffer(buffer, &sig, keyid))
@ -190,6 +190,7 @@ static int do_sign(struct strbuf *buffer, struct object_id **compat_oid,
strbuf_release(&sig); strbuf_release(&sig);
strbuf_release(&compat_sig); strbuf_release(&compat_sig);
strbuf_release(&compat_buf); strbuf_release(&compat_buf);
free(keyid);
return ret; return ret;
} }

View file

@ -1150,11 +1150,14 @@ int add_header_signature(struct strbuf *buf, struct strbuf *sig, const struct gi
static int sign_commit_to_strbuf(struct strbuf *sig, struct strbuf *buf, const char *keyid) static int sign_commit_to_strbuf(struct strbuf *sig, struct strbuf *buf, const char *keyid)
{ {
char *keyid_to_free = NULL;
int ret = 0;
if (!keyid || !*keyid) if (!keyid || !*keyid)
keyid = get_signing_key(); keyid = keyid_to_free = get_signing_key();
if (sign_buffer(buf, sig, keyid)) if (sign_buffer(buf, sig, keyid))
return -1; ret = -1;
return 0; free(keyid_to_free);
return ret;
} }
int parse_signed_commit(const struct commit *commit, int parse_signed_commit(const struct commit *commit,

View file

@ -45,8 +45,8 @@ struct gpg_format {
size_t signature_size); size_t signature_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);
const char *(*get_default_key)(void); char *(*get_default_key)(void);
const char *(*get_key_id)(void); char *(*get_key_id)(void);
}; };
static const char *openpgp_verify_args[] = { static const char *openpgp_verify_args[] = {
@ -86,9 +86,9 @@ static int sign_buffer_gpg(struct strbuf *buffer, struct strbuf *signature,
static int sign_buffer_ssh(struct strbuf *buffer, struct strbuf *signature, static int sign_buffer_ssh(struct strbuf *buffer, struct strbuf *signature,
const char *signing_key); const char *signing_key);
static const char *get_default_ssh_signing_key(void); static char *get_default_ssh_signing_key(void);
static const char *get_ssh_key_id(void); static char *get_ssh_key_id(void);
static struct gpg_format gpg_format[] = { static struct gpg_format gpg_format[] = {
{ {
@ -847,7 +847,7 @@ static char *get_ssh_key_fingerprint(const char *signing_key)
} }
/* Returns the first public key from an ssh-agent to use for signing */ /* Returns the first public key from an ssh-agent to use for signing */
static const char *get_default_ssh_signing_key(void) static char *get_default_ssh_signing_key(void)
{ {
struct child_process ssh_default_key = CHILD_PROCESS_INIT; struct child_process ssh_default_key = CHILD_PROCESS_INIT;
int ret = -1; int ret = -1;
@ -899,12 +899,16 @@ static const char *get_default_ssh_signing_key(void)
return default_key; return default_key;
} }
static const char *get_ssh_key_id(void) { static char *get_ssh_key_id(void)
return get_ssh_key_fingerprint(get_signing_key()); {
char *signing_key = get_signing_key();
char *key_id = get_ssh_key_fingerprint(signing_key);
free(signing_key);
return key_id;
} }
/* Returns a textual but unique representation of the signing key */ /* Returns a textual but unique representation of the signing key */
const char *get_signing_key_id(void) char *get_signing_key_id(void)
{ {
gpg_interface_lazy_init(); gpg_interface_lazy_init();
@ -916,17 +920,17 @@ const char *get_signing_key_id(void)
return get_signing_key(); return get_signing_key();
} }
const char *get_signing_key(void) char *get_signing_key(void)
{ {
gpg_interface_lazy_init(); gpg_interface_lazy_init();
if (configured_signing_key) if (configured_signing_key)
return configured_signing_key; return xstrdup(configured_signing_key);
if (use_format->get_default_key) { if (use_format->get_default_key) {
return use_format->get_default_key(); return use_format->get_default_key();
} }
return git_committer_info(IDENT_STRICT | IDENT_NO_DATE); return xstrdup(git_committer_info(IDENT_STRICT | IDENT_NO_DATE));
} }
const char *gpg_trust_level_to_str(enum signature_trust_level level) const char *gpg_trust_level_to_str(enum signature_trust_level level)

View file

@ -80,13 +80,13 @@ int sign_buffer(struct strbuf *buffer, struct strbuf *signature,
const char *gpg_trust_level_to_str(enum signature_trust_level level); const char *gpg_trust_level_to_str(enum signature_trust_level level);
void set_signing_key(const char *); void set_signing_key(const char *);
const char *get_signing_key(void); char *get_signing_key(void);
/* /*
* Returns a textual unique representation of the signing key in use * Returns a textual unique representation of the signing key in use
* Either a GPG KeyID or a SSH Key Fingerprint * Either a GPG KeyID or a SSH Key Fingerprint
*/ */
const char *get_signing_key_id(void); char *get_signing_key_id(void);
int check_signature(struct signature_check *sigc, int check_signature(struct signature_check *sigc,
const char *signature, size_t slen); const char *signature, size_t slen);
void print_signature_buffer(const struct signature_check *sigc, void print_signature_buffer(const struct signature_check *sigc,

View file

@ -348,7 +348,8 @@ static int generate_push_cert(struct strbuf *req_buf,
{ {
const struct ref *ref; const struct ref *ref;
struct string_list_item *item; struct string_list_item *item;
char *signing_key_id = xstrdup(get_signing_key_id()); char *signing_key_id = get_signing_key_id();
char *signing_key = get_signing_key();
const char *cp, *np; const char *cp, *np;
struct strbuf cert = STRBUF_INIT; struct strbuf cert = STRBUF_INIT;
int update_seen = 0; int update_seen = 0;
@ -381,7 +382,7 @@ static int generate_push_cert(struct strbuf *req_buf,
if (!update_seen) if (!update_seen)
goto free_return; goto free_return;
if (sign_buffer(&cert, &cert, get_signing_key())) if (sign_buffer(&cert, &cert, signing_key))
die(_("failed to sign the push certificate")); die(_("failed to sign the push certificate"));
packet_buf_write(req_buf, "push-cert%c%s", 0, cap_string); packet_buf_write(req_buf, "push-cert%c%s", 0, cap_string);
@ -394,6 +395,7 @@ static int generate_push_cert(struct strbuf *req_buf,
free_return: free_return:
free(signing_key_id); free(signing_key_id);
free(signing_key);
strbuf_release(&cert); strbuf_release(&cert);
return update_seen; return update_seen;
} }

View file

@ -5,6 +5,7 @@ test_description='signed push'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
. "$TEST_DIRECTORY"/lib-gpg.sh . "$TEST_DIRECTORY"/lib-gpg.sh