|
|
2806c5 |
diff --git a/cache.h b/cache.h
|
|
|
2806c5 |
index 94ca1ac..2ab9ffd 100644
|
|
|
2806c5 |
--- a/cache.h
|
|
|
2806c5 |
+++ b/cache.h
|
|
|
2806c5 |
@@ -744,6 +744,14 @@ char *strip_path_suffix(const char *path, const char *suffix);
|
|
|
2806c5 |
int daemon_avoid_alias(const char *path);
|
|
|
2806c5 |
int offset_1st_component(const char *path);
|
|
|
2806c5 |
|
|
|
2806c5 |
+/*
|
|
|
2806c5 |
+ * Returns true iff "str" could be confused as a command-line option when
|
|
|
2806c5 |
+ * passed to a sub-program like "ssh". Note that this has nothing to do with
|
|
|
2806c5 |
+ * shell-quoting, which should be handled separately; we're assuming here that
|
|
|
2806c5 |
+ * the string makes it verbatim to the sub-program.
|
|
|
2806c5 |
+ */
|
|
|
2806c5 |
+int looks_like_command_line_option(const char *str);
|
|
|
2806c5 |
+
|
|
|
2806c5 |
/* object replacement */
|
|
|
2806c5 |
#define READ_SHA1_FILE_REPLACE 1
|
|
|
2806c5 |
extern void *read_sha1_file_extended(const unsigned char *sha1, enum object_type *type, unsigned long *size, unsigned flag);
|
|
|
2806c5 |
diff --git a/connect.c b/connect.c
|
|
|
2806c5 |
index 6d4ea13..970f565 100644
|
|
|
2806c5 |
--- a/connect.c
|
|
|
2806c5 |
+++ b/connect.c
|
|
|
2806c5 |
@@ -450,6 +450,11 @@ static struct child_process *git_proxy_connect(int fd[2], char *host)
|
|
|
2806c5 |
|
|
|
2806c5 |
get_host_and_port(&host, &port);
|
|
|
2806c5 |
|
|
|
2806c5 |
+ if (looks_like_command_line_option(host))
|
|
|
2806c5 |
+ die("strange hostname '%s' blocked", host);
|
|
|
2806c5 |
+ if (looks_like_command_line_option(port))
|
|
|
2806c5 |
+ die("strange port '%s' blocked", port);
|
|
|
2806c5 |
+
|
|
|
2806c5 |
argv = xmalloc(sizeof(*argv) * 4);
|
|
|
2806c5 |
argv[0] = git_proxy_command;
|
|
|
2806c5 |
argv[1] = host;
|
|
|
2806c5 |
@@ -613,6 +618,10 @@ struct child_process *git_connect(int fd[2], const char *url_orig,
|
|
|
2806c5 |
|
|
|
2806c5 |
conn = xcalloc(1, sizeof(*conn));
|
|
|
2806c5 |
|
|
|
2806c5 |
+ if (looks_like_command_line_option(path))
|
|
|
2806c5 |
+ die("strange pathname '%s' blocked", path);
|
|
|
2806c5 |
+
|
|
|
2806c5 |
+
|
|
|
2806c5 |
strbuf_init(&cmd, MAX_CMD_LEN);
|
|
|
2806c5 |
strbuf_addstr(&cmd, prog);
|
|
|
2806c5 |
strbuf_addch(&cmd, ' ');
|
|
|
2806c5 |
@@ -626,6 +635,10 @@ struct child_process *git_connect(int fd[2], const char *url_orig,
|
|
|
2806c5 |
const char *ssh = getenv("GIT_SSH");
|
|
|
2806c5 |
int putty = ssh && strcasestr(ssh, "plink");
|
|
|
2806c5 |
transport_check_allowed("ssh");
|
|
|
2806c5 |
+ if (looks_like_command_line_option(host))
|
|
|
2806c5 |
+ die("strange hostname '%s' blocked", host);
|
|
|
2806c5 |
+
|
|
|
2806c5 |
+
|
|
|
2806c5 |
if (!ssh) ssh = "ssh";
|
|
|
2806c5 |
|
|
|
2806c5 |
*arg++ = ssh;
|
|
|
2806c5 |
diff --git a/path.c b/path.c
|
|
|
2806c5 |
index 04ff148..713d79b 100644
|
|
|
2806c5 |
--- a/path.c
|
|
|
2806c5 |
+++ b/path.c
|
|
|
2806c5 |
@@ -701,3 +701,9 @@ int offset_1st_component(const char *path)
|
|
|
2806c5 |
return 2 + is_dir_sep(path[2]);
|
|
|
2806c5 |
return is_dir_sep(path[0]);
|
|
|
2806c5 |
}
|
|
|
2806c5 |
+
|
|
|
2806c5 |
+int looks_like_command_line_option(const char *str)
|
|
|
2806c5 |
+{
|
|
|
2806c5 |
+ return str && str[0] == '-';
|
|
|
2806c5 |
+}
|
|
|
2806c5 |
+
|
|
|
2806c5 |
diff --git a/t/t5532-fetch-proxy.sh b/t/t5532-fetch-proxy.sh
|
|
|
2806c5 |
index 5531bd1..d3b2651 100755
|
|
|
2806c5 |
--- a/t/t5532-fetch-proxy.sh
|
|
|
2806c5 |
+++ b/t/t5532-fetch-proxy.sh
|
|
|
2806c5 |
@@ -40,4 +40,9 @@ test_expect_success 'fetch through proxy works' '
|
|
|
2806c5 |
test_cmp expect actual
|
|
|
2806c5 |
'
|
|
|
2806c5 |
|
|
|
2806c5 |
+test_expect_success 'funny hostnames are rejected before running proxy' '
|
|
|
2806c5 |
+ test_must_fail git fetch git://-remote/repo.git 2>stderr &&
|
|
|
2806c5 |
+ ! grep "proxying for" stderr
|
|
|
2806c5 |
+'
|
|
|
2806c5 |
+
|
|
|
2806c5 |
test_done
|