ui-shared: prevent malicious filename from injecting headers

This commit is contained in:
Jason A. Donenfeld 2016-01-14 14:28:37 +01:00
parent 4291453ec3
commit 513b3863d9
3 changed files with 32 additions and 3 deletions

26
html.c
View File

@ -239,6 +239,32 @@ void html_url_arg(const char *txt)
html(txt); html(txt);
} }
void html_header_arg_in_quotes(const char *txt)
{
const char *t = txt;
while (t && *t) {
unsigned char c = *t;
const char *e = NULL;
if (c == '\\')
e = "\\\\";
else if (c == '\r')
e = "\\r";
else if (c == '\n')
e = "\\n";
else if (c == '"')
e = "\\\"";
if (e) {
html_raw(txt, t - txt);
html(e);
txt = t + 1;
}
t++;
}
if (t != txt)
html(txt);
}
void html_hidden(const char *name, const char *value) void html_hidden(const char *name, const char *value)
{ {
html("<input type='hidden' name='"); html("<input type='hidden' name='");

1
html.h
View File

@ -23,6 +23,7 @@ extern void html_ntxt(int len, const char *txt);
extern void html_attr(const char *txt); extern void html_attr(const char *txt);
extern void html_url_path(const char *txt); extern void html_url_path(const char *txt);
extern void html_url_arg(const char *txt); extern void html_url_arg(const char *txt);
extern void html_header_arg_in_quotes(const char *txt);
extern void html_hidden(const char *name, const char *value); extern void html_hidden(const char *name, const char *value);
extern void html_option(const char *value, const char *text, const char *selected_value); extern void html_option(const char *value, const char *text, const char *selected_value);
extern void html_intoption(int value, const char *text, int selected_value); extern void html_intoption(int value, const char *text, int selected_value);

View File

@ -692,9 +692,11 @@ void cgit_print_http_headers(void)
htmlf("Content-Type: %s\n", ctx.page.mimetype); htmlf("Content-Type: %s\n", ctx.page.mimetype);
if (ctx.page.size) if (ctx.page.size)
htmlf("Content-Length: %zd\n", ctx.page.size); htmlf("Content-Length: %zd\n", ctx.page.size);
if (ctx.page.filename) if (ctx.page.filename) {
htmlf("Content-Disposition: inline; filename=\"%s\"\n", html("Content-Disposition: inline; filename=\"");
ctx.page.filename); html_header_arg_in_quotes(ctx.page.filename);
html("\"\n");
}
if (!ctx.env.authenticated) if (!ctx.env.authenticated)
html("Cache-Control: no-cache, no-store\n"); html("Cache-Control: no-cache, no-store\n");
htmlf("Last-Modified: %s\n", http_date(ctx.page.modified)); htmlf("Last-Modified: %s\n", http_date(ctx.page.modified));