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

[PATCH v3 2/3] credential: optionally allow partial URLs in credential_from_url_gently()

From
Johannes Schindelin via GitGitGadget <gitgitgadget@gmail.com>
Date
Apr 24, 2020, 11:49 UTC
Message-ID
<e92f139dfc732720f5819a954c54f2e3c5f7d1c9.1587728992.git.gitgitgadget@gmail.com>
In-Reply-To
<pull.615.v3.git.1587728992.gitgitgadget@gmail.com>
From: Johannes Schindelin <johannes.schindelin@gmx.de>

Prior to the fixes for CVE-2020-11008, we were _very_ lenient in what we required from a URL in order to parse it into a `struct credential`. That led to serious vulnerabilities.

There was one call site, though, that really needed that leniency: when parsing config settings a la `credential.dev.azure.com.useHTTPPath`. Settings like this might be desired when users want to use, say, a given user name on a given host, regardless of the protocol to be used.

In preparation for fixing that bug, let's refactor the code to optionally allow for partial URLs. For the moment, this functionality is only exposed via the now-renamed function `credential_from_url_1()`, but it is not used. The intention is to make it easier to verify that this commit does not change the existing behavior unless explicitly allowing for partial URLs.

Please note that this patch does more than just reinstating a way to imitate the behavior before those CVE-2020-11008 fixes: Before that, we would simply ignore URLs without a protocol. In other words, misleadingly, the following setting would be applied to _all_ URLs:

	[credential "example.com"]
		username = that-me

The obvious intention is to match the host name only. With this patch, we allow precisely that: when parsing the URL with non-zero `allow_partial_url`, we do not simply return success if there was no protocol, but we simply leave the protocol unset and continue parsing the URL.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 credential.c | 42 ++++++++++++++++++++++++++++++++++++------
 1 file changed, 36 insertions(+), 6 deletions(-)
diff --git a/credential.c b/credential.c
index 64a841eddca..7dbbf26f174 100644
--- a/credential.c
+++ b/credential.c
@@ -343,8 +343,31 @@ static int check_url_component(const char *url, int quiet,
 	return -1;
 }
 
