git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v4] credential: fix matching URLs with multiple levels in path

From
brian m. carlson <sandals@crustytoothpaste.net>
Date
Apr 26, 2020, 17:26 UTC
Message-ID
<20200426172659.118503-1-sandals@crustytoothpaste.net>
In-Reply-To
<20200421225837.GB3515235@coredump.intra.peff.net>

46fd7b3900 ("credential: allow wildcard patterns when matching config", 2020-02-20) introduced support for matching credential helpers using urlmatch. In doing so, it introduced code to percent-encode the paths we get from the credential helper so that they could be effectively matched by the urlmatch code.

Unfortunately, that code had a bug: it percent-encoded the slashes in the path, resulting in any URL path that contained multiple levels (i.e., a directory component) not matching.

We are currently the only caller of the percent-encoding code and could simply change it not to encode slashes. However, we still want to encode slashes in the username component, so we need to have both behaviors available.

So instead, let's add a flag to control encoding slashes, which is the behavior we want here, and use it when calling the code in this case. Add a test for credential helper URLs using multiple slashes in the path, which our test suite previously lacked, as well as one ensuring that we handle usernames with slashes gracefully.

Reported-by: Ilya Tretyakov <it@it3xl.ru>
Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
---
Changes from v3:
* Don't delete the first character of the summary.
Changes from v2:
* Invert the sense of the flag.
* Shorten the flag name.
Changes from v1:
* Continue to encode slashes in usernames.
* Add a test for encoding slashes in usernames.
* Hoist existing tests near the other percent-encoding tests.
* Update commit message.
* Remove debugging information.
 credential.c           |  4 ++--
 strbuf.c               |  8 +++++---
 strbuf.h               |  7 ++++++-
 t/t0300-credentials.sh | 30 ++++++++++++++++++++++++++++++
 4 files changed, 43 insertions(+), 6 deletions(-)
diff --git a/credential.c b/credential.c
index 108d9e183a..f5327d3d9e 100644
--- a/credential.c
+++ b/credential.c
@@ -136,14 +136,14 @@ static void credential_format(struct credential *c, struct strbuf *out)
 		return;
 	strbuf_addf(out, "%s://", c->protocol);
 	if (c->username && *c->username) {
-		strbuf_add_percentencode(out, c->username);
+		strbuf_add_percentencode(out, c->username, STRBUF_ENCODE_SLASH);
 		strbuf_addch(out, '@');
 	}
 	if (c->host)
 		strbuf_addstr(out, c->host);
 	if (c->path) {
 		strbuf_addch(out, '/');
-		strbuf_add_percentencode(out, c->path);
+		strbuf_add_percentencode(out, c->path, 0);
 	}
 }
 
diff --git a/strbuf.c b/strbuf.c
index bb0065ccaf..51c83aae2d 100644
--- a/strbuf.c
+++ b/strbuf.c
@@ -479,15 +479,17 @@ void strbuf_addbuf_percentquote(struct strbuf *dst, const struct strbuf *src)
 	}
 }
 
-#define URL_UNSAFE_CHARS " <>\"%{}|\\^`:/?#[]@!$&'()*+,;="
+#define URL_UNSAFE_CHARS " <>\"%{}|\\^`:?#[]@!$&'()*+,;="
 
