@@ -886,12 +886,15 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
int err = 0, complete_refs_before_fetch = 1;
int submodule_progress;
int filter_submodules = 0;
-
+ enum credentials_in_url cred_in_url_cfg = get_credentials_in_url();
struct transport_ls_refs_options transport_ls_refs_options =
TRANSPORT_LS_REFS_OPTIONS_INIT;
packet_trace_identity("clone");
+ if (cred_in_url_cfg == CRED_IN_URL_WARN)
+ git_config_push_parameter("transfer.credentialsInUrl=allow");
+
git_config(git_clone_config, NULL);
argc = parse_options(argc, argv, prefix, builtin_clone_options,
@@ -2101,9 +2101,13 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
struct remote *remote = NULL;
int result = 0;
int prune_tags_ok = 1;
+ enum credentials_in_url cred_in_url_cfg = get_credentials_in_url();
packet_trace_identity("fetch");
+ if (cred_in_url_cfg == CRED_IN_URL_WARN)
+ git_config_push_parameter("transfer.credentialsInUrl=allow");
+
/* Record the command line for the reflog */
strbuf_addstr(&default_rla, "fetch");
for (i = 1; i < argc; i++) {
@@ -576,7 +576,7 @@ int cmd_push(int argc, const char **argv, const char *prefix)
struct string_list *push_options;
const struct string_list_item *item;
struct remote *remote;
-
+ enum credentials_in_url cred_in_url_cfg = get_credentials_in_url();
struct option options[] = {
OPT__VERBOSITY(&verbosity),
OPT_STRING( 0 , "repo", &repo, N_("repository"), N_("repository")),
@@ -619,6 +619,10 @@ int cmd_push(int argc, const char **argv, const char *prefix)
};
packet_trace_identity("push");
+
+ if (cred_in_url_cfg == CRED_IN_URL_WARN)
+ git_config_push_parameter("transfer.credentialsInUrl=allow");
+
git_config(git_push_config, &flags);
argc = parse_options(argc, argv, prefix, options, push_usage, 0);
push_options = (push_options_cmdline.nr
@@ -616,25 +616,43 @@ const char *remote_ref_for_branch(struct branch *branch, int for_push)
return NULL;
}
-static void validate_remote_url(struct remote *remote)
+static enum credentials_in_url cred_in_url = CRED_IN_URL_UNKNOWN;
+enum credentials_in_url get_credentials_in_url(void)
{
- int i;
+ enum credentials_in_url new = CRED_IN_URL_ALLOW;
const char *value;
- struct strbuf redacted = STRBUF_INIT;
- int warn_not_die;
+
+ if (cred_in_url != CRED_IN_URL_UNKNOWN)
+ return cred_in_url;
if (git_config_get_string_tmp("transfer.credentialsinurl", &value))
- return;
+ goto done;
if (!strcmp("warn", value))
- warn_not_die = 1;
+ new = CRED_IN_URL_WARN;
else if (!strcmp("die", value))
- warn_not_die = 0;
+ new = CRED_IN_URL_DIE;
else if (!strcmp("allow", value))
- return;
+ goto done;
else
die(_("unrecognized value transfer.credentialsInURL: '%s'"), value);
+done:
+ cred_in_url = new;
+ return cred_in_url;
+}
+
+static void validate_remote_url(struct remote *remote)
+{
+ int i;
+ struct strbuf redacted = STRBUF_INIT;
+ enum credentials_in_url cfg = get_credentials_in_url();
+
+ if (remote->validated_urls)
+ goto done;
+ if (cfg == CRED_IN_URL_ALLOW)
+ goto done;
+
for (i = 0; i < remote->url_nr; i++) {
struct url_info url_info = { 0 };
@@ -648,16 +666,25 @@ static void validate_remote_url(struct remote *remote)
strbuf_addstr(&redacted,
url_info.url + url_info.passwd_off + url_info.passwd_len);
- if (warn_not_die)
+ switch (cfg) {
+ case CRED_IN_URL_WARN:
warning(_("URL '%s' uses plaintext credentials"), redacted.buf);
- else
+ break;
+ case CRED_IN_URL_DIE:
die(_("URL '%s' uses plaintext credentials"), redacted.buf);
-
-loop_cleanup:
+ break;
+ case CRED_IN_URL_ALLOW:
+ case CRED_IN_URL_UNKNOWN:
+ BUG("unreachable");
+ break;
+ }
+ loop_cleanup:
free(url_info.url);
}
strbuf_release(&redacted);
+done:
+ remote->validated_urls = 1;
}
static struct remote *
@@ -98,6 +98,8 @@ struct remote {
int prune;
int prune_tags;
+ int validated_urls;
+
/**
* The configured helper programs to run on the remote side, for
* Git-native protocols.
@@ -441,4 +443,16 @@ void apply_push_cas(struct push_cas_option *, struct remote *, struct ref *);
char *relative_url(const char *remote_url, const char *url,
const char *up_path);
+enum credentials_in_url {
+ CRED_IN_URL_UNKNOWN,
+ CRED_IN_URL_ALLOW,
+ CRED_IN_URL_WARN,
+ CRED_IN_URL_DIE,
+};
+
+/**
+ * Get the transfer.credentialsInUrl config setting as an "enum
+ * credentials_in_url".
+ */
+enum credentials_in_url get_credentials_in_url(void);
#endif
@@ -1841,7 +1841,7 @@ test_expect_success 'fetch warns or fails when using username:password' '
test_must_fail git -c transfer.credentialsInUrl=warn fetch https://username:password@localhost 2>err &&
grep "warning: $message" err >warnings &&
- test_line_count = 3 warnings &&
+ test_line_count = 1 warnings &&
test_must_fail git -c transfer.credentialsInUrl=die fetch https://username:password@localhost 2>err &&
grep "fatal: $message" err >warnings &&
@@ -1864,7 +1864,7 @@ test_expect_success CURL 'fetch warns or fails when using username:password in c
test_must_fail git -C repo -c transfer.credentialsInUrl=warn fetch pwd-url 2>err &&
grep "warning: $message" err >warnings &&
- test_line_count = 3 warnings &&
+ test_line_count = 1 warnings &&
git -C repo remote set-url --push pwd-url https://username:password@localhost &&
git -C repo remote set-url pwd-url https://localhost &&
@@ -1899,7 +1899,7 @@ test_expect_success CURL 'push warns or fails when using username:password in co
test_must_fail git -C repo -c transfer.credentialsInUrl=warn push pwd-url HEAD:refs/heads/branch 2>err &&
grep "warning: $message" err >warnings &&
- test_line_count = 2 warnings &&
+ test_line_count = 1 warnings &&
git -C repo remote set-url --push pwd-url https://username:password@localhost &&
git -C repo remote set-url pwd-url https://localhost &&
@@ -78,7 +78,7 @@ test_expect_success 'clone warns or fails when using username:password' '
test_must_fail git -c transfer.credentialsInUrl=warn clone https://username:password@localhost attempt2 2>err &&
grep "warning: $message" err >warnings &&
- test_line_count = 2 warnings &&
+ test_line_count = 1 warnings &&
test_must_fail git -c transfer.credentialsInUrl=die clone https://username:password@localhost attempt3 2>err &&
grep "fatal: $message" err >warnings &&
Improve on 6dcbdc0d661 (remote: create fetch.credentialsInUrl config, 2022-06-06) by fixing the cases where we emit duplicate warnings, which were: * In the same process, as we'd get the same "struct remote *" again. We could probably save ourselves more work in those scenarios, but adding a flag to the "struct remote" indicating that we've validated the URLs will fix those issues. * When we invoke e.g. "git-remote-https" (aka. "git-remote-curl") from "git fetch". For those cases let's pass down the equivalent of a "-c transfer.credentialsInUrl=allow", since we know that we've already inspected our remotes in the parent process. See 7390f05a3c6 (fetch: after refetch, encourage auto gc repacking, 2022-03-28) for prior use of git_config_push_parameter() for this purpose, i.e. to push config parameters before invoking a sub-process. Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com> --- builtin/clone.c | 5 ++++- builtin/fetch.c | 4 ++++ builtin/push.c | 6 ++++- remote.c | 51 +++++++++++++++++++++++++++++++++---------- remote.h | 14 ++++++++++++ t/t5516-fetch-push.sh | 6 ++--- t/t5601-clone.sh | 2 +- 7 files changed, 70 insertions(+), 18 deletions(-)