-int credential_from_url_gently(struct credential *c, const char *url,
-			       int quiet)
+/*
+ * Potentially-partial URLs can, but do not have to, contain
+ *
+ * - a protocol (or scheme) of the form "<protocol>://"
+ *
+ * - a host name (the part after the protocol and before the first slash after
+ *   that, if any)
+ *
+ * - a user name and potentially a password (as "<user>[:<password>]@" part of
+ *   the host name)
+ *
+ * - a path (the part after the host name, if any, starting with the slash)
+ *
+ * Missing parts will be left unset in `struct credential`. Thus, `https://`
+ * will have only the `protocol` set, `example.com` only the host name, and
+ * `/git` only the path.
+ *
+ * Note that an empty host name in an otherwise fully-qualified URL (e.g.
+ * `cert:///path/to/cert.pem`) will be treated as unset if we expect the URL to
+ * be potentially partial, and only then (otherwise, the empty string is used).
+ *
+ * The credential_from_url() function does not allow partial URLs.
+ */
+static int credential_from_url_1(struct credential *c, const char *url,
+				 int allow_partial_url, int quiet)
 {
 	const char *at, *colon, *cp, *slash, *host, *proto_end;
 
@@ -357,12 +380,12 @@ int credential_from_url_gently(struct credential *c, const char *url,
 	 *   (3) proto://<user>:<pass>@<host>/...
 	 */
 	proto_end = strstr(url, "://");
-	if (!proto_end || proto_end == url) {
+	if (!allow_partial_url && (!proto_end || proto_end == url)) {
 		if (!quiet)
 			warning(_("url has no scheme: %s"), url);
 		return -1;
 	}
-	cp = proto_end + 3;
+	cp = proto_end ? proto_end + 3 : url;
 	at = strchr(cp, '@');
 	colon = strchr(cp, ':');
 	slash = strchrnul(cp, '/');
@@ -382,8 +405,10 @@ int credential_from_url_gently(struct credential *c, const char *url,
 		host = at + 1;
 	}
 
-	c->protocol = xmemdupz(url, proto_end - url);
-	c->host = url_decode_mem(host, slash - host);
+	if (proto_end && proto_end - url > 0)
+		c->protocol = xmemdupz(url, proto_end - url);
+	if (!allow_partial_url || slash - host > 0)
+		c->host = url_decode_mem(host, slash - host);
 	/* Trim leading and trailing slashes from path */
 	while (*slash == '/')
 		slash++;
@@ -405,6 +430,11 @@ int credential_from_url_gently(struct credential *c, const char *url,
 	return 0;
 }
 
+int credential_from_url_gently(struct credential *c, const char *url, int quiet)
+{
+	return credential_from_url_1(c, url, 0, quiet);
+}
+
 void credential_from_url(struct credential *c, const char *url)
 {
 	if (credential_from_url_gently(c, url, 0) < 0)
-- 
gitgitgadget
Previous: Junio C Hamano
Message 48 of 48 in “credential: handle partial URLs in config settings again”
  1. 0/3 credential: handle partial URLs in config settings againJohannes Schindelin via GitGitGadget, Apr 22, 2020
  2. 1/3 credential: fix grammarJohannes Schindelin via GitGitGadget, Apr 22, 2020
  3. Jonathan NiederApr 22, 2020
  4. 3/3 credential: handle `credential.<partial-URL>.<key>` againJohannes Schindelin via GitGitGadget, Apr 22, 2020
  5. Jonathan NiederApr 22, 2020
  6. Johannes SchindelinApr 23, 2020
  7. 2/3 credential: teach `credential_from_url()` a non-strict modeJohannes Schindelin via GitGitGadget, Apr 22, 2020
  8. Junio C HamanoApr 22, 2020
  9. Johannes SchindelinApr 22, 2020
  10. Junio C HamanoApr 22, 2020
  11. Jonathan NiederApr 22, 2020
  12. Carlo ArenasApr 23, 2020
  13. Johannes SchindelinApr 23, 2020
  14. Carlo Marcelo Arenas BelónApr 23, 2020
  15. Johannes SchindelinApr 23, 2020
  16. Junio C HamanoApr 23, 2020
  17. Junio C HamanoApr 23, 2020
  18. Johannes SchindelinApr 23, 2020
  19. Johannes SchindelinApr 23, 2020
  20. Jeff KingApr 22, 2020
  21. Johannes SchindelinApr 22, 2020
  22. Jonathan NiederApr 22, 2020
  23. Johannes SchindelinApr 23, 2020
  24. 0/3 credential: handle partial URLs in config settings againJohannes Schindelin via GitGitGadget, Apr 23, 2020
  25. 2/3 credential: optionally allow partial URLs in credential_from_url_gently()Johannes Schindelin via GitGitGadget, Apr 23, 2020
  26. 3/3 credential: handle `credential.<partial-URL>.<key>` againJohannes Schindelin via GitGitGadget, Apr 23, 2020
  27. Carlo Marcelo Arenas BelónApr 24, 2020
  28. Johannes SchindelinApr 24, 2020
  29. Carlo Marcelo Arenas BelónApr 24, 2020
  30. Johannes SchindelinApr 24, 2020
  31. Junio C HamanoApr 24, 2020
  32. Junio C HamanoApr 24, 2020
  33. Johannes SchindelinApr 24, 2020
  34. 1/3 credential: fix grammarJohannes Schindelin via GitGitGadget, Apr 23, 2020
  35. Carlo Marcelo Arenas BelónApr 24, 2020
  36. 0/3 credential: handle partial URLs in config settings againJohannes Schindelin via GitGitGadget, Apr 24, 2020
  37. 1/3 credential: fix grammarJohannes Schindelin via GitGitGadget, Apr 24, 2020
  38. 3/3 credential: handle `credential.<partial-URL>.<key>` againJohannes Schindelin via GitGitGadget, Apr 24, 2020
  39. Carlo Marcelo Arenas BelónApr 24, 2020
  40. Johannes SchindelinApr 25, 2020
  41. Junio C HamanoApr 24, 2020
  42. Johannes SchindelinApr 24, 2020
  43. Junio C HamanoApr 28, 2020
  44. Johannes SchindelinApr 29, 2020
  45. Junio C HamanoApr 29, 2020
  46. Johannes SchindelinMay 1, 2020
  47. Junio C HamanoMay 1, 2020
  48. 2/3 credential: optionally allow partial URLs in credential_from_url_gently()Johannes Schindelin via GitGitGadget, Apr 24, 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.