summaryrefslogtreecommitdiff
path: root/usr.sbin
diff options
context:
space:
mode:
authorFlorian Obser <florian@cvs.openbsd.org>2015-02-10 08:12:30 +0000
committerFlorian Obser <florian@cvs.openbsd.org>2015-02-10 08:12:30 +0000
commitf5ccda6996b82c0129c5eb8249f0efbb75ff8b5a (patch)
treef1f0a4f6a235912576ac456ddbdf5f2e452af536 /usr.sbin
parentb5c2159defa1cc30b5386914331a73ed5e49c874 (diff)
Encode directory listings.
Problem pointed out by remco AT d-compu.dyndns.org some time ago. Input / OK reyk@
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/httpd/httpd.c58
-rw-r--r--usr.sbin/httpd/httpd.h4
-rw-r--r--usr.sbin/httpd/server_file.c21
3 files changed, 77 insertions, 6 deletions
diff --git a/usr.sbin/httpd/httpd.c b/usr.sbin/httpd/httpd.c
index f640dc2bfbd..273e0f9c9fb 100644
--- a/usr.sbin/httpd/httpd.c
+++ b/usr.sbin/httpd/httpd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: httpd.c,v 1.32 2015/02/08 00:00:59 reyk Exp $ */
+/* $OpenBSD: httpd.c,v 1.33 2015/02/10 08:12:29 florian Exp $ */
/*
* Copyright (c) 2014 Reyk Floeter <reyk@openbsd.org>
@@ -671,6 +671,62 @@ path_info(char *path)
return (p - start);
}
+char*
+escape_uri(const char *src)
+{
+ static char hex[] = "0123456789ABCDEF";
+ char *dp, *dst;
+ unsigned char c;
+
+ /* We need 3 times the memory if every letter is encoded. */
+ if ((dst = calloc(3, strlen(src) + 1)) == NULL)
+ return NULL;
+
+ for (dp = dst; *src != 0; src++) {
+ c = (unsigned char) *src;
+ if (c == ' ' || c == '#' || c == '%' || c == '?' || c == '"' ||
+ c == '&' || c == '<' || c <= 0x1f || c >= 0x7f) {
+ *dp++ = '%';
+ *dp++ = hex[c >> 4];
+ *dp++ = hex[c & 0x0f];
+ } else
+ *dp++ = *src;
+ }
+ return (dst);
+}
+
+char*
+escape_html(const char* src)
+{
+ char *dp, *dst;
+
+ /* We need 5 times the memory if every letter is "<" or ">". */
+ if ((dst = calloc(5, strlen(src) + 1)) == NULL)
+ return NULL;
+
+ for (dp = dst; *src != 0; src++) {
+ if (*src == '<') {
+ *dp++ = '&';
+ *dp++ = 'l';
+ *dp++ = 't';
+ *dp++ = ';';
+ } else if (*src == '>') {
+ *dp++ = '&';
+ *dp++ = 'g';
+ *dp++ = 't';
+ *dp++ = ';';
+ } else if (*src == '&') {
+ *dp++ = '&';
+ *dp++ = 'a';
+ *dp++ = 'm';
+ *dp++ = 'p';
+ *dp++ = ';';
+ } else
+ *dp++ = *src;
+ }
+ return (dst);
+}
+
void
socket_rlimit(int maxfd)
{
diff --git a/usr.sbin/httpd/httpd.h b/usr.sbin/httpd/httpd.h
index 98096c9ac39..625c81077a9 100644
--- a/usr.sbin/httpd/httpd.h
+++ b/usr.sbin/httpd/httpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: httpd.h,v 1.77 2015/02/07 23:56:02 reyk Exp $ */
+/* $OpenBSD: httpd.h,v 1.78 2015/02/10 08:12:29 florian Exp $ */
/*
* Copyright (c) 2006 - 2015 Reyk Floeter <reyk@openbsd.org>
@@ -587,6 +587,8 @@ const char *url_decode(char *);
const char *canonicalize_host(const char *, char *, size_t);
const char *canonicalize_path(const char *, char *, size_t);
size_t path_info(char *);
+char *escape_uri(const char *);
+char *escape_html(const char *);
void imsg_event_add(struct imsgev *);
int imsg_compose_event(struct imsgev *, u_int16_t, u_int32_t,
pid_t, int, void *, u_int16_t);
diff --git a/usr.sbin/httpd/server_file.c b/usr.sbin/httpd/server_file.c
index b24f0c07e99..199bf07c3a4 100644
--- a/usr.sbin/httpd/server_file.c
+++ b/usr.sbin/httpd/server_file.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: server_file.c,v 1.49 2015/02/08 00:00:59 reyk Exp $ */
+/* $OpenBSD: server_file.c,v 1.50 2015/02/10 08:12:29 florian Exp $ */
/*
* Copyright (c) 2006 - 2015 Reyk Floeter <reyk@openbsd.org>
@@ -274,6 +274,7 @@ server_file_index(struct httpd *env, struct client *clt, struct stat *st)
struct evbuffer *evb = NULL;
struct media_type *media;
const char *stripped, *style;
+ char *escapeduri, *escapedhtml, *escapedpath;
struct tm tm;
time_t t, dir_mtime;
@@ -304,6 +305,9 @@ server_file_index(struct httpd *env, struct client *clt, struct stat *st)
/* Indicate failure but continue going through the list */
skip = 0;
+ if ((escapedpath = escape_html(desc->http_path)) == NULL)
+ goto fail;
+
/* A CSS stylesheet allows minimal customization by the user */
style = "body { background-color: white; color: black; font-family: "
"sans-serif; }\nhr { border: 0; border-bottom: 1px dashed; }\n";
@@ -318,9 +322,11 @@ server_file_index(struct httpd *env, struct client *clt, struct stat *st)
"<body>\n"
"<h1>Index of %s</h1>\n"
"<hr>\n<pre>\n",
- desc->http_path, style, desc->http_path) == -1)
+ escapedpath, style, escapedpath) == -1)
skip = 1;
+ free(escapedpath);
+
for (i = 0; i < namesize; i++) {
dp = namelist[i];
@@ -335,6 +341,11 @@ server_file_index(struct httpd *env, struct client *clt, struct stat *st)
strftime(tmstr, sizeof(tmstr), "%d-%h-%Y %R", &tm);
namewidth = 51 - strlen(dp->d_name);
+ if ((escapeduri = escape_uri(dp->d_name)) == NULL)
+ goto fail;
+ if ((escapedhtml = escape_html(dp->d_name)) == NULL)
+ goto fail;
+
if (dp->d_name[0] == '.' &&
!(dp->d_name[1] == '.' && dp->d_name[2] == '\0')) {
/* ignore hidden files starting with a dot */
@@ -342,17 +353,19 @@ server_file_index(struct httpd *env, struct client *clt, struct stat *st)
namewidth -= 1; /* trailing slash */
if (evbuffer_add_printf(evb,
"<a href=\"%s\">%s/</a>%*s%s%20s\n",
- dp->d_name, dp->d_name,
+ escapeduri, escapedhtml,
MAXIMUM(namewidth, 0), " ", tmstr, "-") == -1)
skip = 1;
} else if (S_ISREG(st->st_mode)) {
if (evbuffer_add_printf(evb,
"<a href=\"%s\">%s</a>%*s%s%20llu\n",
- dp->d_name, dp->d_name,
+ escapeduri, escapedhtml,
MAXIMUM(namewidth, 0), " ",
tmstr, st->st_size) == -1)
skip = 1;
}
+ free(escapeduri);
+ free(escapedhtml);
free(dp);
}
free(namelist);