aboutsummaryrefslogtreecommitdiffstats
path: root/promisor-remote.c
diff options
authorChristian Couder <christian.couder@gmail.com>2025-02-18 12:32:03 +0100
committerJunio C Hamano <gitster@pobox.com>2025-02-18 11:05:37 -0800
commit36463e32dfef16dc3a903763f14f5bbf6e0248e7 (patch)
tree65e053ffc7bc35376aeba7651c15f1f7d20fb6f1 /promisor-remote.c
parentd460267613da14eba959eb225e2cbf6a1e132eb1 (diff)
downloadgit-36463e32dfef16dc3a903763f14f5bbf6e0248e7.tar.gz
promisor-remote: check advertised name or URL
A previous commit introduced a "promisor.acceptFromServer" configuration variable with only "None" or "All" as valid values. Let's introduce "KnownName" and "KnownUrl" as valid values for this configuration option to give more choice to a client about which promisor remotes it might accept among those that the server advertised. In case of "KnownName", the client will accept promisor remotes which are already configured on the client and have the same name as those advertised by the client. This could be useful in a corporate setup where servers and clients are trusted to not switch names and URLs, but where some kind of control is still useful. In case of "KnownUrl", the client will accept promisor remotes which have both the same name and the same URL configured on the client as the name and URL advertised by the server. This is the most secure option, so it should be used if possible. Signed-off-by: Christian Couder <chriscool@tuxfamily.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'promisor-remote.c')
-rw-r--r--promisor-remote.c60
1 files changed, 54 insertions, 6 deletions
diff --git a/promisor-remote.c b/promisor-remote.c
index 918be6528f..6a0a61382f 100644
--- a/promisor-remote.c
+++ b/promisor-remote.c
@@ -368,30 +368,73 @@ char *promisor_remote_info(struct repository *repo)
return strbuf_detach(&sb, NULL);
}
+/*
+ * Find first index of 'nicks' where there is 'nick'. 'nick' is
+ * compared case insensitively to the strings in 'nicks'. If not found
+ * 'nicks->nr' is returned.
+ */
+static size_t remote_nick_find(struct strvec *nicks, const char *nick)
+{
+ for (size_t i = 0; i < nicks->nr; i++)
+ if (!strcasecmp(nicks->v[i], nick))
+ return i;
+ return nicks->nr;
+}
+
enum accept_promisor {
ACCEPT_NONE = 0,
+ ACCEPT_KNOWN_URL,
+ ACCEPT_KNOWN_NAME,
ACCEPT_ALL
};
static int should_accept_remote(enum accept_promisor accept,
- const char *remote_name UNUSED,
- const char *remote_url UNUSED)
+ const char *remote_name, const char *remote_url,
+ struct strvec *names, struct strvec *urls)
{
+ size_t i;
+
if (accept == ACCEPT_ALL)
return 1;
- BUG("Unhandled 'enum accept_promisor' value '%d'", accept);
+ i = remote_nick_find(names, remote_name);
+
+ if (i >= names->nr)
+ /* We don't know about that remote */
+ return 0;
+
+ if (accept == ACCEPT_KNOWN_NAME)
+ return 1;
+
+ if (accept != ACCEPT_KNOWN_URL)
+ BUG("Unhandled 'enum accept_promisor' value '%d'", accept);
+
+ if (!strcmp(urls->v[i], remote_url))
+ return 1;
+
+ warning(_("known remote named '%s' but with url '%s' instead of '%s'"),
+ remote_name, urls->v[i], remote_url);
+
+ return 0;
}
-static void filter_promisor_remote(struct strvec *accepted, const char *info)
+static void filter_promisor_remote(struct repository *repo,
+ struct strvec *accepted,
+ const char *info)
{
struct strbuf **remotes;
const char *accept_str;
enum accept_promisor accept = ACCEPT_NONE;
+ struct strvec names = STRVEC_INIT;
+ struct strvec urls = STRVEC_INIT;
if (!git_config_get_string_tmp("promisor.acceptfromserver", &accept_str)) {
if (!*accept_str || !strcasecmp("None", accept_str))
accept = ACCEPT_NONE;
+ else if (!strcasecmp("KnownUrl", accept_str))
+ accept = ACCEPT_KNOWN_URL;
+ else if (!strcasecmp("KnownName", accept_str))
+ accept = ACCEPT_KNOWN_NAME;
else if (!strcasecmp("All", accept_str))
accept = ACCEPT_ALL;
else
@@ -402,6 +445,9 @@ static void filter_promisor_remote(struct strvec *accepted, const char *info)
if (accept == ACCEPT_NONE)
return;
+ if (accept != ACCEPT_ALL)
+ promisor_info_vecs(repo, &names, &urls);
+
/* Parse remote info received */
remotes = strbuf_split_str(info, ';', 0);
@@ -431,7 +477,7 @@ static void filter_promisor_remote(struct strvec *accepted, const char *info)
if (remote_url)
decoded_url = url_percent_decode(remote_url);
- if (decoded_name && should_accept_remote(accept, decoded_name, decoded_url))
+ if (decoded_name && should_accept_remote(accept, decoded_name, decoded_url, &names, &urls))
strvec_push(accepted, decoded_name);
strbuf_list_free(elems);
@@ -439,6 +485,8 @@ static void filter_promisor_remote(struct strvec *accepted, const char *info)
free(decoded_url);
}
+ strvec_clear(&names);
+ strvec_clear(&urls);
strbuf_list_free(remotes);
}
@@ -447,7 +495,7 @@ char *promisor_remote_reply(const char *info)
struct strvec accepted = STRVEC_INIT;
struct strbuf reply = STRBUF_INIT;
- filter_promisor_remote(&accepted, info);
+ filter_promisor_remote(the_repository, &accepted, info);
if (!accepted.nr)
return NULL;