Mercurial > prosody-modules
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; |
