aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason A. Donenfeld2016-01-14 14:28:37 +0100
committerJason A. Donenfeld2016-01-14 14:28:37 +0100
commit513b3863d999f91b47d7e9f26710390db55f9463 (patch)
treef704af1ea3f8da9b3b2904fbe8ed8233278314c6
parent4291453ec30656c2f59645d8a74cf295ce0253a9 (diff)
downloadcgit-513b3863d999f91b47d7e9f26710390db55f9463.tar.gz
cgit-513b3863d999f91b47d7e9f26710390db55f9463.tar.bz2
cgit-513b3863d999f91b47d7e9f26710390db55f9463.zip
ui-shared: prevent malicious filename from injecting headers
-rw-r--r--html.c26
-rw-r--r--html.h1
-rw-r--r--ui-shared.c8
3 files changed, 32 insertions, 3 deletions
diff --git a/html.c b/html.c
index 959148c..d89df3a 100644
--- a/html.c
+++ b/html.c
@@ -239,6 +239,32 @@ void html_url_arg(const char *txt)
239 html(txt); 239 html(txt);
240} 240}
241 241
242void html_header_arg_in_quotes(const char *txt)
243{
244 const char *t = txt;
245 while (t && *t) {
246 unsigned char c = *t;
247 const char *e = NULL;
248 if (c == '\\')
249 e = "\\\\";
250 else if (c == '\r')
251 e = "\\r";
252 else if (c == '\n')
253 e = "\\n";
254 else if (c == '"')
255 e = "\\\"";
256 if (e) {
257 html_raw(txt, t - txt);
258 html(e);
259 txt = t + 1;
260 }
261 t++;
262 }
263 if (t != txt)
264 html(txt);
265
266}
267
242void html_hidden(const char *name, const char *value) 268void html_hidden(const char *name, const char *value)
243{ 269{
244 html("<input type='hidden' name='"); 270 html("<input type='hidden' name='");
diff --git a/html.h b/html.h
index c554763..c72e845 100644
--- a/html.h
+++ b/html.h
@@ -23,6 +23,7 @@ extern void html_ntxt(int len, const char *txt);
23extern void html_attr(const char *txt); 23extern void html_attr(const char *txt);
24extern void html_url_path(const char *txt); 24extern void html_url_path(const char *txt);
25extern void html_url_arg(const char *txt); 25extern void html_url_arg(const char *txt);
26extern void html_header_arg_in_quotes(const char *txt);
26extern void html_hidden(const char *name, const char *value); 27extern void html_hidden(const char *name, const char *value);
27extern void html_option(const char *value, const char *text, const char *selected_value); 28extern void html_option(const char *value, const char *text, const char *selected_value);
28extern void html_intoption(int value, const char *text, int selected_value); 29extern void html_intoption(int value, const char *text, int selected_value);
diff --git a/ui-shared.c b/ui-shared.c
index 21f581f..54bbde7 100644
--- a/ui-shared.c
+++ b/ui-shared.c
@@ -692,9 +692,11 @@ void cgit_print_http_headers(void)
692 htmlf("Content-Type: %s\n", ctx.page.mimetype); 692 htmlf("Content-Type: %s\n", ctx.page.mimetype);
693 if (ctx.page.size) 693 if (ctx.page.size)
694 htmlf("Content-Length: %zd\n", ctx.page.size); 694 htmlf("Content-Length: %zd\n", ctx.page.size);
695 if (ctx.page.filename) 695 if (ctx.page.filename) {
696 htmlf("Content-Disposition: inline; filename=\"%s\"\n", 696 html("Content-Disposition: inline; filename=\"");
697 ctx.page.filename); 697 html_header_arg_in_quotes(ctx.page.filename);
698 html("\"\n");
699 }
698 if (!ctx.env.authenticated) 700 if (!ctx.env.authenticated)
699 html("Cache-Control: no-cache, no-store\n"); 701 html("Cache-Control: no-cache, no-store\n");
700 htmlf("Last-Modified: %s\n", http_date(ctx.page.modified)); 702 htmlf("Last-Modified: %s\n", http_date(ctx.page.modified));