Mercurial > prosody-modules
annotate mod_password_policy/mod_password_policy.lua @ 5553:67152838afbc
mod_http_oauth2: Improve error messages for URI properties
Since there are separate validation checks for URI properties, including
that they should use https, with better and more specific error reporting.
Reverts 'luaPattern' to 'pattern' which is not currently supported by
util.jsonschema, but allows anything that retrieves the schema over http
to validate against it, should they wish to do so.
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Sat, 17 Jun 2023 18:15:00 +0200 |
parents | bfd4af4caddc |
children | d3b69859553a |
rev | line source |
---|---|
841
0649883de4d3
mod_password_policy: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
1 -- Password policy enforcement for Prosody |
0649883de4d3
mod_password_policy: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
2 -- |
0649883de4d3
mod_password_policy: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
3 -- Copyright (C) 2012 Waqas Hussain |
0649883de4d3
mod_password_policy: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
4 -- |
0649883de4d3
mod_password_policy: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
5 -- |
0649883de4d3
mod_password_policy: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
6 -- Configuration: |
0649883de4d3
mod_password_policy: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
7 -- password_policy = { |
0649883de4d3
mod_password_policy: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
8 -- length = 8; |
0649883de4d3
mod_password_policy: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
9 -- } |
0649883de4d3
mod_password_policy: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
10 |
0649883de4d3
mod_password_policy: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
11 |
4832
bfd4af4caddc
mod_password_policy: Support for additional policies provided by other modules
Matthew Wild <mwild1@gmail.com>
parents:
4831
diff
changeset
|
12 local it = require "util.iterators"; |
bfd4af4caddc
mod_password_policy: Support for additional policies provided by other modules
Matthew Wild <mwild1@gmail.com>
parents:
4831
diff
changeset
|
13 local set = require "util.set"; |
bfd4af4caddc
mod_password_policy: Support for additional policies provided by other modules
Matthew Wild <mwild1@gmail.com>
parents:
4831
diff
changeset
|
14 local st = require "util.stanza"; |
bfd4af4caddc
mod_password_policy: Support for additional policies provided by other modules
Matthew Wild <mwild1@gmail.com>
parents:
4831
diff
changeset
|
15 |
841
0649883de4d3
mod_password_policy: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
16 local options = module:get_option("password_policy"); |
0649883de4d3
mod_password_policy: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
17 |
0649883de4d3
mod_password_policy: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
18 options = options or {}; |
0649883de4d3
mod_password_policy: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
19 options.length = options.length or 8; |
4829
caf7e88dc9e5
mod_password_policy: Add check that password doesn't contain username
Matthew Wild <mwild1@gmail.com>
parents:
4828
diff
changeset
|
20 if options.exclude_username == nil then |
caf7e88dc9e5
mod_password_policy: Add check that password doesn't contain username
Matthew Wild <mwild1@gmail.com>
parents:
4828
diff
changeset
|
21 options.exclude_username = true; |
caf7e88dc9e5
mod_password_policy: Add check that password doesn't contain username
Matthew Wild <mwild1@gmail.com>
parents:
4828
diff
changeset
|
22 end |
841
0649883de4d3
mod_password_policy: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
23 |
4832
bfd4af4caddc
mod_password_policy: Support for additional policies provided by other modules
Matthew Wild <mwild1@gmail.com>
parents:
4831
diff
changeset
|
24 local builtin_policies = set.new({ "length", "exclude_username" }); |
bfd4af4caddc
mod_password_policy: Support for additional policies provided by other modules
Matthew Wild <mwild1@gmail.com>
parents:
4831
diff
changeset
|
25 local extra_policies = set.new(it.to_array(it.keys(options))) - builtin_policies; |
bfd4af4caddc
mod_password_policy: Support for additional policies provided by other modules
Matthew Wild <mwild1@gmail.com>
parents:
4831
diff
changeset
|
26 |
bfd4af4caddc
mod_password_policy: Support for additional policies provided by other modules
Matthew Wild <mwild1@gmail.com>
parents:
4831
diff
changeset
|
27 local extra_policy_handlers = {}; |
bfd4af4caddc
mod_password_policy: Support for additional policies provided by other modules
Matthew Wild <mwild1@gmail.com>
parents:
4831
diff
changeset
|
28 |
bfd4af4caddc
mod_password_policy: Support for additional policies provided by other modules
Matthew Wild <mwild1@gmail.com>
parents:
4831
diff
changeset
|
29 module:handle_items("password-policy-provider", function (event) |
bfd4af4caddc
mod_password_policy: Support for additional policies provided by other modules
Matthew Wild <mwild1@gmail.com>
parents:
4831
diff
changeset
|
30 -- Password policy handler added |
bfd4af4caddc
mod_password_policy: Support for additional policies provided by other modules
Matthew Wild <mwild1@gmail.com>
parents:
4831
diff
changeset
|
31 local item = event.item; |
bfd4af4caddc
mod_password_policy: Support for additional policies provided by other modules
Matthew Wild <mwild1@gmail.com>
parents:
4831
diff
changeset
|
32 module:log("error", "Adding password policy handler '%s'", item.name); |
bfd4af4caddc
mod_password_policy: Support for additional policies provided by other modules
Matthew Wild <mwild1@gmail.com>
parents:
4831
diff
changeset
|
33 extra_policy_handlers[item.name] = item.check_password; |
bfd4af4caddc
mod_password_policy: Support for additional policies provided by other modules
Matthew Wild <mwild1@gmail.com>
parents:
4831
diff
changeset
|
34 end, function (event) |
bfd4af4caddc
mod_password_policy: Support for additional policies provided by other modules
Matthew Wild <mwild1@gmail.com>
parents:
4831
diff
changeset
|
35 -- Password policy handler removed |
bfd4af4caddc
mod_password_policy: Support for additional policies provided by other modules
Matthew Wild <mwild1@gmail.com>
parents:
4831
diff
changeset
|
36 local item = event.item; |
bfd4af4caddc
mod_password_policy: Support for additional policies provided by other modules
Matthew Wild <mwild1@gmail.com>
parents:
4831
diff
changeset
|
37 extra_policy_handlers[item.name] = nil; |
bfd4af4caddc
mod_password_policy: Support for additional policies provided by other modules
Matthew Wild <mwild1@gmail.com>
parents:
4831
diff
changeset
|
38 end); |
841
0649883de4d3
mod_password_policy: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
39 |
4829
caf7e88dc9e5
mod_password_policy: Add check that password doesn't contain username
Matthew Wild <mwild1@gmail.com>
parents:
4828
diff
changeset
|
40 function check_password(password, additional_info) |
4830
af6143cf7d22
mod_password_policy: Hard failure on missing/empty passwords
Matthew Wild <mwild1@gmail.com>
parents:
4829
diff
changeset
|
41 if not password or password == "" then |
af6143cf7d22
mod_password_policy: Hard failure on missing/empty passwords
Matthew Wild <mwild1@gmail.com>
parents:
4829
diff
changeset
|
42 return nil, "No password provided", "no-password"; |
af6143cf7d22
mod_password_policy: Hard failure on missing/empty passwords
Matthew Wild <mwild1@gmail.com>
parents:
4829
diff
changeset
|
43 end |
af6143cf7d22
mod_password_policy: Hard failure on missing/empty passwords
Matthew Wild <mwild1@gmail.com>
parents:
4829
diff
changeset
|
44 |
3350
cb26d04b391c
mod_password_policy: Return error as second result explaining failure reason
Matthew Wild <mwild1@gmail.com>
parents:
845
diff
changeset
|
45 if #password < options.length then |
4828
56eba4bca28f
mod_password_policy: Allow check_password() to indicate the policy that failed
Matthew Wild <mwild1@gmail.com>
parents:
3351
diff
changeset
|
46 return nil, ("Password is too short (minimum %d characters)"):format(options.length), "length"; |
3350
cb26d04b391c
mod_password_policy: Return error as second result explaining failure reason
Matthew Wild <mwild1@gmail.com>
parents:
845
diff
changeset
|
47 end |
4829
caf7e88dc9e5
mod_password_policy: Add check that password doesn't contain username
Matthew Wild <mwild1@gmail.com>
parents:
4828
diff
changeset
|
48 |
caf7e88dc9e5
mod_password_policy: Add check that password doesn't contain username
Matthew Wild <mwild1@gmail.com>
parents:
4828
diff
changeset
|
49 if additional_info then |
caf7e88dc9e5
mod_password_policy: Add check that password doesn't contain username
Matthew Wild <mwild1@gmail.com>
parents:
4828
diff
changeset
|
50 local username = additional_info.username; |
caf7e88dc9e5
mod_password_policy: Add check that password doesn't contain username
Matthew Wild <mwild1@gmail.com>
parents:
4828
diff
changeset
|
51 if username and password:lower():find(username:lower(), 1, true) then |
caf7e88dc9e5
mod_password_policy: Add check that password doesn't contain username
Matthew Wild <mwild1@gmail.com>
parents:
4828
diff
changeset
|
52 return nil, "Password must not include your username", "username"; |
caf7e88dc9e5
mod_password_policy: Add check that password doesn't contain username
Matthew Wild <mwild1@gmail.com>
parents:
4828
diff
changeset
|
53 end |
caf7e88dc9e5
mod_password_policy: Add check that password doesn't contain username
Matthew Wild <mwild1@gmail.com>
parents:
4828
diff
changeset
|
54 end |
4832
bfd4af4caddc
mod_password_policy: Support for additional policies provided by other modules
Matthew Wild <mwild1@gmail.com>
parents:
4831
diff
changeset
|
55 |
bfd4af4caddc
mod_password_policy: Support for additional policies provided by other modules
Matthew Wild <mwild1@gmail.com>
parents:
4831
diff
changeset
|
56 for policy in extra_policies do |
bfd4af4caddc
mod_password_policy: Support for additional policies provided by other modules
Matthew Wild <mwild1@gmail.com>
parents:
4831
diff
changeset
|
57 local handler = extra_policy_handlers[policy]; |
bfd4af4caddc
mod_password_policy: Support for additional policies provided by other modules
Matthew Wild <mwild1@gmail.com>
parents:
4831
diff
changeset
|
58 if not handler then |
bfd4af4caddc
mod_password_policy: Support for additional policies provided by other modules
Matthew Wild <mwild1@gmail.com>
parents:
4831
diff
changeset
|
59 module:log("error", "No policy handler found for '%s' (typo, or module not loaded?)", policy); |
bfd4af4caddc
mod_password_policy: Support for additional policies provided by other modules
Matthew Wild <mwild1@gmail.com>
parents:
4831
diff
changeset
|
60 return nil, "Internal error while verifying password", "internal"; |
bfd4af4caddc
mod_password_policy: Support for additional policies provided by other modules
Matthew Wild <mwild1@gmail.com>
parents:
4831
diff
changeset
|
61 end |
bfd4af4caddc
mod_password_policy: Support for additional policies provided by other modules
Matthew Wild <mwild1@gmail.com>
parents:
4831
diff
changeset
|
62 local ok, reason_text, reason_name = handler(password, options[policy], additional_info); |
bfd4af4caddc
mod_password_policy: Support for additional policies provided by other modules
Matthew Wild <mwild1@gmail.com>
parents:
4831
diff
changeset
|
63 if ok ~= true then |
bfd4af4caddc
mod_password_policy: Support for additional policies provided by other modules
Matthew Wild <mwild1@gmail.com>
parents:
4831
diff
changeset
|
64 return nil, reason_text or ("Password failed %s check"):format(policy), reason_name or policy; |
bfd4af4caddc
mod_password_policy: Support for additional policies provided by other modules
Matthew Wild <mwild1@gmail.com>
parents:
4831
diff
changeset
|
65 end |
bfd4af4caddc
mod_password_policy: Support for additional policies provided by other modules
Matthew Wild <mwild1@gmail.com>
parents:
4831
diff
changeset
|
66 end |
bfd4af4caddc
mod_password_policy: Support for additional policies provided by other modules
Matthew Wild <mwild1@gmail.com>
parents:
4831
diff
changeset
|
67 |
3350
cb26d04b391c
mod_password_policy: Return error as second result explaining failure reason
Matthew Wild <mwild1@gmail.com>
parents:
845
diff
changeset
|
68 return true; |
841
0649883de4d3
mod_password_policy: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
69 end |
0649883de4d3
mod_password_policy: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
70 |
4831
5a42cb84c8ee
mod_password_policy: Silence luacheck warning for intentional global
Matthew Wild <mwild1@gmail.com>
parents:
4830
diff
changeset
|
71 function get_policy() --luacheck: ignore 131/get_policy |
3351
662f2722f745
mod_password_policy: Export function to get policy in use by the module
Matthew Wild <mwild1@gmail.com>
parents:
3350
diff
changeset
|
72 return options; |
662f2722f745
mod_password_policy: Export function to get policy in use by the module
Matthew Wild <mwild1@gmail.com>
parents:
3350
diff
changeset
|
73 end |
662f2722f745
mod_password_policy: Export function to get policy in use by the module
Matthew Wild <mwild1@gmail.com>
parents:
3350
diff
changeset
|
74 |
841
0649883de4d3
mod_password_policy: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
75 function handler(event) |
0649883de4d3
mod_password_policy: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
76 local origin, stanza = event.origin, event.stanza; |
0649883de4d3
mod_password_policy: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
77 |
0649883de4d3
mod_password_policy: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
78 if stanza.attr.type == "set" then |
0649883de4d3
mod_password_policy: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
79 local query = stanza.tags[1]; |
0649883de4d3
mod_password_policy: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
80 |
0649883de4d3
mod_password_policy: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
81 local passwords = {}; |
0649883de4d3
mod_password_policy: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
82 |
0649883de4d3
mod_password_policy: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
83 local dataform = query:get_child("x", "jabber:x:data"); |
0649883de4d3
mod_password_policy: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
84 if dataform then |
0649883de4d3
mod_password_policy: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
85 for _,tag in ipairs(dataform.tags) do |
0649883de4d3
mod_password_policy: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
86 if tag.attr.var == "password" then |
0649883de4d3
mod_password_policy: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
87 table.insert(passwords, tag:get_child_text("value")); |
0649883de4d3
mod_password_policy: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
88 end |
0649883de4d3
mod_password_policy: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
89 end |
0649883de4d3
mod_password_policy: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
90 end |
0649883de4d3
mod_password_policy: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
91 |
0649883de4d3
mod_password_policy: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
92 table.insert(passwords, query:get_child_text("password")); |
0649883de4d3
mod_password_policy: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
93 |
4829
caf7e88dc9e5
mod_password_policy: Add check that password doesn't contain username
Matthew Wild <mwild1@gmail.com>
parents:
4828
diff
changeset
|
94 local additional_info = { |
caf7e88dc9e5
mod_password_policy: Add check that password doesn't contain username
Matthew Wild <mwild1@gmail.com>
parents:
4828
diff
changeset
|
95 username = origin.username; |
caf7e88dc9e5
mod_password_policy: Add check that password doesn't contain username
Matthew Wild <mwild1@gmail.com>
parents:
4828
diff
changeset
|
96 }; |
caf7e88dc9e5
mod_password_policy: Add check that password doesn't contain username
Matthew Wild <mwild1@gmail.com>
parents:
4828
diff
changeset
|
97 |
841
0649883de4d3
mod_password_policy: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
98 for _,password in ipairs(passwords) do |
4828
56eba4bca28f
mod_password_policy: Allow check_password() to indicate the policy that failed
Matthew Wild <mwild1@gmail.com>
parents:
3351
diff
changeset
|
99 if password then |
4829
caf7e88dc9e5
mod_password_policy: Add check that password doesn't contain username
Matthew Wild <mwild1@gmail.com>
parents:
4828
diff
changeset
|
100 local pw_ok, pw_err, pw_failed_policy = check_password(password, additional_info); |
4828
56eba4bca28f
mod_password_policy: Allow check_password() to indicate the policy that failed
Matthew Wild <mwild1@gmail.com>
parents:
3351
diff
changeset
|
101 if not pw_ok then |
56eba4bca28f
mod_password_policy: Allow check_password() to indicate the policy that failed
Matthew Wild <mwild1@gmail.com>
parents:
3351
diff
changeset
|
102 module:log("debug", "Password failed check against '%s' policy", pw_failed_policy); |
56eba4bca28f
mod_password_policy: Allow check_password() to indicate the policy that failed
Matthew Wild <mwild1@gmail.com>
parents:
3351
diff
changeset
|
103 origin.send(st.error_reply(stanza, "cancel", "not-acceptable", pw_err)); |
56eba4bca28f
mod_password_policy: Allow check_password() to indicate the policy that failed
Matthew Wild <mwild1@gmail.com>
parents:
3351
diff
changeset
|
104 return true; |
56eba4bca28f
mod_password_policy: Allow check_password() to indicate the policy that failed
Matthew Wild <mwild1@gmail.com>
parents:
3351
diff
changeset
|
105 end |
841
0649883de4d3
mod_password_policy: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
106 end |
0649883de4d3
mod_password_policy: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
107 end |
0649883de4d3
mod_password_policy: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
108 end |
0649883de4d3
mod_password_policy: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
109 end |
0649883de4d3
mod_password_policy: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
110 |
0649883de4d3
mod_password_policy: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
111 module:hook("iq/self/jabber:iq:register:query", handler, 10); |
0649883de4d3
mod_password_policy: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
112 module:hook("iq/host/jabber:iq:register:query", handler, 10); |
0649883de4d3
mod_password_policy: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
113 module:hook("stanza/iq/jabber:iq:register:query", handler, 10); |