12 local type = type; |
12 local type = type; |
13 local error = error; |
13 local error = error; |
14 local ipairs = ipairs; |
14 local ipairs = ipairs; |
15 local hashes = require "util.hashes"; |
15 local hashes = require "util.hashes"; |
16 local jid_bare = require "util.jid".bare; |
16 local jid_bare = require "util.jid".bare; |
17 local saltedPasswordSHA1 = require "util.sasl.scram".saltedPasswordSHA1; |
17 local getAuthenticationDatabaseSHA1 = require "util.sasl.scram".getAuthenticationDatabaseSHA1; |
18 local config = require "core.configmanager"; |
18 local config = require "core.configmanager"; |
19 local usermanager = require "core.usermanager"; |
19 local usermanager = require "core.usermanager"; |
20 local generate_uuid = require "util.uuid".generate; |
20 local generate_uuid = require "util.uuid".generate; |
21 local new_sasl = require "util.sasl".new; |
21 local new_sasl = require "util.sasl".new; |
22 local nodeprep = require "util.encodings".stringprep.nodeprep; |
22 local nodeprep = require "util.encodings".stringprep.nodeprep; |
50 end |
50 end |
51 |
51 |
52 if credentials.iteration_count == nil or credentials.salt == nil or string.len(credentials.salt) == 0 then |
52 if credentials.iteration_count == nil or credentials.salt == nil or string.len(credentials.salt) == 0 then |
53 return nil, "Auth failed. Stored salt and iteration count information is not complete."; |
53 return nil, "Auth failed. Stored salt and iteration count information is not complete."; |
54 end |
54 end |
55 |
55 |
56 local valid, binpass = saltedPasswordSHA1(password, credentials.salt, credentials.iteration_count); |
56 local valid, stored_key, server_key = getAuthenticationDatabaseSHA1(password, credentials.salt, credentials.iteration_count); |
57 local hexpass = binpass:gsub(".", function (c) return ("%02x"):format(c:byte()); end); |
57 local stored_key_hex = stored_key:gsub(".", function (c) return ("%02x"):format(c:byte()); end); |
58 |
58 local server_key_hex = server_key:gsub(".", function (c) return ("%02x"):format(c:byte()); end); |
59 if valid and hexpass == credentials.hashpass then |
59 |
|
60 if valid and stored_key_hex == credentials.stored_key and server_key_hex == credentials.server_key_hex then |
60 return true; |
61 return true; |
61 else |
62 else |
62 return nil, "Auth failed. Invalid username, password, or password hash information."; |
63 return nil, "Auth failed. Invalid username, password, or password hash information."; |
63 end |
64 end |
64 end |
65 end |
100 end |
101 end |
101 |
102 |
102 function provider.create_user(username, password) |
103 function provider.create_user(username, password) |
103 if is_cyrus(host) then return nil, "Account creation/modification not available with Cyrus SASL."; end |
104 if is_cyrus(host) then return nil, "Account creation/modification not available with Cyrus SASL."; end |
104 local salt = generate_uuid(); |
105 local salt = generate_uuid(); |
105 local valid, binpass = saltedPasswordSHA1(password, salt, iteration_count); |
106 local valid, stored_key, server_key = saltedPasswordSHA1(password, salt, iteration_count); |
106 local hexpass = binpass:gsub(".", function (c) return ("%02x"):format(c:byte()); end); |
107 local stored_key_hex = stored_key:gsub(".", function (c) return ("%02x"):format(c:byte()); end); |
107 return datamanager.store(username, host, "accounts", {hashpass = hexpass, salt = salt, iteration_count = iteration_count}); |
108 local server_key_hex = server_key:gsub(".", function (c) return ("%02x"):format(c:byte()); end); |
|
109 return datamanager.store(username, host, "accounts", {stored_key = stored_key_hex, server_key = server_key_hex, salt = salt, iteration_count = iteration_count}); |
108 end |
110 end |
109 |
111 |
110 function provider.get_sasl_handler() |
112 function provider.get_sasl_handler() |
111 local realm = module:get_option("sasl_realm") or module.host; |
113 local realm = module:get_option("sasl_realm") or module.host; |
112 local testpass_authentication_profile = { |
114 local testpass_authentication_profile = { |
122 local credentials = datamanager.load(username, host, "accounts") or {}; |
124 local credentials = datamanager.load(username, host, "accounts") or {}; |
123 if credentials.password then |
125 if credentials.password then |
124 usermanager.set_password(username, credentials.password); |
126 usermanager.set_password(username, credentials.password); |
125 credentials = datamanager.load(username, host, "accounts") or {}; |
127 credentials = datamanager.load(username, host, "accounts") or {}; |
126 end |
128 end |
127 local salted_password, iteration_count, salt = credentials.hashpass, credentials.iteration_count, credentials.salt; |
129 local stored_key, server_key, iteration_count, salt = credentials.stored_key, credentials.server_key, credentials.iteration_count, credentials.salt; |
128 salted_password = salted_password and salted_password:gsub("..", function(x) return string.char(tonumber(x, 16)); end); |
130 stored_key = stored_key and stored_key:gsub("..", function(x) return string.char(tonumber(x, 16)); end); |
129 return salted_password, iteration_count, salt, true; |
131 server_key = server_key and server_key:gsub("..", function(x) return string.char(tonumber(x, 16)); end); |
|
132 return stored_key, server_key, iteration_count, salt, true; |
130 end |
133 end |
131 }; |
134 }; |
132 return new_sasl(realm, testpass_authentication_profile); |
135 return new_sasl(realm, testpass_authentication_profile); |
133 end |
136 end |
134 |
137 |