aboutsummaryrefslogtreecommitdiff
path: root/daemon.c
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2015-03-13 22:55:59 -0700
committerJunio C Hamano <gitster@pobox.com>2015-03-13 22:55:59 -0700
commitc722ba4814f34d02faed305e4cc6498c783543a9 (patch)
treecdf6603541229f3878ac3a8b70e88bf34f5aba69 /daemon.c
parent1165ae6f3d42e0eb0ddfc2d4e6dfa8bd0b88eb60 (diff)
parentb48537305229d1a4f25633f71941ee52d2582017 (diff)
downloadgit-c722ba4814f34d02faed305e4cc6498c783543a9.tar.gz
git-c722ba4814f34d02faed305e4cc6498c783543a9.tar.xz
Merge branch 'jk/daemon-interpolate' into maint
The "interpolated-path" option of "git daemon" inserted any string client declared on the "host=" capability request without checking. Sanitize and limit %H and %CH to a saner and a valid DNS name. * jk/daemon-interpolate: daemon: sanitize incoming virtual hostname t5570: test git-daemon's --interpolated-path option git_connect: let user override virtual-host we send to daemon
Diffstat (limited to 'daemon.c')
-rw-r--r--daemon.c50
1 files changed, 45 insertions, 5 deletions
diff --git a/daemon.c b/daemon.c
index 54a03bd52..26d5f326e 100644
--- a/daemon.c
+++ b/daemon.c
@@ -485,6 +485,45 @@ static void parse_host_and_port(char *hostport, char **host,
}
/*
+ * Sanitize a string from the client so that it's OK to be inserted into a
+ * filesystem path. Specifically, we disallow slashes, runs of "..", and
+ * trailing and leading dots, which means that the client cannot escape
+ * our base path via ".." traversal.
+ */
+static void sanitize_client_strbuf(struct strbuf *out, const char *in)
+{
+ for (; *in; in++) {
+ if (*in == '/')
+ continue;
+ if (*in == '.' && (!out->len || out->buf[out->len - 1] == '.'))
+ continue;
+ strbuf_addch(out, *in);
+ }
+
+ while (out->len && out->buf[out->len - 1] == '.')
+ strbuf_setlen(out, out->len - 1);
+}
+
+static char *sanitize_client(const char *in)
+{
+ struct strbuf out = STRBUF_INIT;
+ sanitize_client_strbuf(&out, in);
+ return strbuf_detach(&out, NULL);
+}
+
+/*
+ * Like sanitize_client, but we also perform any canonicalization
+ * to make life easier on the admin.
+ */
+static char *canonicalize_client(const char *in)
+{
+ struct strbuf out = STRBUF_INIT;
+ sanitize_client_strbuf(&out, in);
+ strbuf_tolower(&out);
+ return strbuf_detach(&out, NULL);
+}
+
+/*
* Read the host as supplied by the client connection.
*/
static void parse_host_arg(char *extra_args, int buflen)
@@ -505,10 +544,10 @@ static void parse_host_arg(char *extra_args, int buflen)
parse_host_and_port(val, &host, &port);
if (port) {
free(tcp_port);
- tcp_port = xstrdup(port);
+ tcp_port = sanitize_client(port);
}
free(hostname);
- hostname = xstrdup_tolower(host);
+ hostname = canonicalize_client(host);
}
/* On to the next one */
@@ -541,8 +580,9 @@ static void parse_host_arg(char *extra_args, int buflen)
ip_address = xstrdup(addrbuf);
free(canon_hostname);
- canon_hostname = xstrdup(ai->ai_canonname ?
- ai->ai_canonname : ip_address);
+ canon_hostname = ai->ai_canonname ?
+ sanitize_client(ai->ai_canonname) :
+ xstrdup(ip_address);
freeaddrinfo(ai);
}
@@ -564,7 +604,7 @@ static void parse_host_arg(char *extra_args, int buflen)
addrbuf, sizeof(addrbuf));
free(canon_hostname);
- canon_hostname = xstrdup(hent->h_name);
+ canon_hostname = sanitize_client(hent->h_name);
free(ip_address);
ip_address = xstrdup(addrbuf);
}