plugins/mod_auth_internal_hashed.lua
author Kim Alvefur <zash@zash.se>
Sun, 24 Mar 2024 21:31:47 +0100
changeset 13467 3ce550ce44ce
parent 13363 1796370091d4
permissions -rw-r--r--
util.startup: Don't use not yet existent shutdown procedure when started as root (thanks SigmaTel71)
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
3164
db9def53fe9c Check in mod_hashpassauth -- works!
Jeff Mitchell <jeff@jefferai.org>
parents:
diff changeset
     1
-- Prosody IM
db9def53fe9c Check in mod_hashpassauth -- works!
Jeff Mitchell <jeff@jefferai.org>
parents:
diff changeset
     2
-- Copyright (C) 2008-2010 Matthew Wild
db9def53fe9c Check in mod_hashpassauth -- works!
Jeff Mitchell <jeff@jefferai.org>
parents:
diff changeset
     3
-- Copyright (C) 2008-2010 Waqas Hussain
db9def53fe9c Check in mod_hashpassauth -- works!
Jeff Mitchell <jeff@jefferai.org>
parents:
diff changeset
     4
-- Copyright (C) 2010 Jeff Mitchell
db9def53fe9c Check in mod_hashpassauth -- works!
Jeff Mitchell <jeff@jefferai.org>
parents:
diff changeset
     5
--
db9def53fe9c Check in mod_hashpassauth -- works!
Jeff Mitchell <jeff@jefferai.org>
parents:
diff changeset
     6
-- This project is MIT/X11 licensed. Please see the
db9def53fe9c Check in mod_hashpassauth -- works!
Jeff Mitchell <jeff@jefferai.org>
parents:
diff changeset
     7
-- COPYING file in the source package for more information.
db9def53fe9c Check in mod_hashpassauth -- works!
Jeff Mitchell <jeff@jefferai.org>
parents:
diff changeset
     8
--
db9def53fe9c Check in mod_hashpassauth -- works!
Jeff Mitchell <jeff@jefferai.org>
parents:
diff changeset
     9
6019
e9147a16059d mod_auth_interal_hashed: Update salt and iteration count when setting a new password
Florian Zeitz <florob@babelmonkeys.de>
parents: 5784
diff changeset
    10
local max = math.max;
e9147a16059d mod_auth_interal_hashed: Update salt and iteration count when setting a new password
Florian Zeitz <florob@babelmonkeys.de>
parents: 5784
diff changeset
    11
12981
74b9e05af71e plugins: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 12950
diff changeset
    12
local scram_hashers = require "prosody.util.sasl.scram".hashers;
74b9e05af71e plugins: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 12950
diff changeset
    13
local generate_uuid = require "prosody.util.uuid".generate;
74b9e05af71e plugins: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 12950
diff changeset
    14
local new_sasl = require "prosody.util.sasl".new;
74b9e05af71e plugins: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 12950
diff changeset
    15
local hex = require"prosody.util.hex";
12359
a0ff5c438e9d util.hex: Deprecate to/from in favour of encode/decode, for consistency!
Matthew Wild <mwild1@gmail.com>
parents: 12132
diff changeset
    16
local to_hex, from_hex = hex.encode, hex.decode;
12981
74b9e05af71e plugins: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 12950
diff changeset
    17
local saslprep = require "prosody.util.encodings".stringprep.saslprep;
74b9e05af71e plugins: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 12950
diff changeset
    18
local secure_equals = require "prosody.util.hashes".equals;
3164
db9def53fe9c Check in mod_hashpassauth -- works!
Jeff Mitchell <jeff@jefferai.org>
parents:
diff changeset
    19
5783
3a81e3b0ea4f mod_auth_internal_hashed: Use logger setup by moduleapi instead of going for util.logger directly
Kim Alvefur <zash@zash.se>
parents: 5782
diff changeset
    20
local log = module._log;
5784
02217725454b mod_auth_internal_hashed: Log calls to provider methods and be consistent with mod_auth_internal_plain
Kim Alvefur <zash@zash.se>
parents: 5783
diff changeset
    21
local host = module.host;
5783
3a81e3b0ea4f mod_auth_internal_hashed: Use logger setup by moduleapi instead of going for util.logger directly
Kim Alvefur <zash@zash.se>
parents: 5782
diff changeset
    22
5500
eeea0eb2602a mod_auth_internal_hashed, mod_auth_internal_plain, mod_privacy, mod_private, mod_register, mod_vcard, mod_muc: Use module:open_store()
Kim Alvefur <zash@zash.se>
parents: 5302
diff changeset
    23
local accounts = module:open_store("accounts");
eeea0eb2602a mod_auth_internal_hashed, mod_auth_internal_plain, mod_privacy, mod_private, mod_register, mod_vcard, mod_muc: Use module:open_store()
Kim Alvefur <zash@zash.se>
parents: 5302
diff changeset
    24
13206
173038306750 plugins: Use get_option_enum where appropriate
Kim Alvefur <zash@zash.se>
parents: 12981
diff changeset
    25
local hash_name = module:get_option_enum("password_hash", "SHA-1", "SHA-256");
10222
e458578ddfd3 mod_auth_internal_hashed: Add support for optionally using SCRAM-SHA-256 instead of SHA-1
Kim Alvefur <zash@zash.se>
parents: 8195
diff changeset
    26
