Commit 8c876fa91d0783bf4e1f0e624b2dfa86574de4e3

Matt Burke 2015-09-10T09:11:16

Validate custom http headers

diff --git a/src/transports/smart.c b/src/transports/smart.c
index 15f45e1..ee49729 100644
--- a/src/transports/smart.c
+++ b/src/transports/smart.c
@@ -66,11 +66,64 @@ static int git_smart__set_callbacks(
 	return 0;
 }
 
+bool is_valid(const char *custom_header)
+{
+	const char *c;
+	int name_len;
+
+	if (custom_header == NULL)
+		return true;
+
+	// Disallow \r and \n
+	c = strchr(custom_header, '\r');
+	if (c != NULL)
+		return false;
+	c = strchr(custom_header, '\n');
+	if (c != NULL)
+		return false;
+
+	// Require a header name followed by :
+	c = strchr(custom_header, ':');
+	if (c == NULL)
+		return false;
+	name_len = c - custom_header;
+	if (name_len < 1)
+		return false;
+
+	// Disallow headers that we set
+	return git__strncmp("User-Agent", custom_header, name_len) == 0 &&
+		git__strncmp("Host", custom_header, name_len) == 0 &&
+		git__strncmp("Accept", custom_header, name_len) == 0 &&
+		git__strncmp("Content-Type", custom_header, name_len) == 0 &&
+		git__strncmp("Transfer-Encoding", custom_header, name_len) == 0 &&
+		git__strncmp("Content-Length", custom_header, name_len) == 0;
+}
+
+const char *find_invalid_header(const git_strarray *custom_headers)
+{
+	size_t i;
+
+	if (custom_headers == NULL || custom_headers->count == 0)
+		return NULL;
+
+	for (i = 0; i < custom_headers->count; i++)
+		if (!is_valid(custom_headers->strings[i]))
+			return custom_headers->strings[i];
+
+	return NULL;
+}
+
 static int git_smart__set_custom_headers(
 	git_transport *transport,
 	const git_strarray *custom_headers)
 {
 	transport_smart *t = (transport_smart *)transport;
+	const char *invalid_header = find_invalid_header(custom_headers);
+
+	if (invalid_header != NULL) {
+		giterr_set(GITERR_INVALID, "Illegal HTTP header '%s'", invalid_header);
+		return -1;
+	}
 
 	t->custom_headers = custom_headers;