aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--Documentation/config/credential.txt5
-rw-r--r--credential.c21
-rw-r--r--credential.h4
-rwxr-xr-xt/t0300-credentials.sh16
4 files changed, 38 insertions, 8 deletions
diff --git a/Documentation/config/credential.txt b/Documentation/config/credential.txt
index fd8113d6d4..9cadca7f73 100644
--- a/Documentation/config/credential.txt
+++ b/Documentation/config/credential.txt
@@ -20,6 +20,11 @@ credential.sanitizePrompt::
will be URL-encoded by default). Configure this setting to `false` to
override that behavior.
+credential.protectProtocol::
+ By default, Carriage Return characters are not allowed in the protocol
+ that is used when Git talks to a credential helper. This setting allows
+ users to override this default.
+
credential.username::
If no username is set for a network authentication, use this username
by default. See credential.<context>.* below, and
diff --git a/credential.c b/credential.c
index 1392a54d5c..b76a730901 100644
--- a/credential.c
+++ b/credential.c
@@ -69,6 +69,8 @@ static int credential_config_callback(const char *var, const char *value,
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;
}
@@ -262,7 +264,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)
@@ -271,19 +274,23 @@ 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);
}
void credential_write(const struct credential *c, FILE *fp)
{
- 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(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);
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);
}
}
diff --git a/credential.h b/credential.h
index 0364d436d2..2c0b39a925 100644
--- a/credential.h
+++ b/credential.h
@@ -120,7 +120,8 @@ struct credential {
quit:1,
use_http_path:1,
username_from_proto:1,
- sanitize_prompt:1;
+ sanitize_prompt:1,
+ protect_protocol:1;
char *username;
char *password;
@@ -134,6 +135,7 @@ struct credential {
.helpers = STRING_LIST_INIT_DUP, \
.password_expiry_utc = TIME_MAX, \
.sanitize_prompt = 1, \
+ .protect_protocol = 1, \
}
/* Initialize a credential structure, setting all fields to empty. */
diff --git a/t/t0300-credentials.sh b/t/t0300-credentials.sh
index b62c70c193..168ae76550 100755
--- a/t/t0300-credentials.sh
+++ b/t/t0300-credentials.sh
@@ -720,6 +720,22 @@ test_expect_success 'url parser rejects embedded newlines' '
test_cmp expect stderr
'
+test_expect_success 'url parser rejects embedded carriage returns' '
+ test_config credential.helper "!true" &&
+ test_must_fail git credential fill 2>stderr <<-\EOF &&
+ url=https://example%0d.com/
+ EOF
+ cat >expect <<-\EOF &&
+ fatal: credential value for host contains carriage return
+ If this is intended, set `credential.protectProtocol=false`
+ EOF
+ test_cmp expect stderr &&
+ GIT_ASKPASS=true \
+ git -c credential.protectProtocol=false credential fill <<-\EOF
+ url=https://example%0d.com/
+ EOF
+'
+
test_expect_success 'host-less URLs are parsed as empty host' '
check fill "verbatim foo bar" <<-\EOF
url=cert:///path/to/cert.pem