diff options
-rw-r--r-- | net/dns.lua | 6 | ||||
-rw-r--r-- | plugins/mod_http_files.lua | 34 | ||||
-rw-r--r-- | tests/test.lua | 7 | ||||
-rw-r--r-- | util/ip.lua | 6 | ||||
-rw-r--r-- | util/random.lua | 28 | ||||
-rw-r--r-- | util/uuid.lua | 2 |
6 files changed, 52 insertions, 31 deletions
diff --git a/net/dns.lua b/net/dns.lua index d893e38f..d711af34 100644 --- a/net/dns.lua +++ b/net/dns.lua @@ -591,7 +591,7 @@ function resolver:adddefaultnameservers() -- - - - - adddefaultnameservers if resolv_conf then for line in resolv_conf:lines() do line = line:gsub("#.*$", "") - :match('^%s*nameserver%s+([%x:%.]*)%s*$'); + :match('^%s*nameserver%s+([%x:%.]*%%?%S*)%s*$'); if line then local ip = new_ip(line); if ip then @@ -853,7 +853,9 @@ function resolver:receive(rset) -- - - - - - - - - - - - - - - - - receive --self.print(response); for j,rr in pairs(response.answer) do - self:remember(rr, response.question[1].type) + if rr.name:sub(-#response.question[1].name, -1) == response.question[1].name then + self:remember(rr, response.question[1].type) + end end -- retire the query 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 diff --git a/tests/test.lua b/tests/test.lua index 1666fcf5..1192b7b8 100644 --- a/tests/test.lua +++ b/tests/test.lua @@ -140,9 +140,12 @@ function dotest(unitname) end local oldmodule, old_M = _fakeG.module, _fakeG._M; - _fakeG.module = function () _M = unit end + _fakeG.module = function () + setmetatable(unit, nil); + unit._M = unit; + end setfenv(chunk, unit); - local success, ret = pcall(chunk); + local success, err = pcall(chunk); _fakeG.module, _fakeG._M = oldmodule, old_M; if not success then print("WARNING: ", "Failed to initialise module: "..unitname, err); diff --git a/util/ip.lua b/util/ip.lua index 7dcace5c..ec3b4d7e 100644 --- a/util/ip.lua +++ b/util/ip.lua @@ -25,6 +25,10 @@ local function new_ip(ipStr, proto) elseif proto ~= "IPv4" and proto ~= "IPv6" then return nil, "invalid protocol"; end + local zone; + if proto == "IPv6" and ipStr:find('%', 1, true) then + ipStr, zone = ipStr:match("^(.-)%%(.*)"); + end if proto == "IPv6" and ipStr:find('.', 1, true) then local changed; ipStr, changed = ipStr:gsub(":(%d+)%.(%d+)%.(%d+)%.(%d+)$", function(a,b,c,d) @@ -33,7 +37,7 @@ local function new_ip(ipStr, proto) if changed ~= 1 then return nil, "invalid-address"; end end - return setmetatable({ addr = ipStr, proto = proto }, ip_mt); + return setmetatable({ addr = ipStr, proto = proto, zone = zone }, ip_mt); end local function toBits(ip) diff --git a/util/random.lua b/util/random.lua index 5938a94f..4963e98c 100644 --- a/util/random.lua +++ b/util/random.lua @@ -6,35 +6,15 @@ -- COPYING file in the source package for more information. -- -local tostring = tostring; -local os_time = os.time; -local os_clock = os.clock; -local ceil = math.ceil; -local H = require "util.hashes".sha512; - -local last_uniq_time = 0; -local function uniq_time() - local new_uniq_time = os_time(); - if last_uniq_time >= new_uniq_time then new_uniq_time = last_uniq_time + 1; end - last_uniq_time = new_uniq_time; - return new_uniq_time; -end - -local function new_random(x) - return H(x..os_clock()..tostring({})); -end - -local buffer = new_random(uniq_time()); +local urandom = assert(io.open("/dev/urandom", "r+")); local function seed(x) - buffer = new_random(buffer..x); + urandom:write(x); + urandom:flush(); end local function bytes(n) - if #buffer < n+4 then seed(uniq_time()); end - local r = buffer:sub(1, n); - buffer = buffer:sub(n+1); - return r; + return urandom:read(n); end return { diff --git a/util/uuid.lua b/util/uuid.lua index e10fc0f7..f4fd21f6 100644 --- a/util/uuid.lua +++ b/util/uuid.lua @@ -16,7 +16,7 @@ local function get_nibbles(n) end local function get_twobits() - return ("%x"):format(get_nibbles(1):byte() % 4 + 8); + return ("%x"):format(random_bytes(1):byte() % 4 + 8); end local function generate() |