Commit e60db3c7 by Matt Burke

Revise custom header error messages

If the header doesn't look like a header (e.g. if it doesn't have a ":"
or if it has newlines), report "custom HTTP header '%s' is malformed".

If the header has the same name as a header already set by libgit2 (e.g.
"Host"), report "HTTP header '%s' is already set by libgit2".
parent 63cc5723
...@@ -66,6 +66,35 @@ static int git_smart__set_callbacks( ...@@ -66,6 +66,35 @@ static int git_smart__set_callbacks(
return 0; return 0;
} }
int http_header_name_length(const char *http_header)
{
const char *colon = strchr(http_header, ':');
if (!colon)
return 0;
return colon - http_header;
}
bool is_malformed_http_header(const char *http_header)
{
const char *c;
int name_len;
// Disallow \r and \n
c = strchr(http_header, '\r');
if (c)
return true;
c = strchr(http_header, '\n');
if (c)
return true;
// Require a header name followed by :
name_len = http_header_name_length(http_header);
if (name_len < 1)
return true;
return false;
}
static char *forbidden_custom_headers[] = { static char *forbidden_custom_headers[] = {
"User-Agent", "User-Agent",
"Host", "Host",
...@@ -75,48 +104,17 @@ static char *forbidden_custom_headers[] = { ...@@ -75,48 +104,17 @@ static char *forbidden_custom_headers[] = {
"Content-Length", "Content-Length",
}; };
bool is_valid_custom_header(const char *custom_header) bool is_forbidden_custom_header(const char *custom_header)
{ {
const char *c;
int name_len;
unsigned long i; unsigned long i;
int name_len = http_header_name_length(custom_header);
// 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 // Disallow headers that we set
for (i = 0; i < ARRAY_SIZE(forbidden_custom_headers); i++) for (i = 0; i < ARRAY_SIZE(forbidden_custom_headers); i++)
if (strncmp(forbidden_custom_headers[i], custom_header, name_len) == 0) if (strncmp(forbidden_custom_headers[i], custom_header, name_len) == 0)
return false;
return true; return true;
}
const char *find_invalid_custom_header(const git_strarray *custom_headers) return false;
{
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_header(custom_headers->strings[i]))
return custom_headers->strings[i];
return NULL;
} }
static int git_smart__set_custom_headers( static int git_smart__set_custom_headers(
...@@ -124,12 +122,18 @@ static int git_smart__set_custom_headers( ...@@ -124,12 +122,18 @@ static int git_smart__set_custom_headers(
const git_strarray *custom_headers) const git_strarray *custom_headers)
{ {
transport_smart *t = (transport_smart *)transport; transport_smart *t = (transport_smart *)transport;
const char *invalid_header = find_invalid_custom_header(custom_headers); size_t i;
if (invalid_header != NULL) { for (i = 0; i < custom_headers->count; i++) {
giterr_set(GITERR_INVALID, "Illegal HTTP header '%s'", invalid_header); if (is_malformed_http_header(custom_headers->strings[i])) {
giterr_set(GITERR_INVALID, "custom HTTP header '%s' is malformed", custom_headers->strings[i]);
return -1; return -1;
} }
if (is_forbidden_custom_header(custom_headers->strings[i])) {
giterr_set(GITERR_INVALID, "custom HTTP header '%s' is already set by libgit2", custom_headers->strings[i]);
return -1;
}
}
t->custom_headers = custom_headers; t->custom_headers = custom_headers;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment