Skip to content

Commit 1229499

Browse files
dschogitster
authored andcommitted
credential: handle credential.<partial-URL>.<key> again
In the patches for CVE-2020-11008, the ability to specify credential settings in the config for partial URLs got lost. For example, it used to be possible to specify a credential helper for a specific protocol: [credential "https://"] helper = my-https-helper Likewise, it used to be possible to configure settings for a specific host, e.g.: [credential "dev.azure.com"] useHTTPPath = true Let's reinstate this behavior. While at it, increase the test coverage to document and verify the behavior with a couple other categories of partial URLs. Signed-off-by: Johannes Schindelin <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent f52b0cb commit 1229499

File tree

4 files changed

+77
-3
lines changed

4 files changed

+77
-3
lines changed

credential.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ int credential_match(const struct credential *want,
3737
#undef CHECK
3838
}
3939

40+
41+
static int credential_from_potentially_partial_url(struct credential *c,
42+
const char *url);
43+
4044
static int credential_config_callback(const char *var, const char *value,
4145
void *data)
4246
{
@@ -82,6 +86,22 @@ static int select_all(const struct urlmatch_item *a,
8286
return 0;
8387
}
8488

89+
static int match_partial_url(const char *url, void *cb)
90+
{
91+
struct credential *c = cb;
92+
struct credential want = CREDENTIAL_INIT;
93+
int matches = 0;
94+
95+
if (credential_from_potentially_partial_url(&want, url) < 0)
96+
warning(_("skipping credential lookup for key: credential.%s"),
97+
url);
98+
else
99+
matches = credential_match(&want, c);
100+
credential_clear(&want);
101+
102+
return matches;
103+
}
104+
85105
static void credential_apply_config(struct credential *c)
86106
{
87107
char *normalized_url;
@@ -101,6 +121,7 @@ static void credential_apply_config(struct credential *c)
101121
config.collect_fn = credential_config_callback;
102122
config.cascade_fn = NULL;
103123
config.select_fn = select_all;
124+
config.fallback_match_fn = match_partial_url;
104125
config.cb = c;
105126

106127
credential_format(c, &url);
@@ -468,6 +489,12 @@ static int credential_from_url_1(struct credential *c, const char *url,
468489
return 0;
469490
}
470491

492+
static int credential_from_potentially_partial_url(struct credential *c,
493+
const char *url)
494+
{
495+
return credential_from_url_1(c, url, 1, 0);
496+
}
497+
471498
int credential_from_url_gently(struct credential *c, const char *url, int quiet)
472499
{
473500
return credential_from_url_1(c, url, 0, quiet);

t/t0300-credentials.sh

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -575,4 +575,42 @@ test_expect_success 'credential system refuses to work with missing protocol' '
575575
test_i18ncmp expect stderr
576576
'
577577

578+
test_expect_success 'credential config with partial URLs' '
579+
echo "echo password=yep" | write_script git-credential-yep &&
580+
test_write_lines url=https://[email protected]/repo.git >stdin &&
581+
for partial in \
582+
example.com \
583+
584+
https:// \
585+
https://example.com \
586+
https://example.com/ \
587+
588+
https://[email protected]/ \
589+
https://example.com/repo.git \
590+
https://[email protected]/repo.git \
591+
/repo.git
592+
do
593+
git -c credential.$partial.helper=yep \
594+
credential fill <stdin >stdout &&
595+
grep yep stdout ||
596+
return 1
597+
done &&
598+
599+
for partial in \
600+
dont.use.this \
601+
http:// \
602+
/repo
603+
do
604+
git -c credential.$partial.helper=yep \
605+
credential fill <stdin >stdout &&
606+
! grep yep stdout ||
607+
return 1
608+
done &&
609+
610+
git -c credential.$partial.helper=yep \
611+
-c credential.with%0anewline.username=uh-oh \
612+
credential fill <stdin >stdout 2>stderr &&
613+
test_i18ngrep "skipping credential lookup for key" stderr
614+
'
615+
578616
test_done

urlmatch.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -572,10 +572,14 @@ int urlmatch_config_entry(const char *var, const char *value, void *cb)
572572

573573
config_url = xmemdupz(key, dot - key);
574574
norm_url = url_normalize_1(config_url, &norm_info, 1);
575+
if (norm_url)
576+
retval = match_urls(url, &norm_info, &matched);
577+
else if (collect->fallback_match_fn)
578+
retval = collect->fallback_match_fn(config_url,
579+
collect->cb);
580+
else
581+
retval = 0;
575582
free(config_url);
576-
if (!norm_url)
577-
return 0;
578-
retval = match_urls(url, &norm_info, &matched);
579583
free(norm_url);
580584
if (!retval)
581585
return 0;

urlmatch.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,11 @@ struct urlmatch_config {
5959
* specificity rules) than existing.
6060
*/
6161
int (*select_fn)(const struct urlmatch_item *found, const struct urlmatch_item *existing);
62+
/*
63+
* An optional callback to allow e.g. for partial URLs; it shall
64+
* return 1 or 0 depending whether `url` matches or not.
65+
*/
66+
int (*fallback_match_fn)(const char *url, void *cb);
6267
};
6368

6469
int urlmatch_config_entry(const char *var, const char *value, void *cb);

0 commit comments

Comments
 (0)