diff options
author | Junio C Hamano <gitster@pobox.com> | 2015-03-03 14:37:05 -0800 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2015-03-03 14:37:06 -0800 |
commit | 4c3dbbf7225c45ab0e04953090d0ece4a15e83a2 (patch) | |
tree | 68820f614f5c4f3b735c2eb6dd13c1e12208a6ae /daemon.c | |
parent | ef4cdb8bb7c56a431f2f553ed39b896f32488a18 (diff) | |
parent | b48537305229d1a4f25633f71941ee52d2582017 (diff) | |
download | git-4c3dbbf7225c45ab0e04953090d0ece4a15e83a2.tar.gz |
Merge branch 'jk/daemon-interpolate'
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.c | 50 |
1 files changed, 45 insertions, 5 deletions
@@ -537,6 +537,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) @@ -557,10 +596,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); hostname_lookup_done = 0; } @@ -597,8 +636,9 @@ static void lookup_hostname(void) 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); } @@ -620,7 +660,7 @@ static void lookup_hostname(void) 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); } |