From 85355a78c23909937f9511c7401a4119e2b6e25d Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sun, 14 Apr 2019 02:06:20 +0200 Subject: util.ip: Add missing netmask for 192.168/16 range (fixes #1343) --- util/ip.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'util') diff --git a/util/ip.lua b/util/ip.lua index 0ec9e297..d1808225 100644 --- a/util/ip.lua +++ b/util/ip.lua @@ -203,7 +203,7 @@ local rfc6598 = new_ip("100.64.0.0"); function ip_methods:private() local private = self.scope ~= 0xE; if not private and self.proto == "IPv4" then - return match(self, rfc1918_8, 8) or match(self, rfc1918_12, 12) or match(self, rfc1918_16) or match(self, rfc6598, 10); + return match(self, rfc1918_8, 8) or match(self, rfc1918_12, 12) or match(self, rfc1918_16, 16) or match(self, rfc6598, 10); end return private; end -- cgit v1.2.3 From db3b9bf5e54e8754d374ea18a444dec777d0f24c Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sat, 18 May 2019 17:28:21 +0200 Subject: util.random: Handle unlikely read errors from /dev/urandom (see #1313) --- util/random.lua | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'util') diff --git a/util/random.lua b/util/random.lua index d8a84514..8ae06b49 100644 --- a/util/random.lua +++ b/util/random.lua @@ -12,7 +12,11 @@ if ok then return crand; end local urandom, urandom_err = io.open("/dev/urandom", "r"); local function bytes(n) - return urandom:read(n); + local data, err = urandom:read(n); + if not data then + error("Unable to retrieve data from secure random number generator (/dev/urandom): "..err); + end + return data; end if not urandom then -- cgit v1.2.3 From f430272c0164496c91a86ad5e027248afda401d4 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sat, 18 May 2019 18:51:25 +0200 Subject: util.random: Coerce error to string (thanks waqas) In theory this could happen in an EOF condition, which should be impossible with a read from /dev/urandom. --- util/random.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'util') diff --git a/util/random.lua b/util/random.lua index 8ae06b49..51f2747d 100644 --- a/util/random.lua +++ b/util/random.lua @@ -14,7 +14,7 @@ local urandom, urandom_err = io.open("/dev/urandom", "r"); local function bytes(n) local data, err = urandom:read(n); if not data then - error("Unable to retrieve data from secure random number generator (/dev/urandom): "..err); + error("Unable to retrieve data from secure random number generator (/dev/urandom): "..tostring(err)); end return data; end -- cgit v1.2.3 From 069408d15861035e9da8052068c60939be938ab3 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Tue, 21 May 2019 08:52:21 +0200 Subject: util.random: Throw different error for EOL condition --- util/random.lua | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'util') diff --git a/util/random.lua b/util/random.lua index 51f2747d..6782d7fa 100644 --- a/util/random.lua +++ b/util/random.lua @@ -14,7 +14,11 @@ local urandom, urandom_err = io.open("/dev/urandom", "r"); local function bytes(n) local data, err = urandom:read(n); if not data then - error("Unable to retrieve data from secure random number generator (/dev/urandom): "..tostring(err)); + if err then + error("Unable to retrieve data from secure random number generator (/dev/urandom): "..tostring(err)); + else + error("Secure random number generator (/dev/urandom) returned an end-of-file condition"); + end end return data; end -- cgit v1.2.3 From e6815c87fb538b894839472820d97d644b20b241 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Thu, 30 May 2019 23:50:28 +0200 Subject: util.sql: Ignore if tables and indices already exist on creation (fixes #1064) Tested with SQLite3 3.16.2 and 3.27.2 and Postgres 11. MySQL does not support IF NOT EXISTS for indices so not handled here. --- util/sql.lua | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'util') diff --git a/util/sql.lua b/util/sql.lua index 47900102..00c7b57f 100644 --- a/util/sql.lua +++ b/util/sql.lua @@ -238,6 +238,9 @@ function engine:transaction(...) end function engine:_create_index(index) local sql = "CREATE INDEX \""..index.name.."\" ON \""..index.table.."\" ("; + if self.params.driver ~= "MySQL" then + sql = sql:gsub("^CREATE INDEX", "%1 IF NOT EXISTS"); + end for i=1,#index do sql = sql.."\""..index[i].."\""; if i ~= #index then sql = sql..", "; end @@ -256,6 +259,9 @@ function engine:_create_index(index) end function engine:_create_table(table) local sql = "CREATE TABLE \""..table.name.."\" ("; + do + sql = sql:gsub("^CREATE TABLE", "%1 IF NOT EXISTS"); + end for i,col in ipairs(table.c) do local col_type = col.type; if col_type == "MEDIUMTEXT" and self.params.driver ~= "MySQL" then -- cgit v1.2.3 From 5399b9b9057f8202ceb25e933d10e1825383bc99 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Mon, 8 Jul 2019 02:46:27 +0200 Subject: util.serialization: Cache default serialization instance (fixes #1389) Most serialization uses still use the default serialize() and thus duplicate much of the setup, which negates some of the performance improvements of the rewrite. --- util/serialization.lua | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'util') diff --git a/util/serialization.lua b/util/serialization.lua index dd6a2a2b..5121a9f9 100644 --- a/util/serialization.lua +++ b/util/serialization.lua @@ -272,10 +272,15 @@ local function deserialize(str) return ret; end +local default = new(); return { new = new; serialize = function (x, opt) - return new(opt)(x); + if opt == nil then + return default(x); + else + return new(opt)(x); + end end; deserialize = deserialize; }; -- cgit v1.2.3 From e55d816cdd519667a206149099a60e2ee6b5a91d Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sun, 20 Oct 2019 20:52:14 +0200 Subject: util.interpolation: Support unescaped variables with more modifiers (fixes #1452) Tests will be added in trunk. --- util/interpolation.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'util') diff --git a/util/interpolation.lua b/util/interpolation.lua index 315cc203..e0ccf47b 100644 --- a/util/interpolation.lua +++ b/util/interpolation.lua @@ -32,7 +32,7 @@ local function new_render(pat, escape, funcs) -- assert(type(values) == "table", "bad argument #2 to 'render' (table expected)"); return (s_gsub(template, pat, function (block) block = s_sub(block, 2, -2); - local name, opt, e = s_match(block, "^([%a_][%w_.]*)(%p?)()"); + local name, raw, opt, e = s_match(block, "^([%a_][%w_.]*)(!?)(%p?)()"); if not name then return end local value = values[name]; if not value and name:find(".", 2, true) then @@ -45,7 +45,7 @@ local function new_render(pat, escape, funcs) if funcs then while value ~= nil and opt == '|' do local f; - f, opt, e = s_match(block, "^([%a_][%w_.]*)(%p?)()", e); + f, raw, opt, e = s_match(block, "^([%a_][%w_.]*)(!?)(%p?)()", e); f = funcs[f]; if f then value = f(value); end end @@ -70,7 +70,7 @@ local function new_render(pat, escape, funcs) if type(value) ~= "string" then value = tostring(value); end - if opt ~= '!' then + if raw ~= '!' then return escape(value); end return value; -- cgit v1.2.3 From 64b86ad50602aae90cee6bf0de5647f5e90287b2 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sun, 3 Nov 2019 22:19:09 +0100 Subject: util.startup: Update config path (fixes #1430) --- util/startup.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'util') diff --git a/util/startup.lua b/util/startup.lua index c101c290..82d0804d 100644 --- a/util/startup.lua +++ b/util/startup.lua @@ -33,7 +33,8 @@ function startup.read_config() if file then file:close(); prosody.config_file = filename; - CFG_CONFIGDIR = filename:match("^(.*)[\\/][^\\/]*$"); -- luacheck: ignore 111 + prosody.paths.config = filename:match("^(.*)[\\/][^\\/]*$"); + CFG_CONFIGDIR = prosody.paths.config; -- luacheck: ignore 111 break; end end -- cgit v1.2.3 From 65bbfdb65b7abecb941537de863e4856e5b637cd Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Mon, 4 Nov 2019 00:29:49 +0100 Subject: util.startup: Ensure prosody.paths are absolute (see #1430) Normally these paths are injected into the installed 'prosody' executable as absolute paths, but it is possible to override at least the config path via environment variable or command line argument. This makes sure a path relative to pwd stays relative to that instead of the data directory. --- util/startup.lua | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'util') diff --git a/util/startup.lua b/util/startup.lua index 82d0804d..e88ed709 100644 --- a/util/startup.lua +++ b/util/startup.lua @@ -231,8 +231,14 @@ end function startup.chdir() if prosody.installed then + local lfs = require "lfs"; + -- Ensure paths are absolute, not relative to the working directory which we're about to change + local cwd = lfs.currentdir(); + prosody.paths.source = config.resolve_relative_path(cwd, prosody.paths.source); + prosody.paths.config = config.resolve_relative_path(cwd, prosody.paths.config); + prosody.paths.data = config.resolve_relative_path(cwd, prosody.paths.data); -- Change working directory to data path. - require "lfs".chdir(prosody.paths.data); + lfs.chdir(prosody.paths.data); end end -- cgit v1.2.3 From abff09b5b516ba8d0cf462c1e68e6669f48b8aaa Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Thu, 6 Jun 2019 17:37:15 +0200 Subject: util.pubsub: Factor out calling of broadcaster This will simplify doing things along with broadcasting. --- util/pubsub.lua | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'util') diff --git a/util/pubsub.lua b/util/pubsub.lua index e5e0cb7c..24f1f41d 100644 --- a/util/pubsub.lua +++ b/util/pubsub.lua @@ -499,7 +499,7 @@ function service:delete(node, actor) --> ok, err end self.events.fire_event("node-deleted", { service = self, node = node, actor = actor }); - self.config.broadcaster("delete", node, node_obj.subscribers, nil, actor, node_obj, self); + self:broadcast("delete", node, node_obj.subscribers, nil, actor, node_obj); return true; end @@ -562,10 +562,14 @@ function service:publish(node, actor, id, item, requested_config) --> ok, err local event_data = { service = self, node = node, actor = actor, id = id, item = item }; self.events.fire_event("item-published/"..node, event_data); self.events.fire_event("item-published", event_data); - self.config.broadcaster("items", node, node_obj.subscribers, item, actor, node_obj, self); + self:broadcast("items", node, node_obj.subscribers, item, actor, node_obj); return true; end +function service:broadcast(event, node, subscribers, item, actor, node_obj) + return self.config.broadcaster(event, node, subscribers, item, actor, node_obj, self); +end + function service:retract(node, actor, id, retract) --> ok, err -- Access checking if not self:may(node, actor, "retract") then @@ -582,7 +586,7 @@ function service:retract(node, actor, id, retract) --> ok, err end self.events.fire_event("item-retracted", { service = self, node = node, actor = actor, id = id }); if retract then - self.config.broadcaster("retract", node, node_obj.subscribers, retract, actor, node_obj, self); + self:broadcast("retract", node, node_obj.subscribers, retract, actor, node_obj); end return true end @@ -604,7 +608,7 @@ function service:purge(node, actor, notify) --> ok, err end self.events.fire_event("node-purged", { service = self, node = node, actor = actor }); if notify then - self.config.broadcaster("purge", node, node_obj.subscribers, nil, actor, node_obj, self); + self:broadcast("purge", node, node_obj.subscribers, nil, actor, node_obj); end return true end -- cgit v1.2.3 From 0307e6754aec0011923b2d010103a8c81146cb13 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Thu, 6 Jun 2019 18:13:46 +0200 Subject: util.pubsub: Pass subscribers trough a filter callback --- util/pubsub.lua | 2 ++ 1 file changed, 2 insertions(+) (limited to 'util') diff --git a/util/pubsub.lua b/util/pubsub.lua index 24f1f41d..1674b9a7 100644 --- a/util/pubsub.lua +++ b/util/pubsub.lua @@ -6,6 +6,7 @@ local service_mt = {}; local default_config = { itemstore = function (config, _) return cache.new(config["max_items"]) end; broadcaster = function () end; + subscriber_filter = function (subs) return subs end; itemcheck = function () return true; end; get_affiliation = function () end; normalize_jid = function (jid) return jid; end; @@ -567,6 +568,7 @@ function service:publish(node, actor, id, item, requested_config) --> ok, err end function service:broadcast(event, node, subscribers, item, actor, node_obj) + subscribers = self.config.subscriber_filter(subscribers, node, event); return self.config.broadcaster(event, node, subscribers, item, actor, node_obj, self); end -- cgit v1.2.3 From 17358273f2d7ad5624459ecc3d0c01b8bb48a1f2 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Sun, 19 Jan 2020 15:26:22 +0000 Subject: util.startup: Add startup step for parsing command-line options --- util/startup.lua | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) (limited to 'util') diff --git a/util/startup.lua b/util/startup.lua index e88ed709..fb898970 100644 --- a/util/startup.lua +++ b/util/startup.lua @@ -12,6 +12,60 @@ local dependencies = require "util.dependencies"; local original_logging_config; +local short_params = { D = "daemonize", F = "no-daemonize" }; +local value_params = { config = true }; + +function startup.parse_args() + local parsed_opts = {}; + + if #arg > 0 and arg[1] ~= "--config" then + while true do + local raw_param = arg[1]; + if not raw_param then + break; + end + + local prefix = raw_param:match("^%-%-?"); + if not prefix then + break; + elseif prefix == "--" and raw_param == "--" then + table.remove(arg, 1); + break; + end + local param = table.remove(arg, 1):sub(#prefix+1); + if #param == 1 then + param = short_params[param]; + end + + if not param then + print("Unknown command-line option: "..tostring(param)); + print("Perhaps you meant to use prosodyctl instead?"); + os.exit(1); + end + + local param_k, param_v; + if value_params[param] then + param_k, param_v = param, table.remove(arg, 1); + if not param_v then + print("Expected a value to follow command-line option: "..raw_param); + os.exit(1); + end + else + param_k, param_v = param:match("^([^=]+)=(.+)$"); + if not param_k then + if param:match("^no%-") then + param_k, param_v = param:sub(4), false; + else + param_k, param_v = param, true; + end + end + end + parsed_opts[param_k] = param_v; + end + end + prosody.opts = parsed_opts; +end + function startup.read_config() local filenames = {}; -- cgit v1.2.3 From f24308103fa0d4057a36069dffff7514760274e5 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Sun, 19 Jan 2020 15:27:16 +0000 Subject: prosody/util.startup: Switch to parse_args() for --root and --config --- util/startup.lua | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'util') diff --git a/util/startup.lua b/util/startup.lua index fb898970..93f40c8f 100644 --- a/util/startup.lua +++ b/util/startup.lua @@ -70,12 +70,11 @@ function startup.read_config() local filenames = {}; local filename; - if arg[1] == "--config" and arg[2] then - table.insert(filenames, arg[2]); + if prosody.opts.config then + table.insert(filenames, prosody.opts.config); if CFG_CONFIGDIR then - table.insert(filenames, CFG_CONFIGDIR.."/"..arg[2]); + table.insert(filenames, CFG_CONFIGDIR.."/"..prosody.opts.config); end - table.remove(arg, 1); table.remove(arg, 1); elseif os.getenv("PROSODY_CONFIG") then -- Passed by prosodyctl table.insert(filenames, os.getenv("PROSODY_CONFIG")); else @@ -459,8 +458,7 @@ function startup.switch_user() os.exit(1); end prosody.current_uid = pposix.getuid(); - local arg_root = arg[1] == "--root"; - if arg_root then table.remove(arg, 1); end + local arg_root = prosody.opts.root; if prosody.current_uid == 0 and config.get("*", "run_as_root") ~= true and not arg_root then -- We haz root! local desired_user = config.get("*", "prosody_user") or "prosody"; @@ -569,6 +567,7 @@ end -- prosodyctl only function startup.prosodyctl() + startup.parse_args(); startup.init_global_state(); startup.read_config(); startup.force_console_logging(); @@ -589,6 +588,7 @@ end function startup.prosody() -- These actions are in a strict order, as many depend on -- previous steps to have already been performed + startup.parse_args(); startup.init_global_state(); startup.read_config(); startup.init_logging(); -- cgit v1.2.3 From 8b60eaf2f346875a10a206088f6214f2200dcc55 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Sun, 19 Jan 2020 15:39:13 +0000 Subject: util.startup: Fix logic to make --config work again --- util/startup.lua | 76 +++++++++++++++++++++++++++++--------------------------- 1 file changed, 39 insertions(+), 37 deletions(-) (limited to 'util') diff --git a/util/startup.lua b/util/startup.lua index 93f40c8f..e54d6935 100644 --- a/util/startup.lua +++ b/util/startup.lua @@ -18,50 +18,52 @@ local value_params = { config = true }; function startup.parse_args() local parsed_opts = {}; - if #arg > 0 and arg[1] ~= "--config" then - while true do - local raw_param = arg[1]; - if not raw_param then - break; - end + if #arg == 0 then + return; + end + while true do + local raw_param = arg[1]; + if not raw_param then + break; + end - local prefix = raw_param:match("^%-%-?"); - if not prefix then - break; - elseif prefix == "--" and raw_param == "--" then - table.remove(arg, 1); - break; - end - local param = table.remove(arg, 1):sub(#prefix+1); - if #param == 1 then - param = short_params[param]; - end + local prefix = raw_param:match("^%-%-?"); + if not prefix then + break; + elseif prefix == "--" and raw_param == "--" then + table.remove(arg, 1); + break; + end + local param = table.remove(arg, 1):sub(#prefix+1); + if #param == 1 then + param = short_params[param]; + end - if not param then - print("Unknown command-line option: "..tostring(param)); - print("Perhaps you meant to use prosodyctl instead?"); + if not param then + print("Unknown command-line option: "..tostring(param)); + print("Perhaps you meant to use prosodyctl instead?"); + os.exit(1); + end + + local param_k, param_v; + if value_params[param] then + param_k, param_v = param, table.remove(arg, 1); + if not param_v then + print("Expected a value to follow command-line option: "..raw_param); os.exit(1); end - - local param_k, param_v; - if value_params[param] then - param_k, param_v = param, table.remove(arg, 1); - if not param_v then - print("Expected a value to follow command-line option: "..raw_param); - os.exit(1); - end - else - param_k, param_v = param:match("^([^=]+)=(.+)$"); - if not param_k then - if param:match("^no%-") then - param_k, param_v = param:sub(4), false; - else - param_k, param_v = param, true; - end + else + param_k, param_v = param:match("^([^=]+)=(.+)$"); + if not param_k then + if param:match("^no%-") then + param_k, param_v = param:sub(4), false; + else + param_k, param_v = param, true; end end - parsed_opts[param_k] = param_v; end + parsed_opts[param_k] = param_v; + print("ARG", param_k, param_v); end prosody.opts = parsed_opts; end -- cgit v1.2.3 From a443414b2b1582836126d7c3b09957cdd1cd692e Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Sun, 19 Jan 2020 15:50:16 +0000 Subject: util.startup: Remove accidentally-committed debugging --- util/startup.lua | 1 - 1 file changed, 1 deletion(-) (limited to 'util') diff --git a/util/startup.lua b/util/startup.lua index e54d6935..35be3162 100644 --- a/util/startup.lua +++ b/util/startup.lua @@ -63,7 +63,6 @@ function startup.parse_args() end end parsed_opts[param_k] = param_v; - print("ARG", param_k, param_v); end prosody.opts = parsed_opts; end -- cgit v1.2.3 From 0b1e6fe7a719abfda49ca17413c6a567c90635a2 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Sun, 19 Jan 2020 15:50:32 +0000 Subject: util.startup: Ensure prosody.opts exists even when no options provided --- util/startup.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'util') diff --git a/util/startup.lua b/util/startup.lua index 35be3162..24ed6026 100644 --- a/util/startup.lua +++ b/util/startup.lua @@ -17,6 +17,7 @@ local value_params = { config = true }; function startup.parse_args() local parsed_opts = {}; + prosody.opts = parsed_opts; if #arg == 0 then return; @@ -64,7 +65,6 @@ function startup.parse_args() end parsed_opts[param_k] = param_v; end - prosody.opts = parsed_opts; end function startup.read_config() -- cgit v1.2.3 From 81325abb7a06ca38e273eef6b0db7f4750c82bcb Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Mon, 24 Feb 2020 23:16:08 +0100 Subject: util.datamanager: Fix iterating over "users" (thanks marc0s) The 'store' path componend used to be unescaped until 756a2a00e7e7 added escaping to address issues with characters like '/' used in PEP, but with a special case for '_' which was already in common use in 'store' path components. Missed adding this escaping here. --- util/datamanager.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'util') diff --git a/util/datamanager.lua b/util/datamanager.lua index cf96887b..0d7060b7 100644 --- a/util/datamanager.lua +++ b/util/datamanager.lua @@ -320,7 +320,7 @@ local type_map = { local function users(host, store, typ) -- luacheck: ignore 431/store typ = type_map[typ or "keyval"]; - local store_dir = format("%s/%s/%s", data_path, encode(host), store); + local store_dir = format("%s/%s/%s", data_path, encode(host), store_encode(store)); local mode, err = lfs.attributes(store_dir, "mode"); if not mode then -- cgit v1.2.3 From 0b713578627418a5bc100d83253bb84b365fef3d Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sun, 26 Jan 2020 16:40:21 +0100 Subject: util.prosodyctl: Tell prosody do daemonize via command line flag (fixes #1514) Backport of 88be11e9f9b9 --- util/prosodyctl.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'util') diff --git a/util/prosodyctl.lua b/util/prosodyctl.lua index 5f0c4d12..6c84ab6e 100644 --- a/util/prosodyctl.lua +++ b/util/prosodyctl.lua @@ -238,9 +238,9 @@ local function start(source_dir) return false, "already-running"; end if not source_dir then - os.execute("./prosody"); + os.execute("./prosody -D"); else - os.execute(source_dir.."/../../bin/prosody"); + os.execute(source_dir.."/../../bin/prosody -D"); end return true; end -- cgit v1.2.3 From f72fa3b2abd2bf18540460b37bf9ca1c8a479b7f Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Fri, 22 May 2020 20:59:01 +0200 Subject: util.sasl.scram: Apply saslprep before hashing password, fixes #1560 --- util/sasl/scram.lua | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'util') diff --git a/util/sasl/scram.lua b/util/sasl/scram.lua index 043f328b..f64feb8b 100644 --- a/util/sasl/scram.lua +++ b/util/sasl/scram.lua @@ -106,6 +106,10 @@ local function getAuthenticationDatabaseSHA1(password, salt, iteration_count) if iteration_count < 4096 then log("warn", "Iteration count < 4096 which is the suggested minimum according to RFC 5802.") end + password = saslprep(password); + if not password then + return false, "password fails SASLprep"; + end local salted_password = Hi(password, salt, iteration_count); local stored_key = sha1(hmac_sha1(salted_password, "Client Key")) local server_key = hmac_sha1(salted_password, "Server Key"); -- cgit v1.2.3 From 7621990511255e6d9199af6451a4791abde3aea5 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Fri, 22 May 2020 21:05:45 +0200 Subject: util.sasl.plain: Apply saslprep to stored password Fixes something like #1560 here too. The password sent by the user already had saslprep applied. --- util/sasl/plain.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'util') diff --git a/util/sasl/plain.lua b/util/sasl/plain.lua index 00c6bd20..43a66c5b 100644 --- a/util/sasl/plain.lua +++ b/util/sasl/plain.lua @@ -70,7 +70,7 @@ local function plain(self, message) if self.profile.plain then local correct_password; correct_password, state = self.profile.plain(self, authentication, self.realm); - correct = (correct_password == password); + correct = (saslprep(correct_password) == password); elseif self.profile.plain_test then correct, state = self.profile.plain_test(self, authentication, password, self.realm); end -- cgit v1.2.3 From 7448c5c1b181055cabbe707c2deb9e4b575df507 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Mon, 22 Jun 2020 14:56:44 +0200 Subject: util.startup: Remove duplicated initialization of logging (fix #1527) --- util/startup.lua | 1 - 1 file changed, 1 deletion(-) (limited to 'util') diff --git a/util/startup.lua b/util/startup.lua index 24ed6026..2a7e8a36 100644 --- a/util/startup.lua +++ b/util/startup.lua @@ -597,7 +597,6 @@ function startup.prosody() startup.sandbox_require(); startup.set_function_metatable(); startup.check_dependencies(); - startup.init_logging(); startup.load_libraries(); startup.setup_plugindir(); startup.setup_datadir(); -- cgit v1.2.3 From 5f8f75ddab1610b193ced17dec46164b6db72db8 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Mon, 15 Jun 2020 14:16:10 +0100 Subject: util.gc: New module for configuring the Lua garbage collector --- util/gc.lua | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 util/gc.lua (limited to 'util') diff --git a/util/gc.lua b/util/gc.lua new file mode 100644 index 00000000..e02e85c4 --- /dev/null +++ b/util/gc.lua @@ -0,0 +1,50 @@ +local array = require "util.array"; +local set = require "util.set"; + +local known_options = { + incremental = set.new { "mode", "threshold", "speed", "step_size" }; + generational = set.new { "mode", "minor_threshold", "major_threshold" }; +}; + +if _VERSION ~= "5.4" then + known_options.generational = nil; + known_options.incremental:remove("step_size"); +end + +local function configure(user, defaults) + local mode = user.mode or defaults.mode or "incremental"; + if not known_options[mode] then + return nil, "GC mode not supported on ".._VERSION..": "..mode; + end + + for k, v in pairs(user) do + if not known_options[mode]:contains(k) then + return nil, "Unknown GC parameter: "..k; + elseif k ~= "mode" and type(v) ~= "number" then + return nil, "parameter '"..k.."' should be a number"; + end + end + + if mode == "incremental" then + if _VERSION == "Lua 5.4" then + collectgarbage(mode, + user.threshold or defaults.threshold, + user.speed or defaults.speed, + user.step_size or defaults.step_size + ); + else + collectgarbage("setpause", user.threshold or defaults.threshold); + collectgarbage("setstepmul", user.speed or defaults.speed); + end + elseif mode == "generational" then + collectgarbage(mode, + user.minor_threshold or defaults.minor_threshold, + user.major_threshold or defaults.major_threshold + ); + end + return true; +end + +return { + configure = configure; +}; -- cgit v1.2.3 From f46f4b97ebf16c4816d5e8847baeb062c0212bd9 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Mon, 15 Jun 2020 14:23:47 +0100 Subject: util.gc: Linter fixes [luacheck] --- util/gc.lua | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'util') diff --git a/util/gc.lua b/util/gc.lua index e02e85c4..b400af6b 100644 --- a/util/gc.lua +++ b/util/gc.lua @@ -1,4 +1,3 @@ -local array = require "util.array"; local set = require "util.set"; local known_options = { @@ -41,7 +40,7 @@ local function configure(user, defaults) user.minor_threshold or defaults.minor_threshold, user.major_threshold or defaults.major_threshold ); - end + end return true; end -- cgit v1.2.3 From e83907f4990b671d8953f64f1b2663d0df0226d4 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Mon, 15 Jun 2020 14:16:34 +0100 Subject: util.startup: Configure the GC on startup, using the config or built-in defaults --- util/startup.lua | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'util') diff --git a/util/startup.lua b/util/startup.lua index 2a7e8a36..c1f4ec8b 100644 --- a/util/startup.lua +++ b/util/startup.lua @@ -12,6 +12,8 @@ local dependencies = require "util.dependencies"; local original_logging_config; +local default_gc_params = { mode = "incremental", threshold = 105, speed = 250 }; + local short_params = { D = "daemonize", F = "no-daemonize" }; local value_params = { config = true }; @@ -544,6 +546,19 @@ function startup.check_unwriteable() end end +function startup.init_gc() + -- Apply garbage collector settings from the config file + local gc = require "util.gc"; + local gc_settings = config.get("*", "gc") or { mode = default_gc_params.mode }; + + local ok, err = gc.configure(gc_settings, default_gc_params); + if not ok then + log("error", "Failed to apply GC configuration: %s", err); + return nil, err; + end + return true; +end + function startup.make_host(hostname) return { type = "local", @@ -573,6 +588,7 @@ function startup.prosodyctl() startup.read_config(); startup.force_console_logging(); startup.init_logging(); + startup.init_gc(); startup.setup_plugindir(); startup.setup_datadir(); startup.chdir(); @@ -593,6 +609,7 @@ function startup.prosody() startup.init_global_state(); startup.read_config(); startup.init_logging(); + startup.init_gc(); startup.sanity_check(); startup.sandbox_require(); startup.set_function_metatable(); -- cgit v1.2.3 From 6774f93b5da1642c1baef1387880da484428981e Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Fri, 26 Jun 2020 16:41:31 +0100 Subject: util.dbuffer: dynamic string buffer Similar to util.ringbuffer (and shares almost identical API). Differences: - size limit is optional and dynamic - does not allocate a fixed buffer of max_size bytes - focus on simply storing references to existing string objects where possible, avoiding unnecessary allocations - references are still stored in a ring buffer to enable use as a fast FIFO Optional second parameter to new() provides the number of ring buffer segments. On Lua 5.2 on my laptop, a segment is ~19 bytes. If the ring buffer fills up, the next write will compact all strings into a single item. --- util/queue.lua | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'util') diff --git a/util/queue.lua b/util/queue.lua index 728e905f..c8e71514 100644 --- a/util/queue.lua +++ b/util/queue.lua @@ -51,6 +51,13 @@ local function new(size, allow_wrapping) end return t[tail]; end; + replace = function (self, data) + if items == 0 then + return self:push(data); + end + t[tail] = data; + return true; + end; items = function (self) --luacheck: ignore 431/t return function (t, pos) -- cgit v1.2.3 From 0156ad50d3f7b8fcfc12f0ebf9d2c2fee4df36ee Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Mon, 24 Aug 2020 16:18:13 +0100 Subject: util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case) This also appears to fix some bugs with chunk-encoded streams in net.http.parser. --- util/dbuffer.lua | 176 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 176 insertions(+) create mode 100644 util/dbuffer.lua (limited to 'util') diff --git a/util/dbuffer.lua b/util/dbuffer.lua new file mode 100644 index 00000000..a50f3a64 --- /dev/null +++ b/util/dbuffer.lua @@ -0,0 +1,176 @@ +local queue = require "util.queue"; + +local dbuffer_methods = {}; +local dynamic_buffer_mt = { __index = dbuffer_methods }; + +function dbuffer_methods:write(data) + if self.max_size and #data + self._length > self.max_size then + return nil; + end + local ok = self.items:push(data); + if not ok then + self:collapse(); + ok = self.items:push(data); + end + if not ok then + return nil; + end + self._length = self._length + #data; + return true; +end + +function dbuffer_methods:read_chunk(requested_bytes) + local chunk, consumed = self.items:peek(), self.front_consumed; + if not chunk then return; end + local chunk_length = #chunk; + local remaining_chunk_length = chunk_length - consumed; + if not requested_bytes then + requested_bytes = remaining_chunk_length; + end + if remaining_chunk_length <= requested_bytes then + self.front_consumed = 0; + self._length = self._length - remaining_chunk_length; + self.items:pop(); + assert(#chunk:sub(consumed + 1, -1) == remaining_chunk_length); + return chunk:sub(consumed + 1, -1), remaining_chunk_length; + end + local end_pos = consumed + requested_bytes; + self.front_consumed = end_pos; + self._length = self._length - requested_bytes; + assert(#chunk:sub(consumed + 1, end_pos) == requested_bytes); + return chunk:sub(consumed + 1, end_pos), requested_bytes; +end + +function dbuffer_methods:read(requested_bytes) + local chunks; + + if requested_bytes and requested_bytes > self._length then + return nil; + end + + local chunk, read_bytes = self:read_chunk(requested_bytes); + if not requested_bytes then + return chunk; + elseif chunk then + requested_bytes = requested_bytes - read_bytes; + if requested_bytes == 0 then -- Already read everything we need + return chunk; + end + chunks = {}; + else + return nil; + end + + -- Need to keep reading more chunks + while chunk do + table.insert(chunks, chunk); + if requested_bytes > 0 then + chunk, read_bytes = self:read_chunk(requested_bytes); + requested_bytes = requested_bytes - read_bytes; + else + break; + end + end + + return table.concat(chunks); +end + +function dbuffer_methods:discard(requested_bytes) + if requested_bytes > self._length then + return nil; + end + + local chunk, read_bytes = self:read_chunk(requested_bytes); + if chunk then + requested_bytes = requested_bytes - read_bytes; + if requested_bytes == 0 then -- Already read everything we need + return true; + end + else + return nil; + end + + while chunk do + if requested_bytes > 0 then + chunk, read_bytes = self:read_chunk(requested_bytes); + requested_bytes = requested_bytes - read_bytes; + else + break; + end + end + return true; +end + +function dbuffer_methods:sub(i, j) + if j == nil then + j = -1; + end + if j < 0 then + j = self._length + (j+1); + end + if i < 0 then + i = self._length + (i+1); + end + if i < 1 then + i = 1; + end + if j > self._length then + j = self._length; + end + if i > j then + return ""; + end + + self:collapse(j); + + return self.items:peek():sub(self.front_consumed+1):sub(i, j); +end + +function dbuffer_methods:byte(i, j) + i = i or 1; + j = j or i; + return string.byte(self:sub(i, j), 1, -1); +end + +function dbuffer_methods:length() + return self._length; +end +dynamic_buffer_mt.__len = dbuffer_methods.length; -- support # operator + +function dbuffer_methods:collapse(bytes) + bytes = bytes or self._length; + + local front_chunk = self.items:peek(); + + if not front_chunk or #front_chunk - self.front_consumed >= bytes then + return; + end + + local front_chunks = { front_chunk:sub(self.front_consumed+1) }; + local front_bytes = #front_chunks[1]; + + while front_bytes < bytes do + self.items:pop(); + local chunk = self.items:peek(); + front_bytes = front_bytes + #chunk; + table.insert(front_chunks, chunk); + end + self.items:replace(table.concat(front_chunks)); + self.front_consumed = 0; +end + +local function new(max_size, max_chunks) + if max_size and max_size <= 0 then + return nil; + end + return setmetatable({ + front_consumed = 0; + _length = 0; + max_size = max_size; + items = queue.new(max_chunks or 32); + }, dynamic_buffer_mt); +end + +return { + new = new; +}; -- cgit v1.2.3