aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKim Alvefur <zash@zash.se>2017-08-28 21:05:12 +0200
committerKim Alvefur <zash@zash.se>2017-08-28 21:05:12 +0200
commit516230f98836464640e9f98cac0e6346ada521ec (patch)
treef7cb8e26a9d516e5cae70dbf374ec06c09254f0b
parent30eb28a6f684a0c2beaa99cab409783183855c5a (diff)
parentf79cc1a386d0fce8f1c274ff7217087cc5e87415 (diff)
downloadprosody-im-server-516230f98836464640e9f98cac0e6346ada521ec.tar
prosody-im-server-516230f98836464640e9f98cac0e6346ada521ec.zip
Merge 0.10->trunk
-rw-r--r--core/usermanager.lua8
-rw-r--r--net/http.lua30
-rw-r--r--net/websocket.lua2
-rw-r--r--plugins/mod_admin_adhoc.lua2
-rw-r--r--plugins/mod_admin_telnet.lua2
-rw-r--r--plugins/mod_auth_internal_hashed.lua4
-rw-r--r--plugins/mod_c2s.lua12
-rw-r--r--plugins/mod_disco.lua2
-rw-r--r--plugins/mod_mam/mod_mam.lua37
-rw-r--r--plugins/mod_register.lua4
-rwxr-xr-xprosody6
-rwxr-xr-xprosodyctl16
-rw-r--r--util/sql.lua6
13 files changed, 103 insertions, 28 deletions
diff --git a/core/usermanager.lua b/core/usermanager.lua
index d5132662..f795e8ae 100644
--- a/core/usermanager.lua
+++ b/core/usermanager.lua
@@ -76,8 +76,12 @@ local function get_password(username, host)
return hosts[host].users.get_password(username);
end
-local function set_password(username, password, host)
- return hosts[host].users.set_password(username, password);
+local function set_password(username, password, host, resource)
+ local ok, err = hosts[host].users.set_password(username, password);
+ if ok then
+ prosody.events.fire_event("user-password-changed", { username = username, host = host, resource = resource });
+ end
+ return ok, err;
end
local function user_exists(username, host)
diff --git a/net/http.lua b/net/http.lua
index d820e471..8364a104 100644
--- a/net/http.lua
+++ b/net/http.lua
@@ -11,6 +11,7 @@ local url = require "socket.url"
local httpstream_new = require "net.http.parser".new;
local util_http = require "util.http";
local events = require "util.events";
+local verify_identity = require"util.x509".verify_identity;
local ssl_available = pcall(require, "ssl");
@@ -34,6 +35,26 @@ local listener = { default_port = 80, default_mode = "*a" };
function listener.onconnect(conn)
local req = requests[conn];
+
+ -- Validate certificate
+ if not req.insecure and conn:ssl() then
+ local sock = conn:socket();
+ local chain_valid = sock.getpeerverification and sock:getpeerverification();
+ if not chain_valid then
+ req.callback("certificate-chain-invalid", 0, req);
+ req.callback = nil;
+ conn:close();
+ return;
+ end
+ local cert = sock.getpeercertificate and sock:getpeercertificate();
+ if not cert or not verify_identity(req.host, false, cert) then
+ req.callback("certificate-verify-failed", 0, req);
+ req.callback = nil;
+ conn:close();
+ return;
+ end
+ end
+
-- Send the request
local request_line = { req.method or "GET", " ", req.path, " HTTP/1.1\r\n" };
if req.query then
@@ -181,6 +202,7 @@ local function request(self, u, ex, callback)
headers[k] = v;
end
end
+ req.insecure = ex.insecure;
end
log("debug", "Making %s %s request '%s' to %s", req.scheme:upper(), method or "GET", req.id, (ex and ex.suppress_url and host_header) or u);
@@ -196,7 +218,7 @@ local function request(self, u, ex, callback)
local sslctx = false;
if using_https then
- sslctx = ex and ex.sslctx or { mode = "client", protocol = "sslv23", options = { "no_sslv2", "no_sslv3" } };
+ sslctx = ex and ex.sslctx or self.options and self.options.sslctx;
end
local handler, conn = server.addclient(host, port_number, listener, "*a", sslctx)
@@ -235,17 +257,19 @@ local function new(options)
return new(setmetatable(new_options, { __index = options }));
end or new;
events = events.new();
- request = request;
};
return http;
end
-local default_http = new();
+local default_http = new({
+ sslctx = { mode = "client", protocol = "sslv23", options = { "no_sslv2", "no_sslv3" } };
+});
return {
request = function (u, ex, callback)
return default_http:request(u, ex, callback);
end;
+ default = default_http;
new = new;
events = default_http.events;
-- COMPAT
diff --git a/net/websocket.lua b/net/websocket.lua
index 373210d6..777b894c 100644
--- a/net/websocket.lua
+++ b/net/websocket.lua
@@ -38,7 +38,7 @@ function websocket_listeners.ondetach(handler)
end
local function fail(s, code, reason)
- module:log("warn", "WebSocket connection failed, closing. %d %s", code, reason);
+ log("warn", "WebSocket connection failed, closing. %d %s", code, reason);
s:close(code, reason);
s.handler:close();
return false
diff --git a/plugins/mod_admin_adhoc.lua b/plugins/mod_admin_adhoc.lua
index 392e715e..f3de6793 100644
--- a/plugins/mod_admin_adhoc.lua
+++ b/plugins/mod_admin_adhoc.lua
@@ -97,7 +97,7 @@ local change_user_password_command_handler = adhoc_simple(change_user_password_l
if module_host ~= host then
return { status = "completed", error = { message = "Trying to change the password of a user on " .. host .. " but command was sent to " .. module_host}};
end
- if usermanager_user_exists(username, host) and usermanager_set_password(username, fields.password, host) then
+ if usermanager_user_exists(username, host) and usermanager_set_password(username, fields.password, host, nil) then
return { status = "completed", info = "Password successfully changed" };
else
return { status = "completed", error = { message = "User does not exist" } };
diff --git a/plugins/mod_admin_telnet.lua b/plugins/mod_admin_telnet.lua
index eae72e61..b3a5c7ca 100644
--- a/plugins/mod_admin_telnet.lua
+++ b/plugins/mod_admin_telnet.lua
@@ -1067,7 +1067,7 @@ function def_env.user:password(jid, password)
elseif not um.user_exists(username, host) then
return nil, "No such user";
end
- local ok, err = um.set_password(username, password, host);
+ local ok, err = um.set_password(username, password, host, nil);
if ok then
return true, "User password changed";
else
diff --git a/plugins/mod_auth_internal_hashed.lua b/plugins/mod_auth_internal_hashed.lua
index 53e345e5..35764afb 100644
--- a/plugins/mod_auth_internal_hashed.lua
+++ b/plugins/mod_auth_internal_hashed.lua
@@ -120,7 +120,9 @@ function provider.get_sasl_handler()
local credentials = accounts:get(username);
if not credentials then return; end
if credentials.password then
- usermanager.set_password(username, credentials.password, host);
+ if provider.set_password(username, credentials.password) == nil then
+ return nil, "Auth failed. Could not set hashed password from plaintext.";
+ end
credentials = accounts:get(username);
if not credentials then return; end
end
diff --git a/plugins/mod_c2s.lua b/plugins/mod_c2s.lua
index f18c2827..3547fe31 100644
--- a/plugins/mod_c2s.lua
+++ b/plugins/mod_c2s.lua
@@ -201,6 +201,18 @@ module:hook_global("user-deleted", function(event)
end
end, 200);
+module:hook_global("user-password-changed", function(event)
+ local username, host, resource = event.username, event.host, event.resource;
+ local user = hosts[host].sessions[username];
+ if user and user.sessions then
+ for r, session in pairs(user.sessions) do
+ if r ~= resource then
+ session:close{ condition = "reset", text = "Password changed" };
+ end
+ end
+ end
+end, 200);
+
function runner_callbacks:ready()
self.data.conn:resume();
end
diff --git a/plugins/mod_disco.lua b/plugins/mod_disco.lua
index 10eb632d..cd07934f 100644
--- a/plugins/mod_disco.lua
+++ b/plugins/mod_disco.lua
@@ -148,7 +148,7 @@ end);
-- Handle caps stream feature
module:hook("stream-features", function (event)
- if event.origin.type == "c2s" or event.origin.type == "c2s_unauthed" then
+ if event.origin.type == "c2s" or event.origin.type == "c2s_unbound" then
event.features:add_child(get_server_caps_feature());
end
end);
diff --git a/plugins/mod_mam/mod_mam.lua b/plugins/mod_mam/mod_mam.lua
index 1dcce4e4..a86697e8 100644
--- a/plugins/mod_mam/mod_mam.lua
+++ b/plugins/mod_mam/mod_mam.lua
@@ -243,15 +243,19 @@ local function message_handler(event, c2s)
local with = jid_bare(c2s and orig_to or orig_from);
-- Filter out <stanza-id> that claim to be from us
- stanza:maptags(function (tag)
- if tag.name == "stanza-id" and tag.attr.xmlns == xmlns_st_id then
- local by_user, by_host, res = jid_prepped_split(tag.attr.by);
- if not res and by_host == module.host and by_user == store_user then
- return nil;
+ if stanza:get_child("stanza-id", xmlns_st_id) then
+ stanza = st.clone(stanza);
+ stanza:maptags(function (tag)
+ if tag.name == "stanza-id" and tag.attr.xmlns == xmlns_st_id then
+ local by_user, by_host, res = jid_prepped_split(tag.attr.by);
+ if not res and by_host == module.host and by_user == store_user then
+ return nil;
+ end
end
- end
- return tag;
- end);
+ return tag;
+ end);
+ event.stanza = stanza;
+ end
-- We store chat messages or normal messages that have a body
if not(orig_type == "chat" or (orig_type == "normal" and stanza:get_child("body")) ) then
@@ -268,18 +272,21 @@ local function message_handler(event, c2s)
end
end
+ local clone_for_storage;
if not strip_tags:empty() then
- stanza = st.clone(stanza);
- stanza:maptags(function (tag)
+ clone_for_storage = st.clone(stanza);
+ clone_for_storage:maptags(function (tag)
if strip_tags:contains(tag.attr.xmlns) then
return nil;
else
return tag;
end
end);
- if #stanza.tags == 0 then
+ if #clone_for_storage.tags == 0 then
return;
end
+ else
+ clone_for_storage = stanza;
end
-- Check with the users preferences
@@ -287,12 +294,14 @@ local function message_handler(event, c2s)
log("debug", "Archiving stanza: %s", stanza:top_tag());
-- And stash it
- local ok = archive:append(store_user, nil, stanza, time_now(), with);
+ local ok = archive:append(store_user, nil, clone_for_storage, time_now(), with);
if ok then
+ local clone_for_other_handlers = st.clone(stanza);
local id = ok;
- event.stanza:tag("stanza-id", { xmlns = xmlns_st_id, by = store_user.."@"..host, id = id }):up();
+ clone_for_other_handlers:tag("stanza-id", { xmlns = xmlns_st_id, by = store_user.."@"..host, id = id }):up();
+ event.stanza = clone_for_other_handlers;
if cleanup then cleanup[store_user] = true; end
- module:fire_event("archive-message-added", { origin = origin, stanza = stanza, for_user = store_user, id = id });
+ module:fire_event("archive-message-added", { origin = origin, stanza = clone_for_storage, for_user = store_user, id = id });
end
else
log("debug", "Not archiving stanza: %s (prefs)", stanza:top_tag());
diff --git a/plugins/mod_register.lua b/plugins/mod_register.lua
index fd5339d9..b39ce090 100644
--- a/plugins/mod_register.lua
+++ b/plugins/mod_register.lua
@@ -91,6 +91,7 @@ module:hook("stream-features", function(event)
features:add_child(register_stream_feature);
end);
+-- Password change and account deletion handler
local function handle_registration_stanza(event)
local session, stanza = event.origin, event.stanza;
local log = session.log or module._log;
@@ -130,7 +131,7 @@ local function handle_registration_stanza(event)
local password = query:get_child_text("password");
if username and password then
if username == session.username then
- if usermanager_set_password(username, password, session.host) then
+ if usermanager_set_password(username, password, session.host, session.resource) then
session.send(st.reply(stanza));
else
-- TODO unable to write file, file may be locked, etc, what's the correct error?
@@ -207,6 +208,7 @@ local function check_throttle(ip)
return throttle:poll(1);
end
+-- In-band registration
module:hook("stanza/iq/jabber:iq:register:query", function(event)
local session, stanza = event.origin, event.stanza;
local log = session.log or module._log;
diff --git a/prosody b/prosody
index 7f6b1c2d..cc879f12 100755
--- a/prosody
+++ b/prosody
@@ -321,7 +321,11 @@ function load_secondary_libraries()
return function() end
end});
- require "net.http"
+ local http = require "net.http"
+ local config_ssl = config.get("*", "ssl")
+ local https_client = config.get("*", "client_https_ssl")
+ http.default.options.sslctx = require "core.certmanager".create_context("client_https port 0", "client",
+ { capath = config_ssl.capath, cafile = config_ssl.cafile, verify = "peer", }, https_client);
require "util.array"
require "util.datetime"
diff --git a/prosodyctl b/prosodyctl
index d1634c32..53399407 100755
--- a/prosodyctl
+++ b/prosodyctl
@@ -249,6 +249,13 @@ local modulemanager = require "core.modulemanager"
local prosodyctl = require "util.prosodyctl"
local socket = require "socket"
+
+local http = require "net.http"
+local config_ssl = config.get("*", "ssl")
+local https_client = config.get("*", "client_https_ssl")
+http.default.options.sslctx = require "core.certmanager".create_context("client_https port 0", "client",
+ { capath = config_ssl.capath, cafile = config_ssl.cafile, verify = "peer", }, https_client);
+
-----------------------
-- FIXME: Duplicate code waiting for util.startup
@@ -1334,7 +1341,14 @@ function commands.check(arg)
print("This version of LuaSec (" .. ssl._VERSION .. ") does not support certificate checking");
cert_ok = false
else
- for host in enabled_hosts() do
+ local function skip_bare_jid_hosts(host)
+ if jid_split(host) then
+ -- See issue #779
+ return false;
+ end
+ return true;
+ end
+ for host in it.filter(skip_bare_jid_hosts, enabled_hosts()) do
print("Checking certificate for "..host);
-- First, let's find out what certificate this host uses.
local host_ssl_config = config.rawget(host, "ssl")
diff --git a/util/sql.lua b/util/sql.lua
index 15749911..61d6af41 100644
--- a/util/sql.lua
+++ b/util/sql.lua
@@ -175,7 +175,11 @@ function engine:execute_query(sql, ...)
sql = self:prepquery(sql);
local stmt = assert(self.conn:prepare(sql));
assert(stmt:execute(...));
- return stmt:rows();
+ local result = {};
+ for row in stmt:rows() do result[#result + 1] = row; end
+ stmt:close();
+ local i = 0;
+ return function() i=i+1; return result[i]; end;
end
function engine:execute_update(sql, ...)
sql = self:prepquery(sql);