Sync with 2.40.4
* maint-2.40: Git 2.40.4 credential: disallow Carriage Returns in the protocol by default credential: sanitize the user prompt credential_format(): also encode <host>[:<port>] t7300: work around platform-specific behaviour with long paths on MinGW compat/regex: fix argument order to calloc(3) mingw: drop bogus (and unneeded) declaration of `_pgmptr` ci: remove 'Upload failed tests' directories' step from linux32 jobsmain
commit
676cddebf9
|
@ -334,12 +334,6 @@ jobs:
|
||||||
with:
|
with:
|
||||||
name: failed-tests-${{matrix.vector.jobname}}
|
name: failed-tests-${{matrix.vector.jobname}}
|
||||||
path: ${{env.FAILED_TEST_ARTIFACTS}}
|
path: ${{env.FAILED_TEST_ARTIFACTS}}
|
||||||
- name: Upload failed tests' directories
|
|
||||||
if: failure() && env.FAILED_TEST_ARTIFACTS != '' && matrix.vector.jobname == 'linux32'
|
|
||||||
uses: actions/upload-artifact@v1 # cannot be upgraded because Node.js Actions aren't supported in this container
|
|
||||||
with:
|
|
||||||
name: failed-tests-${{matrix.vector.jobname}}
|
|
||||||
path: ${{env.FAILED_TEST_ARTIFACTS}}
|
|
||||||
static-analysis:
|
static-analysis:
|
||||||
needs: ci-config
|
needs: ci-config
|
||||||
if: needs.ci-config.outputs.enabled == 'yes'
|
if: needs.ci-config.outputs.enabled == 'yes'
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
Git v2.40.4 Release Notes
|
||||||
|
=========================
|
||||||
|
|
||||||
|
This release lets Git refuse to accept URLs that contain control
|
||||||
|
sequences. This addresses CVE-2024-50349 and CVE-2024-52006.
|
|
@ -14,6 +14,17 @@ credential.useHttpPath::
|
||||||
or https URL to be important. Defaults to false. See
|
or https URL to be important. Defaults to false. See
|
||||||
linkgit:gitcredentials[7] for more information.
|
linkgit:gitcredentials[7] for more information.
|
||||||
|
|
||||||
|
credential.sanitizePrompt::
|
||||||
|
By default, user names and hosts that are shown as part of the
|
||||||
|
password prompt are not allowed to contain control characters (they
|
||||||
|
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::
|
credential.username::
|
||||||
If no username is set for a network authentication, use this username
|
If no username is set for a network authentication, use this username
|
||||||
by default. See credential.<context>.* below, and
|
by default. See credential.<context>.* below, and
|
||||||
|
|
|
@ -27,7 +27,6 @@ static const int delay[] = { 0, 1, 10, 20, 40 };
|
||||||
void open_in_gdb(void)
|
void open_in_gdb(void)
|
||||||
{
|
{
|
||||||
static struct child_process cp = CHILD_PROCESS_INIT;
|
static struct child_process cp = CHILD_PROCESS_INIT;
|
||||||
extern char *_pgmptr;
|
|
||||||
|
|
||||||
strvec_pushl(&cp.args, "mintty", "gdb", NULL);
|
strvec_pushl(&cp.args, "mintty", "gdb", NULL);
|
||||||
strvec_pushf(&cp.args, "--pid=%d", getpid());
|
strvec_pushf(&cp.args, "--pid=%d", getpid());
|
||||||
|
|
|
@ -868,7 +868,7 @@ init_dfa (re_dfa_t *dfa, size_t pat_len)
|
||||||
if (table_size > pat_len)
|
if (table_size > pat_len)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
dfa->state_table = calloc (sizeof (struct re_state_table_entry), table_size);
|
dfa->state_table = calloc (table_size, sizeof (struct re_state_table_entry));
|
||||||
dfa->state_hash_mask = table_size - 1;
|
dfa->state_hash_mask = table_size - 1;
|
||||||
|
|
||||||
dfa->mb_cur_max = MB_CUR_MAX;
|
dfa->mb_cur_max = MB_CUR_MAX;
|
||||||
|
@ -936,7 +936,7 @@ init_dfa (re_dfa_t *dfa, size_t pat_len)
|
||||||
{
|
{
|
||||||
int i, j, ch;
|
int i, j, ch;
|
||||||
|
|
||||||
dfa->sb_char = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1);
|
dfa->sb_char = (re_bitset_ptr_t) calloc (1, sizeof (bitset_t));
|
||||||
if (BE (dfa->sb_char == NULL, 0))
|
if (BE (dfa->sb_char == NULL, 0))
|
||||||
return REG_ESPACE;
|
return REG_ESPACE;
|
||||||
|
|
||||||
|
@ -3079,9 +3079,9 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token,
|
||||||
_NL_COLLATE_SYMB_EXTRAMB);
|
_NL_COLLATE_SYMB_EXTRAMB);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
sbcset = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1);
|
sbcset = (re_bitset_ptr_t) calloc (1, sizeof (bitset_t));
|
||||||
#ifdef RE_ENABLE_I18N
|
#ifdef RE_ENABLE_I18N
|
||||||
mbcset = (re_charset_t *) calloc (sizeof (re_charset_t), 1);
|
mbcset = (re_charset_t *) calloc (1, sizeof (re_charset_t));
|
||||||
#endif /* RE_ENABLE_I18N */
|
#endif /* RE_ENABLE_I18N */
|
||||||
#ifdef RE_ENABLE_I18N
|
#ifdef RE_ENABLE_I18N
|
||||||
if (BE (sbcset == NULL || mbcset == NULL, 0))
|
if (BE (sbcset == NULL || mbcset == NULL, 0))
|
||||||
|
@ -3626,9 +3626,9 @@ build_charclass_op (re_dfa_t *dfa, RE_TRANSLATE_TYPE trans,
|
||||||
re_token_t br_token;
|
re_token_t br_token;
|
||||||
bin_tree_t *tree;
|
bin_tree_t *tree;
|
||||||
|
|
||||||
sbcset = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1);
|
sbcset = (re_bitset_ptr_t) calloc (1, sizeof (bitset_t));
|
||||||
#ifdef RE_ENABLE_I18N
|
#ifdef RE_ENABLE_I18N
|
||||||
mbcset = (re_charset_t *) calloc (sizeof (re_charset_t), 1);
|
mbcset = (re_charset_t *) calloc (1, sizeof (re_charset_t));
|
||||||
#endif /* RE_ENABLE_I18N */
|
#endif /* RE_ENABLE_I18N */
|
||||||
|
|
||||||
#ifdef RE_ENABLE_I18N
|
#ifdef RE_ENABLE_I18N
|
||||||
|
|
|
@ -1628,7 +1628,7 @@ create_ci_newstate (const re_dfa_t *dfa, const re_node_set *nodes,
|
||||||
reg_errcode_t err;
|
reg_errcode_t err;
|
||||||
re_dfastate_t *newstate;
|
re_dfastate_t *newstate;
|
||||||
|
|
||||||
newstate = (re_dfastate_t *) calloc (sizeof (re_dfastate_t), 1);
|
newstate = (re_dfastate_t *) calloc (1, sizeof (re_dfastate_t));
|
||||||
if (BE (newstate == NULL, 0))
|
if (BE (newstate == NULL, 0))
|
||||||
return NULL;
|
return NULL;
|
||||||
err = re_node_set_init_copy (&newstate->nodes, nodes);
|
err = re_node_set_init_copy (&newstate->nodes, nodes);
|
||||||
|
@ -1678,7 +1678,7 @@ create_cd_newstate (const re_dfa_t *dfa, const re_node_set *nodes,
|
||||||
reg_errcode_t err;
|
reg_errcode_t err;
|
||||||
re_dfastate_t *newstate;
|
re_dfastate_t *newstate;
|
||||||
|
|
||||||
newstate = (re_dfastate_t *) calloc (sizeof (re_dfastate_t), 1);
|
newstate = (re_dfastate_t *) calloc (1, sizeof (re_dfastate_t));
|
||||||
if (BE (newstate == NULL, 0))
|
if (BE (newstate == NULL, 0))
|
||||||
return NULL;
|
return NULL;
|
||||||
err = re_node_set_init_copy (&newstate->nodes, nodes);
|
err = re_node_set_init_copy (&newstate->nodes, nodes);
|
||||||
|
|
|
@ -2796,8 +2796,8 @@ get_subexp (re_match_context_t *mctx, int bkref_node, int bkref_str_idx)
|
||||||
continue; /* No. */
|
continue; /* No. */
|
||||||
if (sub_top->path == NULL)
|
if (sub_top->path == NULL)
|
||||||
{
|
{
|
||||||
sub_top->path = calloc (sizeof (state_array_t),
|
sub_top->path = calloc (sl_str - sub_top->str_idx + 1,
|
||||||
sl_str - sub_top->str_idx + 1);
|
sizeof (state_array_t));
|
||||||
if (sub_top->path == NULL)
|
if (sub_top->path == NULL)
|
||||||
return REG_ESPACE;
|
return REG_ESPACE;
|
||||||
}
|
}
|
||||||
|
@ -3361,7 +3361,7 @@ build_trtable (const re_dfa_t *dfa, re_dfastate_t *state)
|
||||||
if (ndests == 0)
|
if (ndests == 0)
|
||||||
{
|
{
|
||||||
state->trtable = (re_dfastate_t **)
|
state->trtable = (re_dfastate_t **)
|
||||||
calloc (sizeof (re_dfastate_t *), SBC_MAX);
|
calloc (SBC_MAX, sizeof (re_dfastate_t *));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -3457,7 +3457,7 @@ out_free:
|
||||||
discern by looking at the character code: allocate a
|
discern by looking at the character code: allocate a
|
||||||
256-entry transition table. */
|
256-entry transition table. */
|
||||||
trtable = state->trtable =
|
trtable = state->trtable =
|
||||||
(re_dfastate_t **) calloc (sizeof (re_dfastate_t *), SBC_MAX);
|
(re_dfastate_t **) calloc (SBC_MAX, sizeof (re_dfastate_t *));
|
||||||
if (BE (trtable == NULL, 0))
|
if (BE (trtable == NULL, 0))
|
||||||
goto out_free;
|
goto out_free;
|
||||||
|
|
||||||
|
@ -3488,7 +3488,7 @@ out_free:
|
||||||
transition tables, one starting at trtable[0] and one
|
transition tables, one starting at trtable[0] and one
|
||||||
starting at trtable[SBC_MAX]. */
|
starting at trtable[SBC_MAX]. */
|
||||||
trtable = state->word_trtable =
|
trtable = state->word_trtable =
|
||||||
(re_dfastate_t **) calloc (sizeof (re_dfastate_t *), 2 * SBC_MAX);
|
(re_dfastate_t **) calloc (2 * SBC_MAX, sizeof (re_dfastate_t *));
|
||||||
if (BE (trtable == NULL, 0))
|
if (BE (trtable == NULL, 0))
|
||||||
goto out_free;
|
goto out_free;
|
||||||
|
|
||||||
|
|
37
credential.c
37
credential.c
|
@ -10,7 +10,7 @@
|
||||||
#include "sigchain.h"
|
#include "sigchain.h"
|
||||||
#include "strbuf.h"
|
#include "strbuf.h"
|
||||||
#include "urlmatch.h"
|
#include "urlmatch.h"
|
||||||
#include "git-compat-util.h"
|
#include "environment.h"
|
||||||
|
|
||||||
void credential_init(struct credential *c)
|
void credential_init(struct credential *c)
|
||||||
{
|
{
|
||||||
|
@ -72,6 +72,10 @@ static int credential_config_callback(const char *var, const char *value,
|
||||||
}
|
}
|
||||||
else if (!strcmp(key, "usehttppath"))
|
else if (!strcmp(key, "usehttppath"))
|
||||||
c->use_http_path = git_config_bool(var, 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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -169,7 +173,8 @@ static void credential_format(struct credential *c, struct strbuf *out)
|
||||||
strbuf_addch(out, '@');
|
strbuf_addch(out, '@');
|
||||||
}
|
}
|
||||||
if (c->host)
|
if (c->host)
|
||||||
strbuf_addstr(out, c->host);
|
strbuf_add_percentencode(out, c->host,
|
||||||
|
STRBUF_ENCODE_HOST_AND_PORT);
|
||||||
if (c->path) {
|
if (c->path) {
|
||||||
strbuf_addch(out, '/');
|
strbuf_addch(out, '/');
|
||||||
strbuf_add_percentencode(out, c->path, 0);
|
strbuf_add_percentencode(out, c->path, 0);
|
||||||
|
@ -183,7 +188,10 @@ static char *credential_ask_one(const char *what, struct credential *c,
|
||||||
struct strbuf prompt = STRBUF_INIT;
|
struct strbuf prompt = STRBUF_INIT;
|
||||||
char *r;
|
char *r;
|
||||||
|
|
||||||
credential_describe(c, &desc);
|
if (c->sanitize_prompt)
|
||||||
|
credential_format(c, &desc);
|
||||||
|
else
|
||||||
|
credential_describe(c, &desc);
|
||||||
if (desc.len)
|
if (desc.len)
|
||||||
strbuf_addf(&prompt, "%s for '%s': ", what, desc.buf);
|
strbuf_addf(&prompt, "%s for '%s': ", what, desc.buf);
|
||||||
else
|
else
|
||||||
|
@ -266,7 +274,8 @@ int credential_read(struct credential *c, FILE *fp)
|
||||||
return 0;
|
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)
|
int required)
|
||||||
{
|
{
|
||||||
if (!value && required)
|
if (!value && required)
|
||||||
|
@ -275,24 +284,28 @@ static void credential_write_item(FILE *fp, const char *key, const char *value,
|
||||||
return;
|
return;
|
||||||
if (strchr(value, '\n'))
|
if (strchr(value, '\n'))
|
||||||
die("credential value for %s contains newline", key);
|
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);
|
fprintf(fp, "%s=%s\n", key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void credential_write(const struct credential *c, FILE *fp)
|
void credential_write(const struct credential *c, FILE *fp)
|
||||||
{
|
{
|
||||||
credential_write_item(fp, "protocol", c->protocol, 1);
|
credential_write_item(c, fp, "protocol", c->protocol, 1);
|
||||||
credential_write_item(fp, "host", c->host, 1);
|
credential_write_item(c, fp, "host", c->host, 1);
|
||||||
credential_write_item(fp, "path", c->path, 0);
|
credential_write_item(c, fp, "path", c->path, 0);
|
||||||
credential_write_item(fp, "username", c->username, 0);
|
credential_write_item(c, fp, "username", c->username, 0);
|
||||||
credential_write_item(fp, "password", c->password, 0);
|
credential_write_item(c, fp, "password", c->password, 0);
|
||||||
credential_write_item(fp, "oauth_refresh_token", c->oauth_refresh_token, 0);
|
credential_write_item(c, fp, "oauth_refresh_token", c->oauth_refresh_token, 0);
|
||||||
if (c->password_expiry_utc != TIME_MAX) {
|
if (c->password_expiry_utc != TIME_MAX) {
|
||||||
char *s = xstrfmt("%"PRItime, c->password_expiry_utc);
|
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);
|
free(s);
|
||||||
}
|
}
|
||||||
for (size_t i = 0; i < c->wwwauth_headers.nr; i++)
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int run_credential_helper(struct credential *c,
|
static int run_credential_helper(struct credential *c,
|
||||||
|
|
|
@ -134,7 +134,9 @@ struct credential {
|
||||||
configured:1,
|
configured:1,
|
||||||
quit:1,
|
quit:1,
|
||||||
use_http_path:1,
|
use_http_path:1,
|
||||||
username_from_proto:1;
|
username_from_proto:1,
|
||||||
|
sanitize_prompt:1,
|
||||||
|
protect_protocol:1;
|
||||||
|
|
||||||
char *username;
|
char *username;
|
||||||
char *password;
|
char *password;
|
||||||
|
@ -149,6 +151,8 @@ struct credential {
|
||||||
.helpers = STRING_LIST_INIT_DUP, \
|
.helpers = STRING_LIST_INIT_DUP, \
|
||||||
.password_expiry_utc = TIME_MAX, \
|
.password_expiry_utc = TIME_MAX, \
|
||||||
.wwwauth_headers = STRVEC_INIT, \
|
.wwwauth_headers = STRVEC_INIT, \
|
||||||
|
.sanitize_prompt = 1, \
|
||||||
|
.protect_protocol = 1, \
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize a credential structure, setting all fields to empty. */
|
/* Initialize a credential structure, setting all fields to empty. */
|
||||||
|
|
4
strbuf.c
4
strbuf.c
|
@ -500,7 +500,9 @@ void strbuf_add_percentencode(struct strbuf *dst, const char *src, int flags)
|
||||||
unsigned char ch = src[i];
|
unsigned char ch = src[i];
|
||||||
if (ch <= 0x1F || ch >= 0x7F ||
|
if (ch <= 0x1F || ch >= 0x7F ||
|
||||||
(ch == '/' && (flags & STRBUF_ENCODE_SLASH)) ||
|
(ch == '/' && (flags & STRBUF_ENCODE_SLASH)) ||
|
||||||
strchr(URL_UNSAFE_CHARS, ch))
|
((flags & STRBUF_ENCODE_HOST_AND_PORT) ?
|
||||||
|
!isalnum(ch) && !strchr("-.:[]", ch) :
|
||||||
|
!!strchr(URL_UNSAFE_CHARS, ch)))
|
||||||
strbuf_addf(dst, "%%%02X", (unsigned char)ch);
|
strbuf_addf(dst, "%%%02X", (unsigned char)ch);
|
||||||
else
|
else
|
||||||
strbuf_addch(dst, ch);
|
strbuf_addch(dst, ch);
|
||||||
|
|
1
strbuf.h
1
strbuf.h
|
@ -380,6 +380,7 @@ size_t strbuf_expand_dict_cb(struct strbuf *sb,
|
||||||
void strbuf_addbuf_percentquote(struct strbuf *dst, const struct strbuf *src);
|
void strbuf_addbuf_percentquote(struct strbuf *dst, const struct strbuf *src);
|
||||||
|
|
||||||
#define STRBUF_ENCODE_SLASH 1
|
#define STRBUF_ENCODE_SLASH 1
|
||||||
|
#define STRBUF_ENCODE_HOST_AND_PORT 2
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Append the contents of a string to a strbuf, percent-encoding any characters
|
* Append the contents of a string to a strbuf, percent-encoding any characters
|
||||||
|
|
|
@ -45,6 +45,10 @@ test_expect_success 'setup helper scripts' '
|
||||||
test -z "$pexpiry" || echo password_expiry_utc=$pexpiry
|
test -z "$pexpiry" || echo password_expiry_utc=$pexpiry
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
write_script git-credential-cntrl-in-username <<-\EOF &&
|
||||||
|
printf "username=\\007latrix Lestrange\\n"
|
||||||
|
EOF
|
||||||
|
|
||||||
PATH="$PWD:$PATH"
|
PATH="$PWD:$PATH"
|
||||||
'
|
'
|
||||||
|
|
||||||
|
@ -532,6 +536,19 @@ test_expect_success 'match percent-encoded values in username' '
|
||||||
EOF
|
EOF
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success 'match percent-encoded values in hostname' '
|
||||||
|
test_config "credential.https://a%20b%20c/.helper" "$HELPER" &&
|
||||||
|
check fill <<-\EOF
|
||||||
|
url=https://a b c/
|
||||||
|
--
|
||||||
|
protocol=https
|
||||||
|
host=a b c
|
||||||
|
username=foo
|
||||||
|
password=bar
|
||||||
|
--
|
||||||
|
EOF
|
||||||
|
'
|
||||||
|
|
||||||
test_expect_success 'fetch with multiple path components' '
|
test_expect_success 'fetch with multiple path components' '
|
||||||
test_unconfig credential.helper &&
|
test_unconfig credential.helper &&
|
||||||
test_config credential.https://example.com/foo/repo.git.helper "verbatim foo bar" &&
|
test_config credential.https://example.com/foo/repo.git.helper "verbatim foo bar" &&
|
||||||
|
@ -721,6 +738,22 @@ test_expect_success 'url parser rejects embedded newlines' '
|
||||||
test_cmp expect stderr
|
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' '
|
test_expect_success 'host-less URLs are parsed as empty host' '
|
||||||
check fill "verbatim foo bar" <<-\EOF
|
check fill "verbatim foo bar" <<-\EOF
|
||||||
url=cert:///path/to/cert.pem
|
url=cert:///path/to/cert.pem
|
||||||
|
@ -830,4 +863,20 @@ test_expect_success 'credential config with partial URLs' '
|
||||||
test_i18ngrep "skipping credential lookup for key" stderr
|
test_i18ngrep "skipping credential lookup for key" stderr
|
||||||
'
|
'
|
||||||
|
|
||||||
|
BEL="$(printf '\007')"
|
||||||
|
|
||||||
|
test_expect_success 'interactive prompt is sanitized' '
|
||||||
|
check fill cntrl-in-username <<-EOF
|
||||||
|
protocol=https
|
||||||
|
host=example.org
|
||||||
|
--
|
||||||
|
protocol=https
|
||||||
|
host=example.org
|
||||||
|
username=${BEL}latrix Lestrange
|
||||||
|
password=askpass-password
|
||||||
|
--
|
||||||
|
askpass: Password for ${SQ}https://%07latrix%20Lestrange@example.org${SQ}:
|
||||||
|
EOF
|
||||||
|
'
|
||||||
|
|
||||||
test_done
|
test_done
|
||||||
|
|
|
@ -351,7 +351,7 @@ test_expect_success 'push over smart http with auth' '
|
||||||
git push "$HTTPD_URL"/auth/smart/test_repo.git &&
|
git push "$HTTPD_URL"/auth/smart/test_repo.git &&
|
||||||
git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git" \
|
git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git" \
|
||||||
log -1 --format=%s >actual &&
|
log -1 --format=%s >actual &&
|
||||||
expect_askpass both user@host &&
|
expect_askpass both user%40host &&
|
||||||
test_cmp expect actual
|
test_cmp expect actual
|
||||||
'
|
'
|
||||||
|
|
||||||
|
@ -363,7 +363,7 @@ test_expect_success 'push to auth-only-for-push repo' '
|
||||||
git push "$HTTPD_URL"/auth-push/smart/test_repo.git &&
|
git push "$HTTPD_URL"/auth-push/smart/test_repo.git &&
|
||||||
git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git" \
|
git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git" \
|
||||||
log -1 --format=%s >actual &&
|
log -1 --format=%s >actual &&
|
||||||
expect_askpass both user@host &&
|
expect_askpass both user%40host &&
|
||||||
test_cmp expect actual
|
test_cmp expect actual
|
||||||
'
|
'
|
||||||
|
|
||||||
|
@ -393,7 +393,7 @@ test_expect_success 'push into half-auth-complete requires password' '
|
||||||
git push "$HTTPD_URL/half-auth-complete/smart/half-auth.git" &&
|
git push "$HTTPD_URL/half-auth-complete/smart/half-auth.git" &&
|
||||||
git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/half-auth.git" \
|
git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/half-auth.git" \
|
||||||
log -1 --format=%s >actual &&
|
log -1 --format=%s >actual &&
|
||||||
expect_askpass both user@host &&
|
expect_askpass both user%40host &&
|
||||||
test_cmp expect actual
|
test_cmp expect actual
|
||||||
'
|
'
|
||||||
|
|
||||||
|
|
|
@ -90,13 +90,13 @@ test_expect_success 'http auth can use user/pass in URL' '
|
||||||
test_expect_success 'http auth can use just user in URL' '
|
test_expect_success 'http auth can use just user in URL' '
|
||||||
set_askpass wrong pass@host &&
|
set_askpass wrong pass@host &&
|
||||||
git clone "$HTTPD_URL_USER/auth/dumb/repo.git" clone-auth-pass &&
|
git clone "$HTTPD_URL_USER/auth/dumb/repo.git" clone-auth-pass &&
|
||||||
expect_askpass pass user@host
|
expect_askpass pass user%40host
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success 'http auth can request both user and pass' '
|
test_expect_success 'http auth can request both user and pass' '
|
||||||
set_askpass user@host pass@host &&
|
set_askpass user@host pass@host &&
|
||||||
git clone "$HTTPD_URL/auth/dumb/repo.git" clone-auth-both &&
|
git clone "$HTTPD_URL/auth/dumb/repo.git" clone-auth-both &&
|
||||||
expect_askpass both user@host
|
expect_askpass both user%40host
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success 'http auth respects credential helper config' '
|
test_expect_success 'http auth respects credential helper config' '
|
||||||
|
@ -114,14 +114,14 @@ test_expect_success 'http auth can get username from config' '
|
||||||
test_config_global "credential.$HTTPD_URL.username" user@host &&
|
test_config_global "credential.$HTTPD_URL.username" user@host &&
|
||||||
set_askpass wrong pass@host &&
|
set_askpass wrong pass@host &&
|
||||||
git clone "$HTTPD_URL/auth/dumb/repo.git" clone-auth-user &&
|
git clone "$HTTPD_URL/auth/dumb/repo.git" clone-auth-user &&
|
||||||
expect_askpass pass user@host
|
expect_askpass pass user%40host
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success 'configured username does not override URL' '
|
test_expect_success 'configured username does not override URL' '
|
||||||
test_config_global "credential.$HTTPD_URL.username" wrong &&
|
test_config_global "credential.$HTTPD_URL.username" wrong &&
|
||||||
set_askpass wrong pass@host &&
|
set_askpass wrong pass@host &&
|
||||||
git clone "$HTTPD_URL_USER/auth/dumb/repo.git" clone-auth-user2 &&
|
git clone "$HTTPD_URL_USER/auth/dumb/repo.git" clone-auth-user2 &&
|
||||||
expect_askpass pass user@host
|
expect_askpass pass user%40host
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success 'set up repo with http submodules' '
|
test_expect_success 'set up repo with http submodules' '
|
||||||
|
@ -142,7 +142,7 @@ test_expect_success 'cmdline credential config passes to submodule via clone' '
|
||||||
set_askpass wrong pass@host &&
|
set_askpass wrong pass@host &&
|
||||||
git -c "credential.$HTTPD_URL.username=user@host" \
|
git -c "credential.$HTTPD_URL.username=user@host" \
|
||||||
clone --recursive super super-clone &&
|
clone --recursive super super-clone &&
|
||||||
expect_askpass pass user@host
|
expect_askpass pass user%40host
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success 'cmdline credential config passes submodule via fetch' '
|
test_expect_success 'cmdline credential config passes submodule via fetch' '
|
||||||
|
@ -153,7 +153,7 @@ test_expect_success 'cmdline credential config passes submodule via fetch' '
|
||||||
git -C super-clone \
|
git -C super-clone \
|
||||||
-c "credential.$HTTPD_URL.username=user@host" \
|
-c "credential.$HTTPD_URL.username=user@host" \
|
||||||
fetch --recurse-submodules &&
|
fetch --recurse-submodules &&
|
||||||
expect_askpass pass user@host
|
expect_askpass pass user%40host
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success 'cmdline credential config passes submodule update' '
|
test_expect_success 'cmdline credential config passes submodule update' '
|
||||||
|
@ -170,7 +170,7 @@ test_expect_success 'cmdline credential config passes submodule update' '
|
||||||
git -C super-clone \
|
git -C super-clone \
|
||||||
-c "credential.$HTTPD_URL.username=user@host" \
|
-c "credential.$HTTPD_URL.username=user@host" \
|
||||||
submodule update &&
|
submodule update &&
|
||||||
expect_askpass pass user@host
|
expect_askpass pass user%40host
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success 'fetch changes via http' '
|
test_expect_success 'fetch changes via http' '
|
||||||
|
|
|
@ -181,7 +181,7 @@ test_expect_success 'clone from password-protected repository' '
|
||||||
echo two >expect &&
|
echo two >expect &&
|
||||||
set_askpass user@host pass@host &&
|
set_askpass user@host pass@host &&
|
||||||
git clone --bare "$HTTPD_URL/auth/smart/repo.git" smart-auth &&
|
git clone --bare "$HTTPD_URL/auth/smart/repo.git" smart-auth &&
|
||||||
expect_askpass both user@host &&
|
expect_askpass both user%40host &&
|
||||||
git --git-dir=smart-auth log -1 --format=%s >actual &&
|
git --git-dir=smart-auth log -1 --format=%s >actual &&
|
||||||
test_cmp expect actual
|
test_cmp expect actual
|
||||||
'
|
'
|
||||||
|
@ -199,7 +199,7 @@ test_expect_success 'clone from auth-only-for-objects repository' '
|
||||||
echo two >expect &&
|
echo two >expect &&
|
||||||
set_askpass user@host pass@host &&
|
set_askpass user@host pass@host &&
|
||||||
git clone --bare "$HTTPD_URL/auth-fetch/smart/repo.git" half-auth &&
|
git clone --bare "$HTTPD_URL/auth-fetch/smart/repo.git" half-auth &&
|
||||||
expect_askpass both user@host &&
|
expect_askpass both user%40host &&
|
||||||
git --git-dir=half-auth log -1 --format=%s >actual &&
|
git --git-dir=half-auth log -1 --format=%s >actual &&
|
||||||
test_cmp expect actual
|
test_cmp expect actual
|
||||||
'
|
'
|
||||||
|
@ -224,14 +224,14 @@ test_expect_success 'redirects send auth to new location' '
|
||||||
set_askpass user@host pass@host &&
|
set_askpass user@host pass@host &&
|
||||||
git -c credential.useHttpPath=true \
|
git -c credential.useHttpPath=true \
|
||||||
clone $HTTPD_URL/smart-redir-auth/repo.git repo-redir-auth &&
|
clone $HTTPD_URL/smart-redir-auth/repo.git repo-redir-auth &&
|
||||||
expect_askpass both user@host auth/smart/repo.git
|
expect_askpass both user%40host auth/smart/repo.git
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success 'GIT_TRACE_CURL redacts auth details' '
|
test_expect_success 'GIT_TRACE_CURL redacts auth details' '
|
||||||
rm -rf redact-auth trace &&
|
rm -rf redact-auth trace &&
|
||||||
set_askpass user@host pass@host &&
|
set_askpass user@host pass@host &&
|
||||||
GIT_TRACE_CURL="$(pwd)/trace" git clone --bare "$HTTPD_URL/auth/smart/repo.git" redact-auth &&
|
GIT_TRACE_CURL="$(pwd)/trace" git clone --bare "$HTTPD_URL/auth/smart/repo.git" redact-auth &&
|
||||||
expect_askpass both user@host &&
|
expect_askpass both user%40host &&
|
||||||
|
|
||||||
# Ensure that there is no "Basic" followed by a base64 string, but that
|
# Ensure that there is no "Basic" followed by a base64 string, but that
|
||||||
# the auth details are redacted
|
# the auth details are redacted
|
||||||
|
@ -243,7 +243,7 @@ test_expect_success 'GIT_CURL_VERBOSE redacts auth details' '
|
||||||
rm -rf redact-auth trace &&
|
rm -rf redact-auth trace &&
|
||||||
set_askpass user@host pass@host &&
|
set_askpass user@host pass@host &&
|
||||||
GIT_CURL_VERBOSE=1 git clone --bare "$HTTPD_URL/auth/smart/repo.git" redact-auth 2>trace &&
|
GIT_CURL_VERBOSE=1 git clone --bare "$HTTPD_URL/auth/smart/repo.git" redact-auth 2>trace &&
|
||||||
expect_askpass both user@host &&
|
expect_askpass both user%40host &&
|
||||||
|
|
||||||
# Ensure that there is no "Basic" followed by a base64 string, but that
|
# Ensure that there is no "Basic" followed by a base64 string, but that
|
||||||
# the auth details are redacted
|
# the auth details are redacted
|
||||||
|
@ -256,7 +256,7 @@ test_expect_success 'GIT_TRACE_CURL does not redact auth details if GIT_TRACE_RE
|
||||||
set_askpass user@host pass@host &&
|
set_askpass user@host pass@host &&
|
||||||
GIT_TRACE_REDACT=0 GIT_TRACE_CURL="$(pwd)/trace" \
|
GIT_TRACE_REDACT=0 GIT_TRACE_CURL="$(pwd)/trace" \
|
||||||
git clone --bare "$HTTPD_URL/auth/smart/repo.git" redact-auth &&
|
git clone --bare "$HTTPD_URL/auth/smart/repo.git" redact-auth &&
|
||||||
expect_askpass both user@host &&
|
expect_askpass both user%40host &&
|
||||||
|
|
||||||
grep -i "Authorization: Basic [0-9a-zA-Z+/]" trace
|
grep -i "Authorization: Basic [0-9a-zA-Z+/]" trace
|
||||||
'
|
'
|
||||||
|
@ -568,7 +568,7 @@ test_expect_success 'http auth remembers successful credentials' '
|
||||||
# the first request prompts the user...
|
# the first request prompts the user...
|
||||||
set_askpass user@host pass@host &&
|
set_askpass user@host pass@host &&
|
||||||
git ls-remote "$HTTPD_URL/auth/smart/repo.git" >/dev/null &&
|
git ls-remote "$HTTPD_URL/auth/smart/repo.git" >/dev/null &&
|
||||||
expect_askpass both user@host &&
|
expect_askpass both user%40host &&
|
||||||
|
|
||||||
# ...and the second one uses the stored value rather than
|
# ...and the second one uses the stored value rather than
|
||||||
# prompting the user.
|
# prompting the user.
|
||||||
|
@ -599,7 +599,7 @@ test_expect_success 'http auth forgets bogus credentials' '
|
||||||
# us to prompt the user again.
|
# us to prompt the user again.
|
||||||
set_askpass user@host pass@host &&
|
set_askpass user@host pass@host &&
|
||||||
git ls-remote "$HTTPD_URL/auth/smart/repo.git" >/dev/null &&
|
git ls-remote "$HTTPD_URL/auth/smart/repo.git" >/dev/null &&
|
||||||
expect_askpass both user@host
|
expect_askpass both user%40host
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success 'client falls back from v2 to v0 to match server' '
|
test_expect_success 'client falls back from v2 to v0 to match server' '
|
||||||
|
|
|
@ -735,7 +735,7 @@ test_expect_success MINGW 'handle clean & core.longpaths = false nicely' '
|
||||||
test_must_fail git clean -xdf 2>.git/err &&
|
test_must_fail git clean -xdf 2>.git/err &&
|
||||||
# grepping for a strerror string is unportable but it is OK here with
|
# grepping for a strerror string is unportable but it is OK here with
|
||||||
# MINGW prereq
|
# MINGW prereq
|
||||||
test_i18ngrep "too long" .git/err
|
test_i18ngrep -e "too long" -e "No such file or directory" .git/err
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success 'clean untracked paths by pathspec' '
|
test_expect_success 'clean untracked paths by pathspec' '
|
||||||
|
|
Loading…
Reference in New Issue