aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/rostermanager.lua16
-rw-r--r--core/sessionmanager.lua16
-rw-r--r--core/usermanager.lua3
-rw-r--r--plugins/mod_presence.lua60
-rw-r--r--plugins/mod_privacy.lua16
-rw-r--r--plugins/mod_private.lua6
-rw-r--r--util/datamanager.lua18
-rw-r--r--util/sasl/scram.lua2
8 files changed, 77 insertions, 60 deletions
diff --git a/core/rostermanager.lua b/core/rostermanager.lua
index e2a92696..506cf205 100644
--- a/core/rostermanager.lua
+++ b/core/rostermanager.lua
@@ -93,15 +93,18 @@ function load_roster(username, host)
else -- Attempt to load roster for non-loaded user
log("debug", "load_roster: loading for offline user: "..username.."@"..host);
end
- roster = datamanager.load(username, host, "roster") or {};
+ local data, err = datamanager.load(username, host, "roster");
+ roster = data or {};
if user then user.roster = roster; end
- if not roster[false] then roster[false] = { }; end
+ if not roster[false] then roster[false] = { broken = err or nil }; end
if roster[jid] then
roster[jid] = nil;
log("warn", "roster for "..jid.." has a self-contact");
end
- hosts[host].events.fire_event("roster-load", username, host, roster);
- return roster;
+ if not err then
+ hosts[host].events.fire_event("roster-load", username, host, roster);
+ end
+ return roster, err;
end
function save_roster(username, host, roster)
@@ -122,6 +125,7 @@ function save_roster(username, host, roster)
if metadata.version ~= true then
metadata.version = (metadata.version or 0) + 1;
end
+ if roster[false].broken then return nil, "Not saving broken roster" end
return datamanager.store(username, host, "roster", roster);
end
log("warn", "save_roster: user had no roster to save");
@@ -187,9 +191,9 @@ function process_inbound_unsubscribe(username, host, jid)
end
function is_contact_subscribed(username, host, jid)
- local roster = load_roster(username, host);
+ local roster, err = load_roster(username, host);
local item = roster[jid];
- return item and (item.subscription == "from" or item.subscription == "both");
+ return item and (item.subscription == "from" or item.subscription == "both"), err;
end
function is_contact_pending_in(username, host, jid)
diff --git a/core/sessionmanager.lua b/core/sessionmanager.lua
index 6e771a84..fd6ed96e 100644
--- a/core/sessionmanager.lua
+++ b/core/sessionmanager.lua
@@ -136,7 +136,7 @@ function bind_resource(session, resource)
local sessions = hosts[session.host].sessions[session.username].sessions;
local limit = config_get(session.host, "core", "max_resources") or 10;
if #sessions >= limit then
- return nil, "cancel", "conflict", "Resource limit reached; only "..limit.." resources allowed";
+ return nil, "cancel", "resource-constraint", "Resource limit reached; only "..limit.." resources allowed";
end
if sessions[resource] then
-- Resource conflict
@@ -174,7 +174,19 @@ function bind_resource(session, resource)
hosts[session.host].sessions[session.username].sessions[resource] = session;
full_sessions[session.full_jid] = session;
- session.roster = rm_load_roster(session.username, session.host);
+ local err;
+ session.roster, err = rm_load_roster(session.username, session.host);
+ if err then
+ full_sessions[session.full_jid] = nil;
+ hosts[session.host].sessions[session.username].sessions[resource] = nil;
+ session.full_jid = nil;
+ session.resource = nil;
+ if next(bare_sessions[session.username..'@'..session.host].sessions) == nil then
+ bare_sessions[session.username..'@'..session.host] = nil;
+ hosts[session.host].sessions[session.username] = nil;
+ end
+ return nil, "cancel", "internal-server-error", "Error loading roster";
+ end
hosts[session.host].events.fire_event("resource-bind", {session=session});
diff --git a/core/usermanager.lua b/core/usermanager.lua
index 4fef936e..07097dc1 100644
--- a/core/usermanager.lua
+++ b/core/usermanager.lua
@@ -74,7 +74,8 @@ function new_default_provider(host)
function provider:user_exists(username)
if not(require_provisioning) and is_cyrus(host) then return true; end
- return datamanager.load(username, host, "accounts") ~= nil; -- FIXME also check for empty credentials
+ local account, err = datamanager.load(username, host, "accounts") ~= nil; -- FIXME also check for empty credentials
+ return (account or err) ~= nil; -- FIXME also check for empty credentials
end
function provider:create_user(username, password)
diff --git a/plugins/mod_presence.lua b/plugins/mod_presence.lua
index 5ad3bfdf..9071ae4c 100644
--- a/plugins/mod_presence.lua
+++ b/plugins/mod_presence.lua
@@ -38,42 +38,23 @@ function core_route_stanza(origin, stanza)
_core_route_stanza(origin, stanza);
end
-local select_top_resources;
-local bare_message_delivery_policy = module:get_option("bare_message_delivery_policy") or "priority";
-if bare_message_delivery_policy == "broadcast" then
- function select_top_resources(user)
- local recipients = {};
- for _, session in pairs(user.sessions) do -- find resources with non-negative priority
+local function select_top_resources(user)
+ local priority = 0;
+ local recipients = {};
+ for _, session in pairs(user.sessions) do -- find resource with greatest priority
+ if session.presence then
+ -- TODO check active privacy list for session
local p = session.priority;
- if p and p >= 0 then
+ if p > priority then
+ priority = p;
+ recipients = {session};
+ elseif p == priority then
t_insert(recipients, session);
end
end
- return recipients;
- end
-else
- if bare_message_delivery_policy ~= "priority" then
- module:log("warn", "Invalid value for config option bare_message_delivery_policy");
- end
- function select_top_resources(user)
- local priority = 0;
- local recipients = {};
- for _, session in pairs(user.sessions) do -- find resource with greatest priority
- if session.presence then
- -- TODO check active privacy list for session
- local p = session.priority;
- if p > priority then
- priority = p;
- recipients = {session};
- elseif p == priority then
- t_insert(recipients, session);
- end
- end
- end
- return recipients;
end
+ return recipients;
end
-
local function recalc_resource_map(user)
if user then
user.top_resources = select_top_resources(user);
@@ -81,7 +62,17 @@ local function recalc_resource_map(user)
end
end
+local ignore_presence_priority = module:get_option("ignore_presence_priority");
+
function handle_normal_presence(origin, stanza, core_route_stanza)
+ if ignore_presence_priority then
+ local priority = stanza:child_with_name("priority");
+ if priority and priority[1] ~= "0" then
+ for i=#priority.tags,1,-1 do priority.tags[i] = nil; end
+ for i=#priority,1,-1 do priority[i] = nil; end
+ priority[1] = "0";
+ end
+ end
if full_sessions[origin.full_jid] then -- if user is still connected
origin.send(stanza); -- reflect their presence back to them
end
@@ -236,16 +227,13 @@ function handle_inbound_presence_subscriptions_and_probes(origin, stanza, from_b
stanza.attr.from, stanza.attr.to = from_bare, to_bare;
log("debug", "inbound presence "..stanza.attr.type.." from "..from_bare.." for "..to_bare);
- if not node then
- log("debug", "dropping presence sent to host or invalid address '%s'", tostring(to_bare));
- end
-
if stanza.attr.type == "probe" then
- if rostermanager.is_contact_subscribed(node, host, from_bare) then
+ local result, err = rostermanager.is_contact_subscribed(node, host, from_bare);
+ if result then
if 0 == send_presence_of_available_resources(node, host, st_from, origin, core_route_stanza) then
core_route_stanza(hosts[host], st.presence({from=to_bare, to=from_bare, type="unavailable"})); -- TODO send last activity
end
- else
+ elseif not err then
core_route_stanza(hosts[host], st.presence({from=to_bare, to=from_bare, type="unsubscribed"}));
end
elseif stanza.attr.type == "subscribe" then
diff --git a/plugins/mod_privacy.lua b/plugins/mod_privacy.lua
index 3e9dbe49..ca5d51fa 100644
--- a/plugins/mod_privacy.lua
+++ b/plugins/mod_privacy.lua
@@ -307,7 +307,7 @@ function checkIfNeedToBeBlocked(e, session)
local is_to_user = bare_jid == jid_bare(to);
local is_from_user = bare_jid == jid_bare(from);
- module:log("debug", "stanza: %s, to: %s, from: %s", tostring(stanza.name), tostring(to), tostring(from));
+ --module:log("debug", "stanza: %s, to: %s, from: %s", tostring(stanza.name), tostring(to), tostring(from));
if privacy_lists.lists == nil or
not (session.activePrivacyList or privacy_lists.default)
@@ -315,7 +315,7 @@ function checkIfNeedToBeBlocked(e, session)
return; -- Nothing to block, default is Allow all
end
if is_from_user and is_to_user then
- module:log("debug", "Not blocking communications between user's resources");
+ --module:log("debug", "Not blocking communications between user's resources");
return; -- from one of a user's resource to another => HANDS OFF!
end
@@ -325,8 +325,8 @@ function checkIfNeedToBeBlocked(e, session)
listname = privacy_lists.default; -- no active list selected, use default list
end
local list = privacy_lists.lists[listname];
- if not list then
- module:log("debug", "given privacy list not found. name: %s", listname);
+ if not list then -- should never happen
+ module:log("warn", "given privacy list not found. name: %s for user %s", listname, bare_jid);
return;
end
for _,item in ipairs(list.items) do
@@ -345,10 +345,10 @@ function checkIfNeedToBeBlocked(e, session)
local evilJid = {};
apply = false;
if is_to_user then
- module:log("debug", "evil jid is (from): %s", from);
+ --module:log("debug", "evil jid is (from): %s", from);
evilJid.node, evilJid.host, evilJid.resource = jid_split(from);
else
- module:log("debug", "evil jid is (to): %s", to);
+ --module:log("debug", "evil jid is (to): %s", to);
evilJid.node, evilJid.host, evilJid.resource = jid_split(to);
end
if item.type == "jid" and
@@ -394,7 +394,7 @@ function checkIfNeedToBeBlocked(e, session)
end
return true; -- stanza blocked !
else
- module:log("debug", "stanza explicitly allowed!")
+ --module:log("debug", "stanza explicitly allowed!")
return;
end
end
@@ -425,7 +425,7 @@ function preCheckIncoming(e)
if session ~= nil then
return checkIfNeedToBeBlocked(e, session);
else
- module:log("debug", "preCheckIncoming: Couldn't get session for jid: %s@%s/%s", tostring(node), tostring(host), tostring(resource));
+ --module:log("debug", "preCheckIncoming: Couldn't get session for jid: %s@%s/%s", tostring(node), tostring(host), tostring(resource));
end
end
end
diff --git a/plugins/mod_private.lua b/plugins/mod_private.lua
index 859bf45a..abf1ec03 100644
--- a/plugins/mod_private.lua
+++ b/plugins/mod_private.lua
@@ -26,7 +26,11 @@ module:add_iq_handler("c2s", "jabber:iq:private",
if #query.tags == 1 then
local tag = query.tags[1];
local key = tag.name..":"..tag.attr.xmlns;
- local data = datamanager.load(node, host, "private");
+ local data, err = datamanager.load(node, host, "private");
+ if err then
+ session.send(st.error_reply(stanza, "wait", "internal-server-error"));
+ return true;
+ end
if stanza.attr.type == "get" then
if data and data[key] then
session.send(st.reply(stanza):tag("query", {xmlns = "jabber:iq:private"}):add_child(st.deserialize(data[key])));
diff --git a/util/datamanager.lua b/util/datamanager.lua
index 01c7aab2..57cd2594 100644
--- a/util/datamanager.lua
+++ b/util/datamanager.lua
@@ -21,12 +21,13 @@ local next = next;
local t_insert = table.insert;
local append = require "util.serialization".append;
local path_separator = "/"; if os.getenv("WINDIR") then path_separator = "\\" end
+local lfs = require "lfs";
local raw_mkdir;
if prosody.platform == "posix" then
raw_mkdir = require "util.pposix".mkdir; -- Doesn't trample on umask
else
- raw_mkdir = require "lfs".mkdir;
+ raw_mkdir = lfs.mkdir;
end
module "datamanager"
@@ -111,14 +112,21 @@ end
function load(username, host, datastore)
local data, ret = loadfile(getpath(username, host, datastore));
if not data then
- log("debug", "Failed to load "..datastore.." storage ('"..ret.."') for user: "..(username or "nil").."@"..(host or "nil"));
- return nil;
+ local mode = lfs.attributes(getpath(username, host, datastore), "mode");
+ if not mode then
+ log("debug", "Failed to load "..datastore.." storage ('"..ret.."') for user: "..(username or "nil").."@"..(host or "nil"));
+ return nil;
+ else -- file exists, but can't be read
+ -- TODO more detailed error checking and logging?
+ log("error", "Failed to load "..datastore.." storage ('"..ret.."') for user: "..(username or "nil").."@"..(host or "nil"));
+ return nil, "Error reading storage";
+ end
end
setfenv(data, {});
local success, ret = pcall(data);
if not success then
log("error", "Unable to load "..datastore.." storage ('"..ret.."') for user: "..(username or "nil").."@"..(host or "nil"));
- return nil;
+ return nil, "Error reading storage";
end
return ret;
end
@@ -137,7 +145,7 @@ function store(username, host, datastore, data)
local f, msg = io_open(getpath(username, host, datastore, nil, true), "w+");
if not f then
log("error", "Unable to write to "..datastore.." storage ('"..msg.."') for user: "..(username or "nil").."@"..(host or "nil"));
- return;
+ return nil, "Error saving to storage";
end
f:write("return ");
append(f, data);
diff --git a/util/sasl/scram.lua b/util/sasl/scram.lua
index 47e8e7b3..6040c402 100644
--- a/util/sasl/scram.lua
+++ b/util/sasl/scram.lua
@@ -212,4 +212,4 @@ function init(registerMechanism)
registerSCRAMMechanism("SHA-1", sha1, hmac_sha1);
end
-return _M; \ No newline at end of file
+return _M;