local get_auth_db = assert(scram_hashers[hash_name], "SCRAM-"..hash_name.." not supported by SASL library");
10223
d58925bb74ca mod_auth_internal_hashed: Precompute SCRAM authentication profile name (thanks MattJ)
Kim Alvefur <zash@zash.se>
parents: 10222
diff changeset
    27
local scram_name = "scram_"..hash_name:gsub("%-","_"):lower();
3288
1a84d7d6f667 mod_auth_internal_hashed: Remove far too many instances of inline hex conversion using gsub, which was creating useless closures and what-not
Matthew Wild <mwild1@gmail.com>
parents: 3287
diff changeset
    28
3164
db9def53fe9c Check in mod_hashpassauth -- works!
Jeff Mitchell <jeff@jefferai.org>
parents:
diff changeset
    29
-- Default; can be set per-user
13217
50324f66ca2a plugins: Use integer config API with interval specification where sensible
Kim Alvefur <zash@zash.se>
parents: 13206
diff changeset
    30
local default_iteration_count = module:get_option_integer("default_iteration_count", 10000, 4096);
3164
db9def53fe9c Check in mod_hashpassauth -- works!
Jeff Mitchell <jeff@jefferai.org>
parents:
diff changeset
    31
12920
5a06d07596f9 mod_auth_internal_hashed: Add oauthbearer handler to our SASL profile
Matthew Wild <mwild1@gmail.com>
parents: 12907
diff changeset
    32
local tokenauth = module:depends("tokenauth");
5a06d07596f9 mod_auth_internal_hashed: Add oauthbearer handler to our SASL profile
Matthew Wild <mwild1@gmail.com>
parents: 12907
diff changeset
    33
5116
5f9066db1b4d mod_auth_internal_hashed: Get rid of useless wrapper function new_hashpass_provider.
Waqas Hussain <waqas20@gmail.com>
parents: 4764
diff changeset
    34
-- define auth provider
5117
2c7e1ce8f482 mod_auth_*: Use module:provides().
Waqas Hussain <waqas20@gmail.com>
parents: 5116
diff changeset
    35
local provider = {};
3164
db9def53fe9c Check in mod_hashpassauth -- works!
Jeff Mitchell <jeff@jefferai.org>
parents:
diff changeset
    36
5116
5f9066db1b4d mod_auth_internal_hashed: Get rid of useless wrapper function new_hashpass_provider.
Waqas Hussain <waqas20@gmail.com>
parents: 4764
diff changeset
    37
function provider.test_password(username, password)
5784
02217725454b mod_auth_internal_hashed: Log calls to provider methods and be consistent with mod_auth_internal_plain
Kim Alvefur <zash@zash.se>
parents: 5783
diff changeset
    38
	log("debug", "test password for user '%s'", username);
5500
eeea0eb2602a mod_auth_internal_hashed, mod_auth_internal_plain, mod_privacy, mod_private, mod_register, mod_vcard, mod_muc: Use module:open_store()
Kim Alvefur <zash@zash.se>
parents: 5302
diff changeset
    39
	local credentials = accounts:get(username) or {};
10918
0d7d71dee0a0 mod_auth_internal_*: Apply saslprep to passwords
Kim Alvefur <zash@zash.se>
parents: 10526
diff changeset
    40
	password = saslprep(password);
0d7d71dee0a0 mod_auth_internal_*: Apply saslprep to passwords
Kim Alvefur <zash@zash.se>
parents: 10526
diff changeset
    41
	if not password then
0d7d71dee0a0 mod_auth_internal_*: Apply saslprep to passwords
Kim Alvefur <zash@zash.se>
parents: 10526
diff changeset
    42
		return nil, "Password fails SASLprep.";
0d7d71dee0a0 mod_auth_internal_*: Apply saslprep to passwords
Kim Alvefur <zash@zash.se>
parents: 10526
diff changeset
    43
	end
3166
3c46cb94caed Add mechanism for upgrading to hashed passwords from default. Remove some extra debug.
Jeff Mitchell <jeff@jefferai.org>
parents: 3164
diff changeset
    44
5116
5f9066db1b4d mod_auth_internal_hashed: Get rid of useless wrapper function new_hashpass_provider.
Waqas Hussain <waqas20@gmail.com>
parents: 4764
diff changeset
    45
	if credentials.password ~= nil and string.len(credentials.password) ~= 0 then
11548
c98aebe601f9 mod_auth_internal_{plain,hashed}: Use constant-time string comparison for secrets
Matthew Wild <mwild1@gmail.com>
parents: 10918
diff changeset
    46
		if not secure_equals(saslprep(credentials.password), password) then
5116
5f9066db1b4d mod_auth_internal_hashed: Get rid of useless wrapper function new_hashpass_provider.
Waqas Hussain <waqas20@gmail.com>
parents: 4764
diff changeset
    47
			return nil, "Auth failed. Provided password is incorrect.";
3164
db9def53fe9c Check in mod_hashpassauth -- works!
Jeff Mitchell <jeff@jefferai.org>
parents:
diff changeset
    48
		end
db9def53fe9c Check in mod_hashpassauth -- works!
Jeff Mitchell <jeff@jefferai.org>
parents:
diff changeset
    49
