diff options
author | Junio C Hamano <gitster@pobox.com> | 2015-03-13 22:55:59 -0700 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2015-03-13 22:55:59 -0700 |
commit | c722ba4814f34d02faed305e4cc6498c783543a9 (patch) | |
tree | cdf6603541229f3878ac3a8b70e88bf34f5aba69 /daemon.c | |
parent | 1165ae6f3d42e0eb0ddfc2d4e6dfa8bd0b88eb60 (diff) | |
parent | b48537305229d1a4f25633f71941ee52d2582017 (diff) | |
download | git-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.c | 50 |
1 files changed, 45 insertions, 5 deletions
@@ -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); } |