Mercurial > prosody-modules
view mod_password_policy/mod_password_policy.lua @ 5511:0860497152af
mod_http_oauth2: Record hash of client_id to allow future verification
RFC 6819 section 5.2.2.2 states that refresh tokens MUST be bound to the
client. In order to do that, we must record something that can
definitely tie the client to the grant. Since the full client_id is so
large (why we have this client_subset function), a hash is stored
instead.
| author | Kim Alvefur <zash@zash.se> |
|---|---|
| date | Fri, 02 Jun 2023 10:14:16 +0200 |
| parents | bfd4af4caddc |
| children | d3b69859553a |
line wrap: on
line source
-- Password policy enforcement for Prosody -- -- Copyright (C) 2012 Waqas Hussain -- -- -- Configuration: -- password_policy = { -- length = 8; -- } local it = require "util.iterators"; local set = require "util.set"; local st = require "util.stanza"; local options = module:get_option("password_policy"); options = options or {}; options.length = options.length or 8; if options.exclude_username == nil then options.exclude_username = true; end local builtin_policies = set.new({ "length", "exclude_username" }); local extra_policies = set.new(it.to_array(it.keys(options))) - builtin_policies; local extra_policy_handlers = {}; module:handle_items("password-policy-provider", function (event) -- Password policy handler added local item = event.item; module:log("error", "Adding password policy handler '%s'", item.name); extra_policy_handlers[item.name] = item.check_password; end, function (event) -- Password policy handler removed local item = event.item; extra_policy_handlers[item.name] = nil; end); function check_password(password, additional_info) if not password or password == "" then return nil, "No password provided", "no-password"; end if #password < options.length then return nil, ("Password is too short (minimum %d characters)"):format(options.length), "length"; end if additional_info then local username = additional_info.username; if username and password:lower():find(username:lower(), 1, true) then return nil, "Password must not include your username", "username"; end end for policy in extra_policies do local handler = extra_policy_handlers[policy]; if not handler then module:log("error", "No policy handler found for '%s' (typo, or module not loaded?)", policy); return nil, "Internal error while verifying password", "internal"; end local ok, reason_text, reason_name = handler(password, options[policy], additional_info); if ok ~= true then return nil, reason_text or ("Password failed %s check"):format(policy), reason_name or policy; end end return true; end function get_policy() --luacheck: ignore 131/get_policy return options; end function handler(event) local origin, stanza = event.origin, event.stanza; if stanza.attr.type == "set" then local query = stanza.tags[1]; local passwords = {}; local dataform = query:get_child("x", "jabber:x:data"); if dataform then for _,tag in ipairs(dataform.tags) do if tag.attr.var == "password" then table.insert(passwords, tag:get_child_text("value")); end end end table.insert(passwords, query:get_child_text("password")); local additional_info = { username = origin.username; }; for _,password in ipairs(passwords) do if password then local pw_ok, pw_err, pw_failed_policy = check_password(password, additional_info); if not pw_ok then module:log("debug", "Password failed check against '%s' policy", pw_failed_policy); origin.send(st.error_reply(stanza, "cancel", "not-acceptable", pw_err)); return true; end end end end end module:hook("iq/self/jabber:iq:register:query", handler, 10); module:hook("iq/host/jabber:iq:register:query", handler, 10); module:hook("stanza/iq/jabber:iq:register:query", handler, 10);
