diff options
Diffstat (limited to 'credential.c')
| -rw-r--r-- | credential.c | 100 |
1 files changed, 69 insertions, 31 deletions
diff --git a/credential.c b/credential.c index ee46351ce0..2594c0c422 100644 --- a/credential.c +++ b/credential.c @@ -1,4 +1,4 @@ -#define USE_THE_REPOSITORY_VARIABLE +#define DISABLE_SIGN_COMPARE_WARNINGS #include "git-compat-util.h" #include "abspath.h" @@ -12,7 +12,9 @@ #include "sigchain.h" #include "strbuf.h" #include "urlmatch.h" -#include "git-compat-util.h" +#include "environment.h" +#include "trace2.h" +#include "repository.h" void credential_init(struct credential *c) { @@ -127,6 +129,10 @@ static int credential_config_callback(const char *var, const char *value, } else if (!strcmp(key, "usehttppath")) c->use_http_path = git_config_bool(var, value); + else if (!strcmp(key, "sanitizeprompt")) + c->sanitize_prompt = git_config_bool(var, value); + else if (!strcmp(key, "protectprotocol")) + c->protect_protocol = git_config_bool(var, value); return 0; } @@ -163,7 +169,7 @@ static int match_partial_url(const char *url, void *cb) return matches; } -static void credential_apply_config(struct credential *c) +static void credential_apply_config(struct repository *r, struct credential *c) { char *normalized_url; struct urlmatch_config config = URLMATCH_CONFIG_INIT; @@ -188,7 +194,7 @@ static void credential_apply_config(struct credential *c) credential_format(c, &url); normalized_url = url_normalize(url.buf, &config.url); - git_config(urlmatch_config_entry, &config); + repo_config(r, urlmatch_config_entry, &config); string_list_clear(&config.vars, 1); free(normalized_url); urlmatch_config_release(&config); @@ -224,7 +230,8 @@ static void credential_format(struct credential *c, struct strbuf *out) strbuf_addch(out, '@'); } if (c->host) - strbuf_addstr(out, c->host); + strbuf_add_percentencode(out, c->host, + STRBUF_ENCODE_HOST_AND_PORT); if (c->path) { strbuf_addch(out, '/'); strbuf_add_percentencode(out, c->path, 0); @@ -238,7 +245,10 @@ static char *credential_ask_one(const char *what, struct credential *c, struct strbuf prompt = STRBUF_INIT; char *r; - credential_describe(c, &desc); + if (c->sanitize_prompt) + credential_format(c, &desc); + else + credential_describe(c, &desc); if (desc.len) strbuf_addf(&prompt, "%s for '%s': ", what, desc.buf); else @@ -251,14 +261,36 @@ static char *credential_ask_one(const char *what, struct credential *c, return xstrdup(r); } -static void credential_getpass(struct credential *c) +static int credential_getpass(struct repository *r, struct credential *c) { + int interactive; + char *value; + if (!repo_config_get_maybe_bool(r, "credential.interactive", &interactive) && + !interactive) { + trace2_data_intmax("credential", r, + "interactive/skipped", 1); + return -1; + } + if (!repo_config_get_string(r, "credential.interactive", &value)) { + int same = !strcmp(value, "never"); + free(value); + if (same) { + trace2_data_intmax("credential", r, + "interactive/skipped", 1); + return -1; + } + } + + trace2_region_enter("credential", "interactive", r); if (!c->username) c->username = credential_ask_one("Username", c, PROMPT_ASKPASS|PROMPT_ECHO); if (!c->password) c->password = credential_ask_one("Password", c, PROMPT_ASKPASS); + trace2_region_leave("credential", "interactive", r); + + return 0; } int credential_has_capability(const struct credential_capability *capa, @@ -357,7 +389,8 @@ int credential_read(struct credential *c, FILE *fp, return 0; } -static void credential_write_item(FILE *fp, const char *key, const char *value, +static void credential_write_item(const struct credential *c, + FILE *fp, const char *key, const char *value, int required) { if (!value && required) @@ -366,6 +399,10 @@ static void credential_write_item(FILE *fp, const char *key, const char *value, return; if (strchr(value, '\n')) die("credential value for %s contains newline", key); + if (c->protect_protocol && strchr(value, '\r')) + die("credential value for %s contains carriage return\n" + "If this is intended, set `credential.protectProtocol=false`", + key); fprintf(fp, "%s=%s\n", key, value); } @@ -373,34 +410,34 @@ void credential_write(const struct credential *c, FILE *fp, enum credential_op_type op_type) { if (credential_has_capability(&c->capa_authtype, op_type)) - credential_write_item(fp, "capability[]", "authtype", 0); + credential_write_item(c, fp, "capability[]", "authtype", 0); if (credential_has_capability(&c->capa_state, op_type)) - credential_write_item(fp, "capability[]", "state", 0); + credential_write_item(c, fp, "capability[]", "state", 0); if (credential_has_capability(&c->capa_authtype, op_type)) { - credential_write_item(fp, "authtype", c->authtype, 0); - credential_write_item(fp, "credential", c->credential, 0); + credential_write_item(c, fp, "authtype", c->authtype, 0); + credential_write_item(c, fp, "credential", c->credential, 0); if (c->ephemeral) - credential_write_item(fp, "ephemeral", "1", 0); + credential_write_item(c, fp, "ephemeral", "1", 0); } - credential_write_item(fp, "protocol", c->protocol, 1); - credential_write_item(fp, "host", c->host, 1); - credential_write_item(fp, "path", c->path, 0); - credential_write_item(fp, "username", c->username, 0); - credential_write_item(fp, "password", c->password, 0); - credential_write_item(fp, "oauth_refresh_token", c->oauth_refresh_token, 0); + credential_write_item(c, fp, "protocol", c->protocol, 1); + credential_write_item(c, fp, "host", c->host, 1); + credential_write_item(c, fp, "path", c->path, 0); + credential_write_item(c, fp, "username", c->username, 0); + credential_write_item(c, fp, "password", c->password, 0); + credential_write_item(c, fp, "oauth_refresh_token", c->oauth_refresh_token, 0); if (c->password_expiry_utc != TIME_MAX) { char *s = xstrfmt("%"PRItime, c->password_expiry_utc); - credential_write_item(fp, "password_expiry_utc", s, 0); + credential_write_item(c, fp, "password_expiry_utc", s, 0); free(s); } for (size_t i = 0; i < c->wwwauth_headers.nr; i++) - credential_write_item(fp, "wwwauth[]", c->wwwauth_headers.v[i], 0); + credential_write_item(c, fp, "wwwauth[]", c->wwwauth_headers.v[i], 0); if (credential_has_capability(&c->capa_state, op_type)) { if (c->multistage) - credential_write_item(fp, "continue", "1", 0); + credential_write_item(c, fp, "continue", "1", 0); for (size_t i = 0; i < c->state_headers_to_send.nr; i++) - credential_write_item(fp, "state[]", c->state_headers_to_send.v[i], 0); + credential_write_item(c, fp, "state[]", c->state_headers_to_send.v[i], 0); } } @@ -464,7 +501,8 @@ static int credential_do(struct credential *c, const char *helper, return r; } -void credential_fill(struct credential *c, int all_capabilities) +void credential_fill(struct repository *r, + struct credential *c, int all_capabilities) { int i; @@ -474,7 +512,7 @@ void credential_fill(struct credential *c, int all_capabilities) credential_next_state(c); c->multistage = 0; - credential_apply_config(c); + credential_apply_config(r, c); if (all_capabilities) credential_set_all_capabilities(c, CREDENTIAL_OP_INITIAL); @@ -501,12 +539,12 @@ void credential_fill(struct credential *c, int all_capabilities) c->helpers.items[i].string); } - credential_getpass(c); - if (!c->username && !c->password && !c->credential) + if (credential_getpass(r, c) || + (!c->username && !c->password && !c->credential)) die("unable to get password from user"); } -void credential_approve(struct credential *c) +void credential_approve(struct repository *r, struct credential *c) { int i; @@ -517,20 +555,20 @@ void credential_approve(struct credential *c) credential_next_state(c); - credential_apply_config(c); + credential_apply_config(r, c); for (i = 0; i < c->helpers.nr; i++) credential_do(c, c->helpers.items[i].string, "store"); c->approved = 1; } -void credential_reject(struct credential *c) +void credential_reject(struct repository *r, struct credential *c) { int i; credential_next_state(c); - credential_apply_config(c); + credential_apply_config(r, c); for (i = 0; i < c->helpers.nr; i++) credential_do(c, c->helpers.items[i].string, "erase"); |
