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.";