local sm_bind_resource = require "core.sessionmanager".bind_resource;
local sm_make_authenticated = require "core.sessionmanager".make_authenticated;
local base64 = require "util.encodings".base64;
+
+ local nodeprep = require "util.encodings".stringprep.nodeprep;
local datamanager_load = require "util.datamanager".load;
local usermanager_validate_credentials = require "core.usermanager".validate_credentials;
+local usermanager_get_supported_methods = require "core.usermanager".get_supported_methods;
+local usermanager_user_exists = require "core.usermanager".user_exists;
+local usermanager_get_password = require "core.usermanager".get_password;
local t_concat, t_insert = table.concat, table.insert;
local tostring = tostring;
local jid_split = require "util.jid".split
end
end
-local function password_callback(node, hostname, realm, mechanism, decoder)
- local func = function(x) return x; end;
- local node = nodeprep(node);
- if not node then
- return func, nil;
- end
- local password = (datamanager_load(node, hostname, "accounts") or {}).password; -- FIXME handle hashed passwords
- if password then
- if mechanism == "PLAIN" then
- return func, password;
- elseif mechanism == "DIGEST-MD5" then
- if decoder then node, realm, password = decoder(node), decoder(realm), decoder(password); end
+local function credentials_callback(mechanism, ...)
+ if mechanism == "PLAIN" then
+ local username, hostname, password = ...;
++ username = nodeprep(username);
++ if not username then
++ return false;
++ end
+ local response = usermanager_validate_credentials(hostname, username, password, mechanism);
+ if response == nil then
+ return false;
+ else
+ return response;
+ end
+ elseif mechanism == "DIGEST-MD5" then
+ function func(x) return x; end
+ local node, domain, realm, decoder = ...;
+ local password = usermanager_get_password(node, domain);
+ if password then
+ if decoder then
+ node, realm, password = decoder(node), decoder(realm), decoder(password);
+ end
return func, md5(node..":"..realm..":"..password);
+ else
+ return func, nil;
end
end
- return func, nil;
end
local function sasl_handler(session, stanza)
module "sasl"
-local function new_plain(realm, password_handler)
- local object = { mechanism = "PLAIN", realm = realm, password_handler = password_handler}
+-- Credentials handler:
+-- Arguments: ("PLAIN", user, host, password)
+-- Returns: true (success) | false (fail) | nil (user unknown)
+local function new_plain(realm, credentials_handler)
+ local object = { mechanism = "PLAIN", realm = realm, credentials_handler = credentials_handler}
function object.feed(self, message)
-
if message == "" or message == nil then return "failure", "malformed-request" end
local response = message
- local authorization = s_match(response, "([^&%z]+)")
- local authentication = s_match(response, "%z([^&%z]+)%z")
- local password = s_match(response, "%z[^&%z]+%z([^&%z]+)")
+ local authorization = s_match(response, "([^%z]+)")
+ local authentication = s_match(response, "%z([^%z]+)%z")
+ local password = s_match(response, "%z[^%z]+%z([^%z]+)")
- authorization, authentication, password = saslprep(authorization), saslprep(authentication), saslprep(password);
-
- if authentication == nil or password == nil then return "failure", "malformed-request" end
-
- local password_encoding, correct_password = self.password_handler(authentication, self.realm, self.realm, "PLAIN")
-
- if correct_password == nil then return "failure", "not-authorized"
- elseif correct_password == false then return "failure", "account-disabled" end
-
- local claimed_password = ""
- if password_encoding == nil then claimed_password = password
- else claimed_password = password_encoding(password) end
- claimed_password = saslprep(claimed_password);
-
- self.username = authentication
- if claimed_password == correct_password then
- return "success"
- else
- return "failure", "not-authorized"
- end
- end
- return object
-end
+ if authentication == nil or password == nil then return "failure", "malformed-request" end
+ self.username = authentication
+ local auth_success = self.credentials_handler("PLAIN", self.username, self.realm, password)
+
+ if auth_success then
+ return "success"
+ elseif auth_success == nil then
+ return "failure", "account-disabled"
+ else
+ return "failure", "not-authorized"
+ end
+ end
+ return object
+end
+-- credentials_handler:
+-- Arguments: (mechanism, node, domain, realm, decoder)
+-- Returns: Password encoding, (plaintext) password
-- implementing RFC 2831
-local function new_digest_md5(realm, password_handler)
+local function new_digest_md5(realm, credentials_handler)
--TODO complete support for authzid
local function serialize(message)