aboutsummaryrefslogtreecommitdiffstats
path: root/plugins/mod_http_files.lua
diff options
context:
space:
mode:
authorKim Alvefur <zash@zash.se>2016-01-08 16:16:08 +0100
committerKim Alvefur <zash@zash.se>2016-01-08 16:16:08 +0100
commit6b1e54864c661211366d22a41435e5e3d07e71ac (patch)
treefa735fdc4d7fd7f7b8f14ea5dc1e5a86a0ca5dde /plugins/mod_http_files.lua
parent7baeaaa363aca2190c22f1bd4463ac52ab83bb99 (diff)
parentf9a3ca3602c72f24edecc95a886eace4edd42c5d (diff)
downloadprosody-6b1e54864c661211366d22a41435e5e3d07e71ac.tar.gz
prosody-6b1e54864c661211366d22a41435e5e3d07e71ac.zip
Merge 0.9->0.10
Diffstat (limited to 'plugins/mod_http_files.lua')
-rw-r--r--plugins/mod_http_files.lua34
1 files changed, 33 insertions, 1 deletions
diff --git a/plugins/mod_http_files.lua b/plugins/mod_http_files.lua
index 7c503c82..0c542714 100644
--- a/plugins/mod_http_files.lua
+++ b/plugins/mod_http_files.lua
@@ -49,6 +49,34 @@ if not mime_map then
end
end
+local forbidden_chars_pattern = "[/%z]";
+if prosody.platform == "windows" then
+ forbidden_chars_pattern = "[/%z\001-\031\127\"*:<>?|]"
+end
+
+local urldecode = require "util.http".urldecode;
+function sanitize_path(path)
+ local out = {};
+
+ local c = 0;
+ for component in path:gmatch("([^/]+)") do
+ component = urldecode(component);
+ if component:find(forbidden_chars_pattern) then
+ return nil;
+ elseif component == ".." then
+ if c <= 0 then
+ return nil;
+ end
+ out[c] = nil;
+ c = c - 1;
+ elseif component ~= "." then
+ c = c + 1;
+ out[c] = component;
+ end
+ end
+ return "/"..table.concat(out, "/");
+end
+
local cache = setmetatable({}, { __mode = "kv" }); -- Let the garbage collector have it if it wants to.
function serve(opts)
@@ -60,7 +88,11 @@ function serve(opts)
local directory_index = opts.directory_index;
local function serve_file(event, path)
local request, response = event.request, event.response;
- local orig_path = request.path;
+ path = sanitize_path(path);
+ if not path then
+ return 400;
+ end
+ local orig_path = sanitize_path(request.path);
local full_path = base_path .. (path and "/"..path or ""):gsub("/", path_sep);
local attr = stat(full_path:match("^.*[^\\/]")); -- Strip trailing path separator because Windows
if not attr then