plugins/mod_auth_internal_hashed.lua

changeset 3214
a69d8021b1db
parent 3204
7a15cbf23c5b
parent 3213
c85bba8bd41a
child 3216
d4d0519cd0c1
equal deleted inserted replaced
3204:7a15cbf23c5b 3214:a69d8021b1db
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;
23 local hosts = hosts; 23 local hosts = hosts;
24
25 -- TODO: remove these two lines in near future
26 local hmac_sha1 = require "util.hmac".sha1;
27 local sha1 = require "util.hashes".sha1;
24 28
25 local prosody = _G.prosody; 29 local prosody = _G.prosody;
26 30
27 local is_cyrus = usermanager.is_cyrus; 31 local is_cyrus = usermanager.is_cyrus;
28 32
50 end 54 end
51 55
52 if credentials.iteration_count == nil or credentials.salt == nil or string.len(credentials.salt) == 0 then 56 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."; 57 return nil, "Auth failed. Stored salt and iteration count information is not complete.";
54 end 58 end
55 59
56 local valid, binpass = saltedPasswordSHA1(password, credentials.salt, credentials.iteration_count); 60 local valid, stored_key, server_key
57 local hexpass = binpass:gsub(".", function (c) return ("%02x"):format(c:byte()); end); 61
58 62 -- convert hexpass to stored_key and server_key
59 if valid and hexpass == credentials.hashpass then 63 -- TODO: remove this in near future
64 if credentials.hashpass then
65 valid = true;
66 local salted_password = credentials.hashpass:gsub("..", function(x) return string.char(tonumber(x, 16)); end);
67 credentials.stored_key = sha1(hmac_sha1(salted_password, "Client Key")):gsub(".", function (c) return ("%02x"):format(c:byte()); end);
68 credentials.server_key = hmac_sha1(salted_password, "Server Key"):gsub(".", function (c) return ("%02x"):format(c:byte()); end);
69 credentials.hashpass = nil
70 datamanager.store(username, host, "accounts", credentials);
71 end
72
73 local valid, stored_key, server_key = getAuthenticationDatabaseSHA1(password, credentials.salt, credentials.iteration_count);
74
75 local stored_key_hex = stored_key:gsub(".", function (c) return ("%02x"):format(c:byte()); end);
76 local server_key_hex = server_key:gsub(".", function (c) return ("%02x"):format(c:byte()); end);
77
78 if valid and stored_key_hex == credentials.stored_key and server_key_hex == credentials.server_key then
60 return true; 79 return true;
61 else 80 else
62 return nil, "Auth failed. Invalid username, password, or password hash information."; 81 return nil, "Auth failed. Invalid username, password, or password hash information.";
63 end 82 end
64 end 83 end
65 84
66 function provider.set_password(username, password) 85 function provider.set_password(username, password)
67 if is_cyrus(host) then return nil, "Passwords unavailable for Cyrus SASL."; end 86 if is_cyrus(host) then return nil, "Passwords unavailable for Cyrus SASL."; end
68 local account = datamanager.load(username, host, "accounts"); 87 local account = datamanager.load(username, host, "accounts");
69 if account then 88 if account then
70 if account.iteration_count == nil then 89 account.salt = account.salt or generate_uuid();
71 account.iteration_count = iteration_count; 90 account.iteration_count = account.iteration_count or iteration_count;
72 end 91 local valid, stored_key, server_key = getAuthenticationDatabaseSHA1(password, account.salt, account.iteration_count);
73 92 local stored_key_hex = stored_key:gsub(".", function (c) return ("%02x"):format(c:byte()); end);
74 if account.salt == nil then 93 local server_key_hex = server_key:gsub(".", function (c) return ("%02x"):format(c:byte()); end);
75 account.salt = generate_uuid(); 94
76 end 95 account.stored_key = stored_key_hex
77 96 account.server_key = server_key_hex
78 local valid, binpass = saltedPasswordSHA1(password, account.salt, account.iteration_count);
79 local hexpass = binpass:gsub(".", function (c) return ("%02x"):format(c:byte()); end);
80 account.hashpass = hexpass;
81 97
82 account.password = nil; 98 account.password = nil;
83 return datamanager.store(username, host, "accounts", account); 99 return datamanager.store(username, host, "accounts", account);
84 end 100 end
85 return nil, "Account not available."; 101 return nil, "Account not available.";
100 end 116 end
101 117
102 function provider.create_user(username, password) 118 function provider.create_user(username, password)
103 if is_cyrus(host) then return nil, "Account creation/modification not available with Cyrus SASL."; end 119 if is_cyrus(host) then return nil, "Account creation/modification not available with Cyrus SASL."; end
104 local salt = generate_uuid(); 120 local salt = generate_uuid();
105 local valid, binpass = saltedPasswordSHA1(password, salt, iteration_count); 121 local valid, stored_key, server_key = saltedPasswordSHA1(password, salt, iteration_count);
106 local hexpass = binpass:gsub(".", function (c) return ("%02x"):format(c:byte()); end); 122 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}); 123 local server_key_hex = server_key:gsub(".", function (c) return ("%02x"):format(c:byte()); end);
124 return datamanager.store(username, host, "accounts", {stored_key = stored_key_hex, server_key = server_key_hex, salt = salt, iteration_count = iteration_count});
108 end 125 end
109 126
110 function provider.get_sasl_handler() 127 function provider.get_sasl_handler()
111 local realm = module:get_option("sasl_realm") or module.host; 128 local realm = module:get_option("sasl_realm") or module.host;
112 local testpass_authentication_profile = { 129 local testpass_authentication_profile = {
122 local credentials = datamanager.load(username, host, "accounts") or {}; 139 local credentials = datamanager.load(username, host, "accounts") or {};
123 if credentials.password then 140 if credentials.password then
124 usermanager.set_password(username, credentials.password, host); 141 usermanager.set_password(username, credentials.password, host);
125 credentials = datamanager.load(username, host, "accounts") or {}; 142 credentials = datamanager.load(username, host, "accounts") or {};
126 end 143 end
127 local salted_password, iteration_count, salt = credentials.hashpass, credentials.iteration_count, credentials.salt; 144
128 salted_password = salted_password and salted_password:gsub("..", function(x) return string.char(tonumber(x, 16)); end); 145 -- convert hexpass to stored_key and server_key
129 return salted_password, iteration_count, salt, true; 146 -- TODO: remove this in near future
147 if credentials.hashpass then
148 local salted_password = credentials.hashpass:gsub("..", function(x) return string.char(tonumber(x, 16)); end);
149 credentials.stored_key = sha1(hmac_sha1(salted_password, "Client Key")):gsub(".", function (c) return ("%02x"):format(c:byte()); end);
150 credentials.server_key = hmac_sha1(salted_password, "Server Key"):gsub(".", function (c) return ("%02x"):format(c:byte()); end);
151 credentials.hashpass = nil
152 datamanager.store(username, host, "accounts", credentials);
153 end
154
155 local stored_key, server_key, iteration_count, salt = credentials.stored_key, credentials.server_key, credentials.iteration_count, credentials.salt;
156 stored_key = stored_key and stored_key:gsub("..", function(x) return string.char(tonumber(x, 16)); end);
157 server_key = server_key and server_key:gsub("..", function(x) return string.char(tonumber(x, 16)); end);
158 return stored_key, server_key, iteration_count, salt, true;
130 end 159 end
131 }; 160 };
132 return new_sasl(realm, testpass_authentication_profile); 161 return new_sasl(realm, testpass_authentication_profile);
133 end 162 end
134 163

mercurial