git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "Johannes Schindelin via GitGitGadget" <gitgitgadget@gmail.com>
To: git@vger.kernel.org
Cc: "brian m. carlson" <sandals@crustytoothpaste.net>,
	Johannes Schindelin <johannes.schindelin@gmx.de>,
	Johannes Schindelin <johannes.schindelin@gmx.de>
Subject: [PATCH 2/2] credential: handle `credential.<partial-URL>.<key>` again
Date: Fri, 24 Apr 2020 22:35:49 +0000	[thread overview]
Message-ID: <46ed1596f91222edeed6258a95ae8f68e3b4993f.1587767749.git.gitgitgadget@gmail.com> (raw)
In-Reply-To: <pull.620.git.1587767749.gitgitgadget@gmail.com>

From: Johannes Schindelin <johannes.schindelin@gmx.de>

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 <johannes.schindelin@gmx.de>
---
 credential.c           | 27 +++++++++++++++++++++++++++
 t/t0300-credentials.sh | 38 ++++++++++++++++++++++++++++++++++++++
 urlmatch.c             | 10 +++++++---
 urlmatch.h             |  5 +++++
 4 files changed, 77 insertions(+), 3 deletions(-)

diff --git a/credential.c b/credential.c
index b8f693fa288..4e7197d97a9 100644
--- a/credential.c
+++ b/credential.c
@@ -37,6 +37,10 @@ int credential_match(const struct credential *want,
 #undef CHECK
 }
 
+
+static int credential_from_potentially_partial_url(struct credential *c,
+						   const char *url);
+
 static int credential_config_callback(const char *var, const char *value,
 				      void *data)
 {
@@ -82,6 +86,22 @@ static int select_all(const struct urlmatch_item *a,
 	return 0;
 }
 
+static int match_partial_url(const char *url, void *cb)
+{
+	struct credential *c = cb;
+	struct credential want = CREDENTIAL_INIT;
+	int matches = 0;
+
+	if (credential_from_potentially_partial_url(&want, url) < 0)
+		warning(_("skipping credential lookup for key: credential.%s"),
+			url);
+	else
+		matches = credential_match(&want, c);
+	credential_clear(&want);
+
+	return matches;
+}
+
 static void credential_apply_config(struct credential *c)
 {
 	char *normalized_url;
@@ -101,6 +121,7 @@ static void credential_apply_config(struct credential *c)
 	config.collect_fn = credential_config_callback;
 	config.cascade_fn = NULL;
 	config.select_fn = select_all;
+	config.fallback_match_fn = match_partial_url;
 	config.cb = c;
 
 	credential_format(c, &url);
@@ -468,6 +489,12 @@ static int credential_from_url_1(struct credential *c, const char *url,
 	return 0;
 }
 
+static int credential_from_potentially_partial_url(struct credential *c,
+						   const char *url)
+{
+	return credential_from_url_1(c, url, 1, 0);
+}
+
 int credential_from_url_gently(struct credential *c, const char *url, int quiet)
 {
 	return credential_from_url_1(c, url, 0, quiet);
diff --git a/t/t0300-credentials.sh b/t/t0300-credentials.sh
index 5555a1524f1..c6643288ed6 100755
--- a/t/t0300-credentials.sh
+++ b/t/t0300-credentials.sh
@@ -575,4 +575,42 @@ test_expect_success 'credential system refuses to work with missing protocol' '
 	test_i18ncmp expect stderr
 '
 
+test_expect_success 'credential config with partial URLs' '
+	echo "echo password=yep" | write_script git-credential-yep &&
+	test_write_lines url=https://user@example.com/repo.git >stdin &&
+	for partial in \
+		example.com \
+		user@example.com \
+		https:// \
+		https://example.com \
+		https://example.com/ \
+		https://user@example.com \
+		https://user@example.com/ \
+		https://example.com/repo.git \
+		https://user@example.com/repo.git \
+		/repo.git
+	do
+		git -c credential.$partial.helper=yep \
+			credential fill <stdin >stdout &&
+		grep yep stdout ||
+		return 1
+	done &&
+
+	for partial in \
+		dont.use.this \
+		http:// \
+		/repo
+	do
+		git -c credential.$partial.helper=yep \
+			credential fill <stdin >stdout &&
+		! grep yep stdout ||
+		return 1
+	done &&
+
+	git -c credential.$partial.helper=yep \
+		-c credential.with%0anewline.username=uh-oh \
+		credential fill <stdin >stdout 2>stderr &&
+	test_i18ngrep "skipping credential lookup for key" stderr
+'
+
 test_done
diff --git a/urlmatch.c b/urlmatch.c
index 29272a5c4f4..33a2ccd306b 100644
--- a/urlmatch.c
+++ b/urlmatch.c
@@ -572,10 +572,14 @@ int urlmatch_config_entry(const char *var, const char *value, void *cb)
 
 		config_url = xmemdupz(key, dot - key);
 		norm_url = url_normalize_1(config_url, &norm_info, 1);
+		if (norm_url)
+			retval = match_urls(url, &norm_info, &matched);
+		else if (collect->fallback_match_fn)
+			retval = collect->fallback_match_fn(config_url,
+							    collect->cb);
+		else
+			retval = 0;
 		free(config_url);
-		if (!norm_url)
-			return 0;
-		retval = match_urls(url, &norm_info, &matched);
 		free(norm_url);
 		if (!retval)
 			return 0;
diff --git a/urlmatch.h b/urlmatch.h
index 2407520731f..6ff42f81b0c 100644
--- a/urlmatch.h
+++ b/urlmatch.h
@@ -59,6 +59,11 @@ struct urlmatch_config {
 	 * specificity rules) than existing.
 	 */
 	int (*select_fn)(const struct urlmatch_item *found, const struct urlmatch_item *existing);
+	/*
+	 * An optional callback to allow e.g. for partial URLs; it shall
+	 * return 1 or 0 depending whether `url` matches or not.
+	 */
+	int (*fallback_match_fn)(const char *url, void *cb);
 };
 
 int urlmatch_config_entry(const char *var, const char *value, void *cb);
-- 
gitgitgadget

  parent reply	other threads:[~2020-04-24 22:35 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-04-24 22:35 [PATCH 0/2] credential: handle partial URLs in config settings again (master) Johannes Schindelin via GitGitGadget
2020-04-24 22:35 ` [PATCH 1/2] credential: optionally allow partial URLs in credential_from_url_gently() Johannes Schindelin via GitGitGadget
2020-04-24 22:35 ` Johannes Schindelin via GitGitGadget [this message]
2020-04-24 22:53 ` [PATCH 0/2] credential: handle partial URLs in config settings again (master) Junio C Hamano

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=46ed1596f91222edeed6258a95ae8f68e3b4993f.1587767749.git.gitgitgadget@gmail.com \
    --to=gitgitgadget@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=johannes.schindelin@gmx.de \
    --cc=sandals@crustytoothpaste.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).