-void strbuf_add_percentencode(struct strbuf *dst, const char *src)
+void strbuf_add_percentencode(struct strbuf *dst, const char *src, int flags)
 {
 	size_t i, len = strlen(src);
 
 	for (i = 0; i < len; i++) {
 		unsigned char ch = src[i];
-		if (ch <= 0x1F || ch >= 0x7F || strchr(URL_UNSAFE_CHARS, ch))
+		if (ch <= 0x1F || ch >= 0x7F ||
+		    (ch == '/' && (flags & STRBUF_ENCODE_SLASH)) ||
+		    strchr(URL_UNSAFE_CHARS, ch))
 			strbuf_addf(dst, "%%%02X", (unsigned char)ch);
 		else
 			strbuf_addch(dst, ch);
diff --git a/strbuf.h b/strbuf.h
index ce8e49c0b2..e524c52e01 100644
--- a/strbuf.h
+++ b/strbuf.h
@@ -378,11 +378,16 @@ size_t strbuf_expand_dict_cb(struct strbuf *sb,
  */
 void strbuf_addbuf_percentquote(struct strbuf *dst, const struct strbuf *src);
 
+#define STRBUF_ENCODE_SLASH 1
+
 /**
  * Append the contents of a string to a strbuf, percent-encoding any characters
  * that are needed to be encoded for a URL.
+ *
+ * If STRBUF_ENCODE_SLASH is set in flags, percent-encode slashes.  Otherwise,
+ * slashes are not percent-encoded.
  */
-void strbuf_add_percentencode(struct strbuf *dst, const char *src);
+void strbuf_add_percentencode(struct strbuf *dst, const char *src, int flags);
 
 /**
  * Append the given byte size as a human-readable string (i.e. 12.23 KiB,
diff --git a/t/t0300-credentials.sh b/t/t0300-credentials.sh
index 5555a1524f..87267a7aac 100755
--- a/t/t0300-credentials.sh
+++ b/t/t0300-credentials.sh
@@ -366,6 +366,36 @@ test_expect_success 'match percent-encoded values' '
 	EOF
 '
 
+test_expect_success 'match percent-encoded values in username' '
+	test_config credential.https://user%2fname@example.com/foo/bar.git.helper "$HELPER" &&
+	check fill <<-\EOF
+	url=https://user%2fname@example.com/foo/bar.git
+	--
+	protocol=https
+	host=example.com
+	username=foo
+	password=bar
+	--
+	EOF
+'
+
+test_expect_success 'fetch with multiple path components' '
+	test_unconfig credential.helper &&
+	test_config credential.https://example.com/foo/repo.git.helper "verbatim foo bar" &&
+	check fill <<-\EOF
+	url=https://example.com/foo/repo.git
+	--
+	protocol=https
+	host=example.com
+	username=foo
+	password=bar
+	--
+	verbatim: get
+	verbatim: protocol=https
+	verbatim: host=example.com
+	EOF
+'
+
 test_expect_success 'pull username from config' '
 	test_config credential.https://example.com.username foo &&
 	check fill <<-\EOF
Previous: Eric SunshineNext: brian m. carlson
Message 18 of 20 in “Credential helpers are no longer invoked in case of having sub-folder parts in a repository URL. Since 2.26.1 version”
  1. Ilya TretyakovApr 21, 2020
  2. Jeff KingApr 21, 2020
  3. brian m. carlsonApr 22, 2020
  4. Jonathan NiederApr 22, 2020
  5. Jeff KingApr 22, 2020
  6. brian m. carlsonApr 22, 2020
  7. Jeff KingApr 22, 2020
  8. Johannes SchindelinApr 22, 2020
  9. credential: fix matching URLs with multiple levels in pathbrian m. carlson, Apr 22, 2020
  10. Jeff KingApr 22, 2020
  11. brian m. carlsonApr 22, 2020
  12. credential: fix matching URLs with multiple levels in pathbrian m. carlson, Apr 22, 2020
  13. Jeff KingApr 22, 2020
  14. Carlo Marcelo Arenas BelónApr 24, 2020
  15. Junio C HamanoApr 24, 2020
  16. redential: fix matching URLs with multiple levels in pathbrian m. carlson, Apr 25, 2020
  17. Eric SunshineApr 26, 2020
  18. credential: fix matching URLs with multiple levels in pathbrian m. carlson, Apr 26, 2020
  19. credential: fix matching URLs with multiple levels in pathbrian m. carlson, Apr 27, 2020
  20. Junio C HamanoApr 27, 2020

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.