5116
5f9066db1b4d mod_auth_internal_hashed: Get rid of useless wrapper function new_hashpass_provider.
Waqas Hussain <waqas20@gmail.com>
parents: 4764
diff changeset
    50
		if provider.set_password(username, credentials.password) == nil then
5f9066db1b4d mod_auth_internal_hashed: Get rid of useless wrapper function new_hashpass_provider.
Waqas Hussain <waqas20@gmail.com>
parents: 4764
diff changeset
    51
			return nil, "Auth failed. Could not set hashed password from plaintext.";
5f9066db1b4d mod_auth_internal_hashed: Get rid of useless wrapper function new_hashpass_provider.
Waqas Hussain <waqas20@gmail.com>
parents: 4764
diff changeset
    52
		else
3164
db9def53fe9c Check in mod_hashpassauth -- works!
Jeff Mitchell <jeff@jefferai.org>
parents:
diff changeset
    53
			return true;
db9def53fe9c Check in mod_hashpassauth -- works!
Jeff Mitchell <jeff@jefferai.org>
parents:
diff changeset
    54
		end
db9def53fe9c Check in mod_hashpassauth -- works!
Jeff Mitchell <jeff@jefferai.org>
parents:
diff changeset
    55
	end
db9def53fe9c Check in mod_hashpassauth -- works!
Jeff Mitchell <jeff@jefferai.org>
parents:
diff changeset
    56
5116
5f9066db1b4d mod_auth_internal_hashed: Get rid of useless wrapper function new_hashpass_provider.
Waqas Hussain <waqas20@gmail.com>
parents: 4764
diff changeset
    57
	if credentials.iteration_count == nil or credentials.salt == nil or string.len(credentials.salt) == 0 then
5f9066db1b4d mod_auth_internal_hashed: Get rid of useless wrapper function new_hashpass_provider.
Waqas Hussain <waqas20@gmail.com>
parents: 4764
diff changeset
    58
		return nil, "Auth failed. Stored salt and iteration count information is not complete.";
3164
db9def53fe9c Check in mod_hashpassauth -- works!
Jeff Mitchell <jeff@jefferai.org>
parents:
diff changeset
    59
	end
5776
bd0ff8ae98a8 Remove all trailing whitespace
Florian Zeitz <florob@babelmonkeys.de>
parents: 5500
diff changeset
    60
10222
e458578ddfd3 mod_auth_internal_hashed: Add support for optionally using SCRAM-SHA-256 instead of SHA-1
Kim Alvefur <zash@zash.se>
parents: 8195
diff changeset
    61
	local valid, stored_key, server_key = get_auth_db(password, credentials.salt, credentials.iteration_count);
5776
bd0ff8ae98a8 Remove all trailing whitespace
Florian Zeitz <florob@babelmonkeys.de>
parents: 5500
diff changeset
    62
5116
5f9066db1b4d mod_auth_internal_hashed: Get rid of useless wrapper function new_hashpass_provider.
Waqas Hussain <waqas20@gmail.com>
parents: 4764
diff changeset
    63
	local stored_key_hex = to_hex(stored_key);
5f9066db1b4d mod_auth_internal_hashed: Get rid of useless wrapper function new_hashpass_provider.
Waqas Hussain <waqas20@gmail.com>
parents: 4764
diff changeset
    64
	local server_key_hex = to_hex(server_key);
5776
bd0ff8ae98a8 Remove all trailing whitespace
Florian Zeitz <florob@babelmonkeys.de>
parents: 5500
diff changeset
    65
11548
c98aebe601f9 mod_auth_internal_{plain,hashed}: Use constant-time string comparison for secrets
Matthew Wild <mwild1@gmail.com>
parents: 10918
diff changeset
    66
	if valid and secure_equals(stored_key_hex, credentials.stored_key) and secure_equals(server_key_hex, credentials.server_key) then
3164
db9def53fe9c Check in mod_hashpassauth -- works!
Jeff Mitchell <jeff@jefferai.org>
parents:
diff changeset
    67
		return true;
5116
5f9066db1b4d mod_auth_internal_hashed: Get rid of useless wrapper function new_hashpass_provider.
Waqas Hussain <waqas20@gmail.com>
parents: 4764
diff changeset
    68
	else
5f9066db1b4d mod_auth_internal_hashed: Get rid of useless wrapper function new_hashpass_provider.
Waqas Hussain <waqas20@gmail.com>
parents: 4764
diff changeset
    69
		return nil, "Auth failed. Invalid username, password, or password hash information.";
3164
db9def53fe9c Check in mod_hashpassauth -- works!
Jeff Mitchell <jeff@jefferai.org>
parents:
diff changeset
    70
	end
5116
5f9066db1b4d mod_auth_internal_hashed: Get rid of useless wrapper function new_hashpass_provider.
Waqas Hussain <waqas20@gmail.com>
parents: 4764
diff changeset
    71
end
3164
db9def53fe9c Check in mod_hashpassauth -- works!
Jeff Mitchell <jeff@jefferai.org>
parents:
diff changeset
    72
5116
5f9066db1b4d mod_auth_internal_hashed: Get rid of useless wrapper function new_hashpass_provider.
Waqas Hussain <waqas20@gmail.com>
parents: 4764
diff changeset
    73
function provider.set_password(username, password)
5784
02217725454b mod_auth_internal_hashed: Log calls to provider methods and be consistent with mod_auth_internal_plain
Kim Alvefur <zash@zash.se>
parents: 5783
diff changeset
    74
	log("debug", "set_password for username '%s'", username);
