comparison mod_password_policy/mod_password_policy.lua @ 4832:bfd4af4caddc

mod_password_policy: Support for additional policies provided by other modules E.g. check a password contains an uppercase character: module:provides("password-policy", { name = "contains_uppercase"; check_password = function (password, policy) return (policy ~= true) or (not not password:match("%u")); end; }) Config: password_policy = { contains_uppercase = true; }
author Matthew Wild <mwild1@gmail.com>
date Wed, 22 Dec 2021 14:48:46 +0000
parents 5a42cb84c8ee
children d3b69859553a
comparison
equal deleted inserted replaced
4831:5a42cb84c8ee 4832:bfd4af4caddc
7 -- password_policy = { 7 -- password_policy = {
8 -- length = 8; 8 -- length = 8;
9 -- } 9 -- }
10 10
11 11
12 local it = require "util.iterators";
13 local set = require "util.set";
14 local st = require "util.stanza";
15
12 local options = module:get_option("password_policy"); 16 local options = module:get_option("password_policy");
13 17
14 options = options or {}; 18 options = options or {};
15 options.length = options.length or 8; 19 options.length = options.length or 8;
16 if options.exclude_username == nil then 20 if options.exclude_username == nil then
17 options.exclude_username = true; 21 options.exclude_username = true;
18 end 22 end
19 23
20 local st = require "util.stanza"; 24 local builtin_policies = set.new({ "length", "exclude_username" });
25 local extra_policies = set.new(it.to_array(it.keys(options))) - builtin_policies;
26
27 local extra_policy_handlers = {};
28
29 module:handle_items("password-policy-provider", function (event)
30 -- Password policy handler added
31 local item = event.item;
32 module:log("error", "Adding password policy handler '%s'", item.name);
33 extra_policy_handlers[item.name] = item.check_password;
34 end, function (event)
35 -- Password policy handler removed
36 local item = event.item;
37 extra_policy_handlers[item.name] = nil;
38 end);
21 39
22 function check_password(password, additional_info) 40 function check_password(password, additional_info)
23 if not password or password == "" then 41 if not password or password == "" then
24 return nil, "No password provided", "no-password"; 42 return nil, "No password provided", "no-password";
25 end 43 end
32 local username = additional_info.username; 50 local username = additional_info.username;
33 if username and password:lower():find(username:lower(), 1, true) then 51 if username and password:lower():find(username:lower(), 1, true) then
34 return nil, "Password must not include your username", "username"; 52 return nil, "Password must not include your username", "username";
35 end 53 end
36 end 54 end
55
56 for policy in extra_policies do
57 local handler = extra_policy_handlers[policy];
58 if not handler then
59 module:log("error", "No policy handler found for '%s' (typo, or module not loaded?)", policy);
60 return nil, "Internal error while verifying password", "internal";
61 end
62 local ok, reason_text, reason_name = handler(password, options[policy], additional_info);
63 if ok ~= true then
64 return nil, reason_text or ("Password failed %s check"):format(policy), reason_name or policy;
65 end
66 end
67
37 return true; 68 return true;
38 end 69 end
39 70
40 function get_policy() --luacheck: ignore 131/get_policy 71 function get_policy() --luacheck: ignore 131/get_policy
41 return options; 72 return options;