From: "Johannes Schindelin via GitGitGadget" <gitgitgadget@gmail.com>
To: git@vger.kernel.org
Cc: Jeff King <peff@peff.net>,
"brian m. carlson" <sandals@crustytoothpaste.net>,
Jonathan Nieder <jrnieder@gmail.com>,
Ilya Tretyakov <it@it3xl.ru>, Junio C Hamano <gitster@pobox.com>,
Johannes Schindelin <johannes.schindelin@gmx.de>
Subject: [PATCH v3 0/3] credential: handle partial URLs in config settings again
Date: Fri, 24 Apr 2020 11:49:49 +0000 [thread overview]
Message-ID: <pull.615.v3.git.1587728992.gitgitgadget@gmail.com> (raw)
In-Reply-To: <pull.615.v2.git.1587685397.gitgitgadget@gmail.com>
This fixes the problem illustrated by Peff's example
[https://lore.kernel.org/git/20200422040644.GC3559880@coredump.intra.peff.net/]
, in maint-2.17:
$ echo url=https://example.com |
git -c credential.example.com.username=foo credential fill
warning: url has no scheme: example.com
fatal: credential url cannot be parsed: example.com
The fix is necessarily different than what was proposed by brian
[https://lore.kernel.org/git/20200422012344.2051103-1-sandals@crustytoothpaste.net/]
because that fix targets v2.26.x which has 46fd7b390034 (credential: allow
wildcard patterns when matching config, 2020-02-20).
This patch series targets maint-2.17 instead (and might actually not be able
to fix maint due to that wildcard pattern patch; I haven't had the time to
check yet).
Please note that Git v2.17.4 will not do what we would expect here: if any
host name (without protocol) is specified, e.g. -c
credential.golli.wog.username = boo, it will actually ignore the host name.
That is, this will populate the username:
$ echo url=https://example.com |
git -c credential.totally.bog.us.username=foo credential fill
Obviously, this is unexpected, as a Git config like this would leave the
last specified user name as "winner":
[credential "first.com"]
username = Whos On
[credential "second.com"]
username = Who
This patch series fixes this. The quoted part of [credential "<value>"] will
be interpreted as a partial URL:
* It can start with a protocol followed by ://, but does not have to.
* If it starts with a protocol, the host name will always be set (if the
:// is followed immediately by yet another slash, then it will be set to
the empty string).
* If it starts without a protocol, it is treated as a path if the value
starts with a slash (and the host will be left unset).
* If it starts without a protocol and the first character is not a slash,
it will be treated as a host name, optionally followed by a slash and the
path.
Changes since v2:
* Refactored out the credential_from_potentially_partial_url() function so
that existing callers (except for the one we want to change) stay
untouched.
* When encountering an invalid URL while parsing the config, we no longer
suppress the parser's warning.
* The test now uses the file name convention stdin/stdout/stderr of
t/lib-credential.sh.
Changes since v1:
* The condition when the c->host field is set was made more intuitive.
* The "fix grammar" commit now has Jonathan's "reviewed-by" footer.
* Inverted the meaning of the parameter strict and renamed it to
allow_partial_urls, to clarify its role.
* Enhanced the commit message of the second patch to illustrate the
motivation for the lenient mode a bit better.
* [Not a change] I did leave the second and the third patch separate from
one another. This makes it a lot easier to follow the iteration and to
keep the reviews straight: it separates the "how do we make URL parts
optional?" from the "where do we need URL parts to be optional?"
* A partial URL https:// is now correctly interpreted as having only the
protocol set, but not host name nor path.
* The lenient mode is now explained a lot more verbosely in the code
comment in credential.h.
* When skipping a config setting, we now show the config key, not just the
URL (which might be incomplete, i.e. not actually a URL).
* When skipping a config setting, the correct struct credential is cleared
(i.e. the just-parsed one, not the one against which we wanted to match
the just-parsed one).
* Added a ton more partial URLs to the test, and the test now also verifies
that the warning comes out all right.
Johannes Schindelin (3):
credential: fix grammar
credential: optionally allow partial URLs in
credential_from_url_gently()
credential: handle `credential.<partial-URL>.<key>` again
credential.c | 60 +++++++++++++++++++++++++++++++++++++-----
credential.h | 2 +-
t/t0300-credentials.sh | 39 +++++++++++++++++++++++++++
3 files changed, 93 insertions(+), 8 deletions(-)
base-commit: df5be6dc3fd18c294ec93a9af0321334e3f92c9c
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-615%2Fdscho%2Fcredential-config-partial-url-maint-2.17-v3
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-615/dscho/credential-config-partial-url-maint-2.17-v3
Pull-Request: https://github.com/gitgitgadget/git/pull/615
Range-diff vs v2:
1: 2c1c0ae91eb = 1: 2c1c0ae91eb credential: fix grammar
2: fc772d21b74 ! 2: e92f139dfc7 credential: optionally allow partial URLs in credential_from_url_gently()
@@ Commit message
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 add a parameter called
- `allow_partial_url` to the `credential_from_url_gently()` function and
- convert the existing callers to set that parameter to 0, i.e. do not
- change the existing behavior, just add the option to be more lenient.
+ 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
@@ Commit message
## credential.c ##
@@ credential.c: static int check_url_component(const char *url, int quiet,
+ return -1;
}
- int credential_from_url_gently(struct credential *c, const char *url,
+-int credential_from_url_gently(struct credential *c, const char *url,
- int quiet)
-+ int allow_partial_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;
@@ credential.c: int credential_from_url_gently(struct credential *c, const char *u
while (*slash == '/')
slash++;
@@ credential.c: 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)
-+ if (credential_from_url_gently(c, url, 0, 0) < 0)
- die(_("credential url cannot be parsed: %s"), url);
- }
-
- ## credential.h ##
-@@ credential.h: void credential_write(const struct credential *, FILE *);
- * an error but leave the broken state in the credential object for further
- * examination. The non-gentle form will issue a warning to stderr and return
- * an empty credential.
-+ *
-+ * If allow_partial_url is non-zero, partial URLs are allowed, i.e. it can, but
-+ * does 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 will be
-+ * treated as unset when allow_partial_url is non-zero (and only then,
-+ * otherwise it is treated as the empty string).
-+ *
-+ * The credential_from_url() function does not allow partial URLs.
- */
- void credential_from_url(struct credential *, const char *url);
--int credential_from_url_gently(struct credential *, const char *url, int quiet);
-+int credential_from_url_gently(struct credential *, const char *url,
-+ int allow_partial_url, int quiet);
-
- int credential_match(const struct credential *have,
- const struct credential *want);
-
- ## fsck.c ##
-@@ fsck.c: static int check_submodule_url(const char *url)
- else if (url_to_curl_url(url, &curl_url)) {
- struct credential c = CREDENTIAL_INIT;
- int ret = 0;
-- if (credential_from_url_gently(&c, curl_url, 1) ||
-+ if (credential_from_url_gently(&c, curl_url, 0, 1) ||
- !*c.host)
- ret = -1;
- credential_clear(&c);
+ if (credential_from_url_gently(c, url, 0) < 0)
3: daedaffe960 ! 3: 0535908dd7e credential: handle `credential.<partial-URL>.<key>` again
@@ Commit message
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
## credential.c ##
+@@ credential.c: 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)
+ {
@@ credential.c: static int credential_config_callback(const char *var, const char *value,
char *url = xmemdupz(key, dot - key);
int matched;
- credential_from_url(&want, url);
-+ if (credential_from_url_gently(&want, url, 1, 0) < 0) {
++ if (credential_from_potentially_partial_url(&want, url) < 0) {
+ warning(_("skipping credential lookup for key: %s"),
+ var);
+ credential_clear(&want);
@@ credential.c: static int credential_config_callback(const char *var, const char
matched = credential_match(&want, c);
credential_clear(&want);
+@@ credential.c: 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);
## t/t0300-credentials.sh ##
@@ t/t0300-credentials.sh: test_expect_success 'credential system refuses to work with missing protocol' '
@@ t/t0300-credentials.sh: test_expect_success 'credential system refuses to work w
+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 >input &&
++ test_write_lines url=https://user@example.com/repo.git >stdin &&
+ for partial in \
+ example.com \
+ user@example.com \
@@ t/t0300-credentials.sh: test_expect_success 'credential system refuses to work w
+ /repo.git
+ do
+ git -c credential.$partial.helper=yep \
-+ credential fill <input >output &&
-+ grep yep output ||
++ credential fill <stdin >stdout &&
++ grep yep stdout ||
+ return 1
+ done &&
+
@@ t/t0300-credentials.sh: test_expect_success 'credential system refuses to work w
+ /repo
+ do
+ git -c credential.$partial.helper=yep \
-+ credential fill <input >output &&
-+ ! grep yep output ||
++ 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 <input >output 2>error &&
-+ test_i18ngrep "skipping credential lookup for key" error
++ credential fill <stdin >stdout 2>stderr &&
++ test_i18ngrep "skipping credential lookup for key" stderr
+
+'
+
--
gitgitgadget
next prev parent reply other threads:[~2020-04-24 11:49 UTC|newest]
Thread overview: 48+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-04-22 20:51 [PATCH 0/3] credential: handle partial URLs in config settings again Johannes Schindelin via GitGitGadget
2020-04-22 20:51 ` [PATCH 1/3] credential: fix grammar Johannes Schindelin via GitGitGadget
2020-04-22 23:29 ` Jonathan Nieder
2020-04-22 20:51 ` [PATCH 2/3] credential: teach `credential_from_url()` a non-strict mode Johannes Schindelin via GitGitGadget
2020-04-22 22:29 ` Junio C Hamano
2020-04-22 22:50 ` Johannes Schindelin
2020-04-22 23:02 ` Junio C Hamano
2020-04-22 23:38 ` Jonathan Nieder
2020-04-23 0:02 ` Carlo Arenas
2020-04-23 13:28 ` Johannes Schindelin
2020-04-23 21:22 ` Carlo Marcelo Arenas Belón
2020-04-23 22:03 ` Johannes Schindelin
2020-04-23 22:11 ` Junio C Hamano
2020-04-23 22:16 ` Junio C Hamano
2020-04-23 23:22 ` Johannes Schindelin
2020-04-23 22:50 ` Johannes Schindelin
2020-04-22 20:51 ` [PATCH 3/3] credential: handle `credential.<partial-URL>.<key>` again Johannes Schindelin via GitGitGadget
2020-04-22 23:57 ` Jonathan Nieder
2020-04-23 23:19 ` Johannes Schindelin
2020-04-22 22:13 ` [PATCH 0/3] credential: handle partial URLs in config settings again Jeff King
2020-04-22 22:26 ` Johannes Schindelin
2020-04-22 22:47 ` Jonathan Nieder
2020-04-23 22:11 ` Johannes Schindelin
2020-04-23 23:43 ` [PATCH v2 " Johannes Schindelin via GitGitGadget
2020-04-23 23:43 ` [PATCH v2 1/3] credential: fix grammar Johannes Schindelin via GitGitGadget
2020-04-23 23:43 ` [PATCH v2 2/3] credential: optionally allow partial URLs in credential_from_url_gently() Johannes Schindelin via GitGitGadget
2020-04-23 23:43 ` [PATCH v2 3/3] credential: handle `credential.<partial-URL>.<key>` again Johannes Schindelin via GitGitGadget
2020-04-24 0:05 ` Carlo Marcelo Arenas Belón
2020-04-24 0:16 ` Johannes Schindelin
2020-04-24 0:39 ` Carlo Marcelo Arenas Belón
2020-04-24 11:34 ` Johannes Schindelin
2020-04-24 0:34 ` Junio C Hamano
2020-04-24 0:40 ` Junio C Hamano
2020-04-24 11:36 ` Johannes Schindelin
2020-04-24 0:49 ` [PATCH v2 0/3] credential: handle partial URLs in config settings again Carlo Marcelo Arenas Belón
2020-04-24 11:49 ` Johannes Schindelin via GitGitGadget [this message]
2020-04-24 11:49 ` [PATCH v3 1/3] credential: fix grammar Johannes Schindelin via GitGitGadget
2020-04-24 11:49 ` [PATCH v3 2/3] credential: optionally allow partial URLs in credential_from_url_gently() Johannes Schindelin via GitGitGadget
2020-04-24 11:49 ` [PATCH v3 3/3] credential: handle `credential.<partial-URL>.<key>` again Johannes Schindelin via GitGitGadget
2020-04-24 15:23 ` Carlo Marcelo Arenas Belón
2020-04-25 10:43 ` Johannes Schindelin
2020-04-24 22:20 ` Junio C Hamano
2020-04-24 22:29 ` Johannes Schindelin
2020-04-28 23:13 ` Junio C Hamano
2020-04-29 14:58 ` Johannes Schindelin
2020-04-29 15:36 ` Junio C Hamano
2020-05-01 19:58 ` Johannes Schindelin
2020-05-01 20:01 ` 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
List information: http://vger.kernel.org/majordomo-info.html
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=pull.615.v3.git.1587728992.gitgitgadget@gmail.com \
--to=gitgitgadget@gmail.com \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=it@it3xl.ru \
--cc=johannes.schindelin@gmx.de \
--cc=jrnieder@gmail.com \
--cc=peff@peff.net \
--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.
Code repositories for project(s) associated with this public inbox
https://80x24.org/mirrors/git.git
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 read-only IMAP folder(s) and NNTP newsgroup(s).