5500
eeea0eb2602a mod_auth_internal_hashed, mod_auth_internal_plain, mod_privacy, mod_private, mod_register, mod_vcard, mod_muc: Use module:open_store()
Kim Alvefur <zash@zash.se>
parents: 5302
diff changeset
    75
	local account = accounts:get(username);
5116
5f9066db1b4d mod_auth_internal_hashed: Get rid of useless wrapper function new_hashpass_provider.
Waqas Hussain <waqas20@gmail.com>
parents: 4764
diff changeset
    76
	if account then
6019
e9147a16059d mod_auth_interal_hashed: Update salt and iteration count when setting a new password
Florian Zeitz <florob@babelmonkeys.de>
parents: 5784
diff changeset
    77
		account.salt = generate_uuid();
e9147a16059d mod_auth_interal_hashed: Update salt and iteration count when setting a new password
Florian Zeitz <florob@babelmonkeys.de>
parents: 5784
diff changeset
    78
		account.iteration_count = max(account.iteration_count or 0, default_iteration_count);
10222
e458578ddfd3 mod_auth_internal_hashed: Add support for optionally using SCRAM-SHA-256 instead of SHA-1
Kim Alvefur <zash@zash.se>
parents: 8195
diff changeset
    79
		local valid, stored_key, server_key = get_auth_db(password, account.salt, account.iteration_count);
