Software /
code /
prosody
Comparison
plugins/mod_auth_internal_hashed.lua @ 10218:e458578ddfd3
mod_auth_internal_hashed: Add support for optionally using SCRAM-SHA-256 instead of SHA-1
This will currently require a hard reset of all passwords back to plain.
This will be least painful on new deployments.
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Sun, 13 Jan 2019 14:02:56 +0100 |
parent | 8192:4354f556c5db |
child | 10219:d58925bb74ca |
comparison
equal
deleted
inserted
replaced
10217:60b445183d84 | 10218:e458578ddfd3 |
---|---|
7 -- COPYING file in the source package for more information. | 7 -- COPYING file in the source package for more information. |
8 -- | 8 -- |
9 | 9 |
10 local max = math.max; | 10 local max = math.max; |
11 | 11 |
12 local getAuthenticationDatabaseSHA1 = require "util.sasl.scram".getAuthenticationDatabaseSHA1; | 12 local scram_hashers = require "util.sasl.scram".hashers; |
13 local usermanager = require "core.usermanager"; | 13 local usermanager = require "core.usermanager"; |
14 local generate_uuid = require "util.uuid".generate; | 14 local generate_uuid = require "util.uuid".generate; |
15 local new_sasl = require "util.sasl".new; | 15 local new_sasl = require "util.sasl".new; |
16 local hex = require"util.hex"; | 16 local hex = require"util.hex"; |
17 local to_hex, from_hex = hex.to, hex.from; | 17 local to_hex, from_hex = hex.to, hex.from; |
19 local log = module._log; | 19 local log = module._log; |
20 local host = module.host; | 20 local host = module.host; |
21 | 21 |
22 local accounts = module:open_store("accounts"); | 22 local accounts = module:open_store("accounts"); |
23 | 23 |
24 | 24 local hash_name = module:get_option_string("password_hash", "SHA-1"); |
25 local get_auth_db = assert(scram_hashers[hash_name], "SCRAM-"..hash_name.." not supported by SASL library"); | |
25 | 26 |
26 -- Default; can be set per-user | 27 -- Default; can be set per-user |
27 local default_iteration_count = 4096; | 28 local default_iteration_count = 4096; |
28 | 29 |
29 -- define auth provider | 30 -- define auth provider |
47 | 48 |
48 if credentials.iteration_count == nil or credentials.salt == nil or string.len(credentials.salt) == 0 then | 49 if credentials.iteration_count == nil or credentials.salt == nil or string.len(credentials.salt) == 0 then |
49 return nil, "Auth failed. Stored salt and iteration count information is not complete."; | 50 return nil, "Auth failed. Stored salt and iteration count information is not complete."; |
50 end | 51 end |
51 | 52 |
52 local valid, stored_key, server_key = getAuthenticationDatabaseSHA1(password, credentials.salt, credentials.iteration_count); | 53 local valid, stored_key, server_key = get_auth_db(password, credentials.salt, credentials.iteration_count); |
53 | 54 |
54 local stored_key_hex = to_hex(stored_key); | 55 local stored_key_hex = to_hex(stored_key); |
55 local server_key_hex = to_hex(server_key); | 56 local server_key_hex = to_hex(server_key); |
56 | 57 |
57 if valid and stored_key_hex == credentials.stored_key and server_key_hex == credentials.server_key then | 58 if valid and stored_key_hex == credentials.stored_key and server_key_hex == credentials.server_key then |
65 log("debug", "set_password for username '%s'", username); | 66 log("debug", "set_password for username '%s'", username); |
66 local account = accounts:get(username); | 67 local account = accounts:get(username); |
67 if account then | 68 if account then |
68 account.salt = generate_uuid(); | 69 account.salt = generate_uuid(); |
69 account.iteration_count = max(account.iteration_count or 0, default_iteration_count); | 70 account.iteration_count = max(account.iteration_count or 0, default_iteration_count); |
70 local valid, stored_key, server_key = getAuthenticationDatabaseSHA1(password, account.salt, account.iteration_count); | 71 local valid, stored_key, server_key = get_auth_db(password, account.salt, account.iteration_count); |
71 local stored_key_hex = to_hex(stored_key); | 72 local stored_key_hex = to_hex(stored_key); |
72 local server_key_hex = to_hex(server_key); | 73 local server_key_hex = to_hex(server_key); |
73 | 74 |
74 account.stored_key = stored_key_hex | 75 account.stored_key = stored_key_hex |
75 account.server_key = server_key_hex | 76 account.server_key = server_key_hex |
96 function provider.create_user(username, password) | 97 function provider.create_user(username, password) |
97 if password == nil then | 98 if password == nil then |
98 return accounts:set(username, {}); | 99 return accounts:set(username, {}); |
99 end | 100 end |
100 local salt = generate_uuid(); | 101 local salt = generate_uuid(); |
101 local valid, stored_key, server_key = getAuthenticationDatabaseSHA1(password, salt, default_iteration_count); | 102 local valid, stored_key, server_key = get_auth_db(password, salt, default_iteration_count); |
102 local stored_key_hex = to_hex(stored_key); | 103 local stored_key_hex = to_hex(stored_key); |
103 local server_key_hex = to_hex(server_key); | 104 local server_key_hex = to_hex(server_key); |
104 return accounts:set(username, { | 105 return accounts:set(username, { |
105 stored_key = stored_key_hex, server_key = server_key_hex, | 106 stored_key = stored_key_hex, server_key = server_key_hex, |
106 salt = salt, iteration_count = default_iteration_count | 107 salt = salt, iteration_count = default_iteration_count |
114 function provider.get_sasl_handler() | 115 function provider.get_sasl_handler() |
115 local testpass_authentication_profile = { | 116 local testpass_authentication_profile = { |
116 plain_test = function(_, username, password, realm) | 117 plain_test = function(_, username, password, realm) |
117 return usermanager.test_password(username, realm, password), true; | 118 return usermanager.test_password(username, realm, password), true; |
118 end, | 119 end, |
119 scram_sha_1 = function(_, username) | 120 ["scram_"..hash_name:gsub("%-","_"):lower()] = function(_, username) |
120 local credentials = accounts:get(username); | 121 local credentials = accounts:get(username); |
121 if not credentials then return; end | 122 if not credentials then return; end |
122 if credentials.password then | 123 if credentials.password then |
123 if provider.set_password(username, credentials.password) == nil then | 124 if provider.set_password(username, credentials.password) == nil then |
124 return nil, "Auth failed. Could not set hashed password from plaintext."; | 125 return nil, "Auth failed. Could not set hashed password from plaintext."; |