diff options
author | Patrick Steinhardt <ps@pks.im> | 2021-01-12 13:27:14 +0100 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2021-01-15 13:03:45 -0800 |
commit | d8d77153eafdb0fc334e827976f09e4bdff26b58 (patch) | |
tree | 9ad261640d42b1c2e5cf36830f6c797e711ee547 /config.c | |
parent | environment: make `getenv_safe()` a public function (diff) | |
download | tgif-d8d77153eafdb0fc334e827976f09e4bdff26b58.tar.xz |
config: allow specifying config entries via envvar pairs
While we currently have the `GIT_CONFIG_PARAMETERS` environment variable
which can be used to pass runtime configuration data to git processes,
it's an internal implementation detail and not supposed to be used by
end users.
Next to being for internal use only, this way of passing config entries
has a major downside: the config keys need to be parsed as they contain
both key and value in a single variable. As such, it is left to the user
to escape any potentially harmful characters in the value, which is
quite hard to do if values are controlled by a third party.
This commit thus adds a new way of adding config entries via the
environment which gets rid of this shortcoming. If the user passes the
`GIT_CONFIG_COUNT=$n` environment variable, Git will parse environment
variable pairs `GIT_CONFIG_KEY_$i` and `GIT_CONFIG_VALUE_$i` for each
`i` in `[0,n)`.
While the same can be achieved with `git -c <name>=<value>`, one may
wish to not do so for potentially sensitive information. E.g. if one
wants to set `http.extraHeader` to contain an authentication token,
doing so via `-c` would trivially leak those credentials via e.g. ps(1),
which typically also shows command arguments.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'config.c')
-rw-r--r-- | config.c | 67 |
1 files changed, 59 insertions, 8 deletions
@@ -8,6 +8,7 @@ #include "cache.h" #include "branch.h" #include "config.h" +#include "environment.h" #include "repository.h" #include "lockfile.h" #include "exec-cmd.h" @@ -598,23 +599,73 @@ static int parse_config_env_list(char *env, config_fn_t fn, void *data) int git_config_from_parameters(config_fn_t fn, void *data) { - const char *env = getenv(CONFIG_DATA_ENVIRONMENT); + const char *env; + struct strbuf envvar = STRBUF_INIT; + struct strvec to_free = STRVEC_INIT; int ret = 0; - char *envw; + char *envw = NULL; struct config_source source; - if (!env) - return 0; - memset(&source, 0, sizeof(source)); source.prev = cf; source.origin_type = CONFIG_ORIGIN_CMDLINE; cf = &source; - /* sq_dequote will write over it */ - envw = xstrdup(env); - ret = parse_config_env_list(envw, fn, data); + env = getenv(CONFIG_COUNT_ENVIRONMENT); + if (env) { + unsigned long count; + char *endp; + int i; + count = strtoul(env, &endp, 10); + if (*endp) { + ret = error(_("bogus count in %s"), CONFIG_COUNT_ENVIRONMENT); + goto out; + } + if (count > INT_MAX) { + ret = error(_("too many entries in %s"), CONFIG_COUNT_ENVIRONMENT); + goto out; + } + + for (i = 0; i < count; i++) { + const char *key, *value; + + strbuf_addf(&envvar, "GIT_CONFIG_KEY_%d", i); + key = getenv_safe(&to_free, envvar.buf); + if (!key) { + ret = error(_("missing config key %s"), envvar.buf); + goto out; + } + strbuf_reset(&envvar); + + strbuf_addf(&envvar, "GIT_CONFIG_VALUE_%d", i); + value = getenv_safe(&to_free, envvar.buf); + if (!value) { + ret = error(_("missing config value %s"), envvar.buf); + goto out; + } + strbuf_reset(&envvar); + + if (config_parse_pair(key, value, fn, data) < 0) { + ret = -1; + goto out; + } + } + } + + env = getenv(CONFIG_DATA_ENVIRONMENT); + if (env) { + /* sq_dequote will write over it */ + envw = xstrdup(env); + if (parse_config_env_list(envw, fn, data) < 0) { + ret = -1; + goto out; + } + } + +out: + strbuf_release(&envvar); + strvec_clear(&to_free); free(envw); cf = source.prev; return ret; |