10526
b1ca849b8e3a mod_auth_internal_hashed: Pass on errors from password hash function (fixes #1477)
Kim Alvefur <zash@zash.se>
parents: 8195
diff changeset
    80
		if not valid then
b1ca849b8e3a mod_auth_internal_hashed: Pass on errors from password hash function (fixes #1477)
Kim Alvefur <zash@zash.se>
parents: 8195
diff changeset
    81
			return valid, stored_key;
b1ca849b8e3a mod_auth_internal_hashed: Pass on errors from password hash function (fixes #1477)
Kim Alvefur <zash@zash.se>
parents: 8195
diff changeset
    82
		end
3288
1a84d7d6f667 mod_auth_internal_hashed: Remove far too many instances of inline hex conversion using gsub, which was creating useless closures and what-not
Matthew Wild <mwild1@gmail.com>
parents: 3287
diff changeset
    83
		local stored_key_hex = to_hex(stored_key);
1a84d7d6f667 mod_auth_internal_hashed: Remove far too many instances of inline hex conversion using gsub, which was creating useless closures and what-not
Matthew Wild <mwild1@gmail.com>
parents: 3287
diff changeset
    84
		local server_key_hex = to_hex(server_key);
5776
bd0ff8ae98a8 Remove all trailing whitespace
Florian Zeitz <florob@babelmonkeys.de>
parents: 5500
diff changeset
    85
5116
5f9066db1b4d mod_auth_internal_hashed: Get rid of useless wrapper function new_hashpass_provider.
Waqas Hussain <waqas20@gmail.com>
parents: 4764
diff changeset
    86
		account.stored_key = stored_key_hex
5f9066db1b4d mod_auth_internal_hashed: Get rid of useless wrapper function new_hashpass_provider.
Waqas Hussain <waqas20@gmail.com>
parents: 4764
diff changeset
    87
		account.server_key = server_key_hex
3164
db9def53fe9c Check in mod_hashpassauth -- works!
Jeff Mitchell <jeff@jefferai.org>
parents:
diff changeset
    88
5116
5f9066db1b4d mod_auth_internal_hashed: Get rid of useless wrapper function new_hashpass_provider.
Waqas Hussain <waqas20@gmail.com>
parents: 4764
diff changeset
    89
		account.password = nil;
12650
3f38f4735c7a usermanager, mod_auth_*: Add get_account_info() returning creation/update time
Matthew Wild <mwild1@gmail.com>
parents: 12359
diff changeset
    90
		account.updated = os.time();
5500
eeea0eb2602a mod_auth_internal_hashed, mod_auth_internal_plain, mod_privacy, mod_private, mod_register, mod_vcard, mod_muc: Use module:open_store()
Kim Alvefur <zash@zash.se>
parents: 5302
diff changeset
    91
		return accounts:set(username, account);
3994
42899d5efe3b mod_auth_internal_*: Support for delete_user method
Matthew Wild <mwild1@gmail.com>
parents: 3981
diff changeset
    92
	end
5116
5f9066db1b4d mod_auth_internal_hashed: Get rid of useless wrapper function new_hashpass_provider.
Waqas Hussain <waqas20@gmail.com>
parents: 4764
diff changeset
    93
	return nil, "Account not available.";
5f9066db1b4d mod_auth_internal_hashed: Get rid of useless wrapper function new_hashpass_provider.
Waqas Hussain <waqas20@gmail.com>
parents: 4764
diff changeset
    94
end
3994
42899d5efe3b mod_auth_internal_*: Support for delete_user method
Matthew Wild <mwild1@gmail.com>
parents: 3981
diff changeset
    95
12650
3f38f4735c7a usermanager, mod_auth_*: Add get_account_info() returning creation/update time
Matthew Wild <mwild1@gmail.com>
parents: 12359
diff changeset
    96
function provider.get_account_info(username)
3f38f4735c7a usermanager, mod_auth_*: Add get_account_info() returning creation/update time
Matthew Wild <mwild1@gmail.com>
parents: 12359
diff changeset
    97
	local account = accounts:get(username);
3f38f4735c7a usermanager, mod_auth_*: Add get_account_info() returning creation/update time
Matthew Wild <mwild1@gmail.com>
parents: 12359
diff changeset
    98
	if not account then return nil, "Account not available"; end
3f38f4735c7a usermanager, mod_auth_*: Add get_account_info() returning creation/update time
Matthew Wild <mwild1@gmail.com>
parents: 12359
diff changeset
    99
	return {
3f38f4735c7a usermanager, mod_auth_*: Add get_account_info() returning creation/update time
Matthew Wild <mwild1@gmail.com>
parents: 12359
diff changeset
   100
		created = account.created;
3f38f4735c7a usermanager, mod_auth_*: Add get_account_info() returning creation/update time
Matthew Wild <mwild1@gmail.com>
parents: 12359
diff changeset
   101
		password_updated = account.updated;
12906
0a0a251bcd6c mod_auth_internal_hashed: Implement is_enabled() method
Kim Alvefur <zash@zash.se>
parents: 12905
diff changeset
   102
		enabled = not account.disabled;
12650
3f38f4735c7a usermanager, mod_auth_*: Add get_account_info() returning creation/update time
Matthew Wild <mwild1@gmail.com>
parents: 12359
diff changeset
   103
	};
3f38f4735c7a usermanager, mod_auth_*: Add get_account_info() returning creation/update time
Matthew Wild <mwild1@gmail.com>
parents: 12359
diff changeset
   104
end
3f38f4735c7a usermanager, mod_auth_*: Add get_account_info() returning creation/update time
Matthew Wild <mwild1@gmail.com>
parents: 12359
diff changeset
   105
5116
5f9066db1b4d mod_auth_internal_hashed: Get rid of useless wrapper function new_hashpass_provider.
Waqas Hussain <waqas20@gmail.com>
parents: 4764
diff changeset
   106
function provider.user_exists(username)
5500
eeea0eb2602a mod_auth_internal_hashed, mod_auth_internal_plain, mod_privacy, mod_private, mod_register, mod_vcard, mod_muc: Use module:open_store()
Kim Alvefur <zash@zash.se>
parents: 5302
diff changeset
   107
	local account = accounts:get(username);
5116
5f9066db1b4d mod_auth_internal_hashed: Get rid of useless wrapper function new_hashpass_provider.
Waqas Hussain <waqas20@gmail.com>
parents: 4764
diff changeset
   108
	if not account then
5784
02217725454b mod_auth_internal_hashed: Log calls to provider methods and be consistent with mod_auth_internal_plain
Kim Alvefur <zash@zash.se>
parents: 5783
diff changeset
   109
		log("debug", "account not found for username '%s'", username);
5116
5f9066db1b4d mod_auth_internal_hashed: Get rid of useless wrapper function new_hashpass_provider.
Waqas Hussain <waqas20@gmail.com>
parents: 4764
diff changeset
   110
		return nil, "Auth failed. Invalid username";
3164
db9def53fe9c Check in mod_hashpassauth -- works!
Jeff Mitchell <jeff@jefferai.org>
parents:
diff changeset
   111
	end
5116
5f9066db1b4d mod_auth_internal_hashed: Get rid of useless wrapper function new_hashpass_provider.
Waqas Hussain <waqas20@gmail.com>
parents: 4764
diff changeset
   112
	return true;
5f9066db1b4d mod_auth_internal_hashed: Get rid of useless wrapper function new_hashpass_provider.
Waqas Hussain <waqas20@gmail.com>
parents: 4764
diff changeset
   113
end
5f9066db1b4d mod_auth_internal_hashed: Get rid of useless wrapper function new_hashpass_provider.
Waqas Hussain <waqas20@gmail.com>
parents: 4764
diff changeset
   114
12904
5484debdfdfe mod_auth_internal_hashed: Refactor to prepare for disabling users
Kim Alvefur <zash@zash.se>
parents: 12673
diff changeset
   115
function provider.is_enabled(username) -- luacheck: ignore 212
12906
0a0a251bcd6c mod_auth_internal_hashed: Implement is_enabled() method
Kim Alvefur <zash@zash.se>
parents: 12905
diff changeset
   116
	local info, err = provider.get_account_info(username);
0a0a251bcd6c mod_auth_internal_hashed: Implement is_enabled() method
Kim Alvefur <zash@zash.se>
parents: 12905
diff changeset
   117
	if not info then return nil, err; end
0a0a251bcd6c mod_auth_internal_hashed: Implement is_enabled() method
Kim Alvefur <zash@zash.se>
parents: 12905
diff changeset
   118
	return info.enabled;
12904
5484debdfdfe mod_auth_internal_hashed: Refactor to prepare for disabling users
Kim Alvefur <zash@zash.se>
parents: 12673
diff changeset
   119
end
5484debdfdfe mod_auth_internal_hashed: Refactor to prepare for disabling users
Kim Alvefur <zash@zash.se>
parents: 12673
diff changeset
   120
12907
13950bf92802 mod_auth_internal_hashed: Implement methods to enable and disable users
Kim Alvefur <zash@zash.se>
parents: 12906
diff changeset
   121
function provider.enable(username)
13950bf92802 mod_auth_internal_hashed: Implement methods to enable and disable users
Kim Alvefur <zash@zash.se>
parents: 12906
diff changeset
   122
	-- TODO map store?
13950bf92802 mod_auth_internal_hashed: Implement methods to enable and disable users
Kim Alvefur <zash@zash.se>
parents: 12906
diff changeset
   123
	local account = accounts:get(username);
13950bf92802 mod_auth_internal_hashed: Implement methods to enable and disable users
Kim Alvefur <zash@zash.se>
parents: 12906
diff changeset
   124
	account.disabled = nil;
12937
3ab0bbb1dc35 mod_auth_internal_hashed: Record time of account disable / re-enable
Kim Alvefur <zash@zash.se>
parents: 12920
diff changeset
   125
	account.updated = os.time();
12907
13950bf92802 mod_auth_internal_hashed: Implement methods to enable and disable users
Kim Alvefur <zash@zash.se>
parents: 12906
diff changeset
   126
	return accounts:set(username, account);
12905
b884ddb5a0e7 mod_auth_internal_hashed: Add stub methods for enabling and disabling users
Kim Alvefur <zash@zash.se>
parents: 12904
diff changeset
   127
end
b884ddb5a0e7 mod_auth_internal_hashed: Add stub methods for enabling and disabling users
Kim Alvefur <zash@zash.se>
parents: 12904
diff changeset
   128
13363
1796370091d4 usermanager, mod_auth_internal_hashed: Support metadata when disabling a user
Matthew Wild <mwild1@gmail.com>
parents: 13217
diff changeset
   129
function provider.disable(username, meta)
12907
13950bf92802 mod_auth_internal_hashed: Implement methods to enable and disable users
Kim Alvefur <zash@zash.se>
parents: 12906
diff changeset
   130
	local account = accounts:get(username);
13950bf92802 mod_auth_internal_hashed: Implement methods to enable and disable users
Kim Alvefur <zash@zash.se>
parents: 12906
diff changeset
   131
	account.disabled = true;
13363
1796370091d4 usermanager, mod_auth_internal_hashed: Support metadata when disabling a user
Matthew Wild <mwild1@gmail.com>
parents: 13217
diff changeset
   132
	account.disabled_meta = meta;
12937
3ab0bbb1dc35 mod_auth_internal_hashed: Record time of account disable / re-enable
Kim Alvefur <zash@zash.se>
parents: 12920
diff changeset
   133
	account.updated = os.time();
12907
13950bf92802 mod_auth_internal_hashed: Implement methods to enable and disable users
Kim Alvefur <zash@zash.se>
parents: 12906
diff changeset
   134
	return accounts:set(username, account);
12905
b884ddb5a0e7 mod_auth_internal_hashed: Add stub methods for enabling and disabling users
Kim Alvefur <zash@zash.se>
parents: 12904
diff changeset
   135
end
b884ddb5a0e7 mod_auth_internal_hashed: Add stub methods for enabling and disabling users
Kim Alvefur <zash@zash.se>
parents: 12904
diff changeset
   136
5156
6b08c922a2e4 mod_auth_internal_{plain,hashed}: Add support for iterating over accounts
Kim Alvefur <zash@zash.se>
parents: 5117
diff changeset
   137
function provider.users()
5500
eeea0eb2602a mod_auth_internal_hashed, mod_auth_internal_plain, mod_privacy, mod_private, mod_register, mod_vcard, mod_muc: Use module:open_store()
Kim Alvefur <zash@zash.se>
parents: 5302
diff changeset
   138
	return accounts:users();
5156
6b08c922a2e4 mod_auth_internal_{plain,hashed}: Add support for iterating over accounts
Kim Alvefur <zash@zash.se>
parents: 5117
diff changeset
   139
end
6b08c922a2e4 mod_auth_internal_{plain,hashed}: Add support for iterating over accounts
Kim Alvefur <zash@zash.se>
parents: 5117
diff changeset
   140
5116
5f9066db1b4d mod_auth_internal_hashed: Get rid of useless wrapper function new_hashpass_provider.
Waqas Hussain <waqas20@gmail.com>
parents: 4764
diff changeset
   141
function provider.create_user(username, password)
12673
aed38948791f mod_auth_internal_hashed: Allow creating disabled account without password
Kim Alvefur <zash@zash.se>
parents: 12650
diff changeset
   142
	local now = os.time();
5116
5f9066db1b4d mod_auth_internal_hashed: Get rid of useless wrapper function new_hashpass_provider.
Waqas Hussain <waqas20@gmail.com>
parents: 4764
diff changeset
   143
	if password == nil then
12673
aed38948791f mod_auth_internal_hashed: Allow creating disabled account without password
Kim Alvefur <zash@zash.se>
parents: 12650
diff changeset
   144
		return accounts:set(username, { created = now; updated = now; disabled = true });
5116
5f9066db1b4d mod_auth_internal_hashed: Get rid of useless wrapper function new_hashpass_provider.
Waqas Hussain <waqas20@gmail.com>
parents: 4764
diff changeset
   145
	end
5f9066db1b4d mod_auth_internal_hashed: Get rid of useless wrapper function new_hashpass_provider.
Waqas Hussain <waqas20@gmail.com>
parents: 4764
diff changeset
   146
	local salt = generate_uuid();
10222
e458578ddfd3 mod_auth_internal_hashed: Add support for optionally using SCRAM-SHA-256 instead of SHA-1
Kim Alvefur <zash@zash.se>
parents: 8195
diff changeset
   147
	local valid, stored_key, server_key = get_auth_db(password, salt, default_iteration_count);
10526
b1ca849b8e3a mod_auth_internal_hashed: Pass on errors from password hash function (fixes #1477)
Kim Alvefur <zash@zash.se>
parents: 8195
diff changeset
   148
	if not valid then
b1ca849b8e3a mod_auth_internal_hashed: Pass on errors from password hash function (fixes #1477)
Kim Alvefur <zash@zash.se>
parents: 8195
diff changeset
   149
		return valid, stored_key;
b1ca849b8e3a mod_auth_internal_hashed: Pass on errors from password hash function (fixes #1477)
Kim Alvefur <zash@zash.se>
parents: 8195
diff changeset
   150
	end
5116
5f9066db1b4d mod_auth_internal_hashed: Get rid of useless wrapper function new_hashpass_provider.
Waqas Hussain <waqas20@gmail.com>
parents: 4764
diff changeset
   151
	local stored_key_hex = to_hex(stored_key);
5f9066db1b4d mod_auth_internal_hashed: Get rid of useless wrapper function new_hashpass_provider.
Waqas Hussain <waqas20@gmail.com>
parents: 4764
diff changeset
   152
	local server_key_hex = to_hex(server_key);
8059
cacf14c218ab mod_auth_internal_hashed: Split long lines [luacheck]
Kim Alvefur <zash@zash.se>
parents: 8058
diff changeset
   153
	return accounts:set(username, {
cacf14c218ab mod_auth_internal_hashed: Split long lines [luacheck]
Kim Alvefur <zash@zash.se>
parents: 8058
diff changeset
   154
		stored_key = stored_key_hex, server_key = server_key_hex,
12650
3f38f4735c7a usermanager, mod_auth_*: Add get_account_info() returning creation/update time
Matthew Wild <mwild1@gmail.com>
parents: 12359
diff changeset
   155
		salt = salt, iteration_count = default_iteration_count,
3f38f4735c7a usermanager, mod_auth_*: Add get_account_info() returning creation/update time
Matthew Wild <mwild1@gmail.com>
parents: 12359
diff changeset
   156
		created = now, updated = now;
8059
cacf14c218ab mod_auth_internal_hashed: Split long lines [luacheck]
Kim Alvefur <zash@zash.se>
parents: 8058
diff changeset
   157
	});
3164
db9def53fe9c Check in mod_hashpassauth -- works!
Jeff Mitchell <jeff@jefferai.org>
parents:
diff changeset
   158
end
db9def53fe9c Check in mod_hashpassauth -- works!
Jeff Mitchell <jeff@jefferai.org>
parents:
diff changeset
   159
5116
5f9066db1b4d mod_auth_internal_hashed: Get rid of useless wrapper function new_hashpass_provider.
Waqas Hussain <waqas20@gmail.com>
parents: 4764
diff changeset
   160
function provider.delete_user(username)
5500
eeea0eb2602a mod_auth_internal_hashed, mod_auth_internal_plain, mod_privacy, mod_private, mod_register, mod_vcard, mod_muc: Use module:open_store()
Kim Alvefur <zash@zash.se>
parents: 5302
diff changeset
   161
	return accounts:set(username, nil);
5116
5f9066db1b4d mod_auth_internal_hashed: Get rid of useless wrapper function new_hashpass_provider.
Waqas Hussain <waqas20@gmail.com>
parents: 4764
diff changeset
   162
end
3164
db9def53fe9c Check in mod_hashpassauth -- works!
Jeff Mitchell <jeff@jefferai.org>
parents:
diff changeset
   163
5116
5f9066db1b4d mod_auth_internal_hashed: Get rid of useless wrapper function new_hashpass_provider.
Waqas Hussain <waqas20@gmail.com>
parents: 4764
diff changeset
   164
function provider.get_sasl_handler()
5f9066db1b4d mod_auth_internal_hashed: Get rid of useless wrapper function new_hashpass_provider.
Waqas Hussain <waqas20@gmail.com>
parents: 4764
diff changeset
   165
	local testpass_authentication_profile = {
12950
59478b295137 mod_auth_internal_hashed: Shorten call path
Kim Alvefur <zash@zash.se>
parents: 12937
diff changeset
   166
		plain_test = function(_, username, password)
59478b295137 mod_auth_internal_hashed: Shorten call path
Kim Alvefur <zash@zash.se>
parents: 12937
diff changeset
   167
			return provider.test_password(username, password), provider.is_enabled(username);
5116
5f9066db1b4d mod_auth_internal_hashed: Get rid of useless wrapper function new_hashpass_provider.
Waqas Hussain <waqas20@gmail.com>
parents: 4764
diff changeset
   168
		end,
10223
d58925bb74ca mod_auth_internal_hashed: Precompute SCRAM authentication profile name (thanks MattJ)
Kim Alvefur <zash@zash.se>
parents: 10222
diff changeset
   169
		[scram_name] = function(_, username)
5500
eeea0eb2602a mod_auth_internal_hashed, mod_auth_internal_plain, mod_privacy, mod_private, mod_register, mod_vcard, mod_muc: Use module:open_store()
Kim Alvefur <zash@zash.se>
parents: 5302
diff changeset
   170
			local credentials = accounts:get(username);
5116
5f9066db1b4d mod_auth_internal_hashed: Get rid of useless wrapper function new_hashpass_provider.
Waqas Hussain <waqas20@gmail.com>
parents: 4764
diff changeset
   171
			if not credentials then return; end
5f9066db1b4d mod_auth_internal_hashed: Get rid of useless wrapper function new_hashpass_provider.
Waqas Hussain <waqas20@gmail.com>
parents: 4764
diff changeset
   172
			if credentials.password then
8195
4354f556c5db core.usermanager, various modules: Disconnect other resources on password change (thanks waqas) (fixes #512)
Kim Alvefur <zash@zash.se>
parents: 8059
diff changeset
   173
				if provider.set_password(username, credentials.password) == nil then
4354f556c5db core.usermanager, various modules: Disconnect other resources on password change (thanks waqas) (fixes #512)
Kim Alvefur <zash@zash.se>
parents: 8059
diff changeset
   174
					return nil, "Auth failed. Could not set hashed password from plaintext.";
4354f556c5db core.usermanager, various modules: Disconnect other resources on password change (thanks waqas) (fixes #512)
Kim Alvefur <zash@zash.se>
parents: 8059
diff changeset
   175
				end
5500
eeea0eb2602a mod_auth_internal_hashed, mod_auth_internal_plain, mod_privacy, mod_private, mod_register, mod_vcard, mod_muc: Use module:open_store()
Kim Alvefur <zash@zash.se>
parents: 5302
diff changeset
   176
				credentials = accounts:get(username);
5116
5f9066db1b4d mod_auth_internal_hashed: Get rid of useless wrapper function new_hashpass_provider.
Waqas Hussain <waqas20@gmail.com>
parents: 4764
diff changeset
   177
				if not credentials then return; end
5f9066db1b4d mod_auth_internal_hashed: Get rid of useless wrapper function new_hashpass_provider.
Waqas Hussain <waqas20@gmail.com>
parents: 4764
diff changeset
   178
			end
5776
bd0ff8ae98a8 Remove all trailing whitespace
Florian Zeitz <florob@babelmonkeys.de>
parents: 5500
diff changeset
   179
8059
cacf14c218ab mod_auth_internal_hashed: Split long lines [luacheck]
Kim Alvefur <zash@zash.se>
parents: 8058
diff changeset
   180
			local stored_key, server_key = credentials.stored_key, credentials.server_key;
cacf14c218ab mod_auth_internal_hashed: Split long lines [luacheck]
Kim Alvefur <zash@zash.se>
parents: 8058
diff changeset
   181
			local iteration_count, salt = credentials.iteration_count, credentials.salt;
5116
5f9066db1b4d mod_auth_internal_hashed: Get rid of useless wrapper function new_hashpass_provider.
Waqas Hussain <waqas20@gmail.com>
parents: 4764
diff changeset
   182
			stored_key = stored_key and from_hex(stored_key);
5f9066db1b4d mod_auth_internal_hashed: Get rid of useless wrapper function new_hashpass_provider.
Waqas Hussain <waqas20@gmail.com>
parents: 4764
diff changeset
   183
			server_key = server_key and from_hex(server_key);
12906
0a0a251bcd6c mod_auth_internal_hashed: Implement is_enabled() method
Kim Alvefur <zash@zash.se>
parents: 12905
diff changeset
   184
			return stored_key, server_key, iteration_count, salt, not credentials.disabled;
12920
5a06d07596f9 mod_auth_internal_hashed: Add oauthbearer handler to our SASL profile
Matthew Wild <mwild1@gmail.com>
parents: 12907
diff changeset
   185
		end;
5a06d07596f9 mod_auth_internal_hashed: Add oauthbearer handler to our SASL profile
Matthew Wild <mwild1@gmail.com>
parents: 12907
diff changeset
   186
		oauthbearer = tokenauth.sasl_handler(provider, "oauth2", module:shared("tokenauth/oauthbearer_config"));
5116
5f9066db1b4d mod_auth_internal_hashed: Get rid of useless wrapper function new_hashpass_provider.
Waqas Hussain <waqas20@gmail.com>
parents: 4764
diff changeset
   187
	};
5f9066db1b4d mod_auth_internal_hashed: Get rid of useless wrapper function new_hashpass_provider.
Waqas Hussain <waqas20@gmail.com>
parents: 4764
diff changeset
   188
	return new_sasl(host, testpass_authentication_profile);
5f9066db1b4d mod_auth_internal_hashed: Get rid of useless wrapper function new_hashpass_provider.
Waqas Hussain <waqas20@gmail.com>
parents: 4764
diff changeset
   189
end
5776
bd0ff8ae98a8 Remove all trailing whitespace
Florian Zeitz <florob@babelmonkeys.de>
parents: 5500
diff changeset
   190
5117
2c7e1ce8f482 mod_auth_*: Use module:provides().
Waqas Hussain <waqas20@gmail.com>
parents: 5116
diff changeset
   191
module:provides("auth", provider);
5116
5f9066db1b4d mod_auth_internal_hashed: Get rid of useless wrapper function new_hashpass_provider.
Waqas Hussain <waqas20@gmail.com>
parents: 4764
diff changeset
   192