author | Matthew Wild <mwild1@gmail.com> |
Sat, 15 Oct 2022 19:42:55 +0100 | |
changeset 5075 | bc983da908e6 |
parent 4836 | bfd4af4caddc |
child 5822 | d3b69859553a |
permissions | -rw-r--r-- |
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 |
|
4836
bfd4af4caddc
mod_password_policy: Support for additional policies provided by other modules
Matthew Wild <mwild1@gmail.com>
parents:
4835
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:
4835
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:
4835
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:
4835
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; |
4833
caf7e88dc9e5
mod_password_policy: Add check that password doesn't contain username
Matthew Wild <mwild1@gmail.com>
parents:
4832
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:
4832
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:
4832
diff
changeset
|
22 |
end |
841
0649883de4d3
mod_password_policy: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
23 |
|
4836
bfd4af4caddc
mod_password_policy: Support for additional policies provided by other modules
Matthew Wild <mwild1@gmail.com>
parents:
4835
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:
4835
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:
4835
diff
changeset
|
26 |
|
bfd4af4caddc
mod_password_policy: Support for additional policies provided by other modules
Matthew Wild <mwild1@gmail.com>
parents:
4835
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:
4835
diff
changeset
|
28 |
|
bfd4af4caddc
mod_password_policy: Support for additional policies provided by other modules
Matthew Wild <mwild1@gmail.com>
parents:
4835
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:
4835
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:
4835
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:
4835
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:
4835
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:
4835
diff
changeset
|
34 |
end, function (event) |
bfd4af4caddc
mod_password_policy: Support for additional policies provided by other modules
Matthew Wild <mwild1@gmail.com>
parents:
4835
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:
4835
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:
4835
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:
4835
diff
changeset
|
38 |
end); |
841
0649883de4d3
mod_password_policy: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
39 |
|
4833
caf7e88dc9e5
mod_password_policy: Add check that password doesn't contain username
Matthew Wild <mwild1@gmail.com>
parents:
4832
diff
changeset
|
40 |
function check_password(password, additional_info) |
4834
af6143cf7d22
mod_password_policy: Hard failure on missing/empty passwords
Matthew Wild <mwild1@gmail.com>
parents:
4833
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:
4833
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:
4833
diff
changeset
|
43 |
end |
af6143cf7d22
mod_password_policy: Hard failure on missing/empty passwords
Matthew Wild <mwild1@gmail.com>
parents:
4833
diff
changeset
|
44 |
|
3354
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 |
4832
56eba4bca28f
mod_password_policy: Allow check_password() to indicate the policy that failed
Matthew Wild <mwild1@gmail.com>
parents:
3355
diff
changeset
|
46 |
return nil, ("Password is too short (minimum %d characters)"):format(options.length), "length"; |
3354
cb26d04b391c
mod_password_policy: Return error as second result explaining failure reason
Matthew Wild <mwild1@gmail.com>
parents:
845
diff
changeset
|
47 |
end |
4833
caf7e88dc9e5
mod_password_policy: Add check that password doesn't contain username
Matthew Wild <mwild1@gmail.com>
parents:
4832
diff
changeset
|
48 |
|
caf7e88dc9e5
mod_password_policy: Add check that password doesn't contain username
Matthew Wild <mwild1@gmail.com>
parents:
4832
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:
4832
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:
4832
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:
4832
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:
4832
diff
changeset
|
53 |
end |
caf7e88dc9e5
mod_password_policy: Add check that password doesn't contain username
Matthew Wild <mwild1@gmail.com>
parents:
4832
diff
changeset
|
54 |
end |
4836
bfd4af4caddc
mod_password_policy: Support for additional policies provided by other modules
Matthew Wild <mwild1@gmail.com>
parents:
4835
diff
changeset
|
55 |
|
bfd4af4caddc
mod_password_policy: Support for additional policies provided by other modules
Matthew Wild <mwild1@gmail.com>
parents:
4835
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:
4835
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:
4835
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:
4835
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:
4835
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:
4835
diff
changeset
|
61 |
end |
bfd4af4caddc
mod_password_policy: Support for additional policies provided by other modules
Matthew Wild <mwild1@gmail.com>
parents:
4835
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:
4835
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:
4835
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:
4835
diff
changeset
|
65 |
end |
bfd4af4caddc
mod_password_policy: Support for additional policies provided by other modules
Matthew Wild <mwild1@gmail.com>
parents:
4835
diff
changeset
|
66 |
end |
bfd4af4caddc
mod_password_policy: Support for additional policies provided by other modules
Matthew Wild <mwild1@gmail.com>
parents:
4835
diff
changeset
|
67 |
|
3354
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 |
|
4835
5a42cb84c8ee
mod_password_policy: Silence luacheck warning for intentional global
Matthew Wild <mwild1@gmail.com>
parents:
4834
diff
changeset
|
71 |
function get_policy() --luacheck: ignore 131/get_policy |
3355
662f2722f745
mod_password_policy: Export function to get policy in use by the module
Matthew Wild <mwild1@gmail.com>
parents:
3354
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:
3354
diff
changeset
|
73 |
end |
662f2722f745
mod_password_policy: Export function to get policy in use by the module
Matthew Wild <mwild1@gmail.com>
parents:
3354
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 |
|
4833
caf7e88dc9e5
mod_password_policy: Add check that password doesn't contain username
Matthew Wild <mwild1@gmail.com>
parents:
4832
diff
changeset
|
94 |
local additional_info = { |
caf7e88dc9e5
mod_password_policy: Add check that password doesn't contain username
Matthew Wild <mwild1@gmail.com>
parents:
4832
diff
changeset
|
95 |
username = origin.username; |
caf7e88dc9e5
mod_password_policy: Add check that password doesn't contain username
Matthew Wild <mwild1@gmail.com>
parents:
4832
diff
changeset
|
96 |
}; |
caf7e88dc9e5
mod_password_policy: Add check that password doesn't contain username
Matthew Wild <mwild1@gmail.com>
parents:
4832
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 |
4832
56eba4bca28f
mod_password_policy: Allow check_password() to indicate the policy that failed
Matthew Wild <mwild1@gmail.com>
parents:
3355
diff
changeset
|
99 |
if password then |
4833
caf7e88dc9e5
mod_password_policy: Add check that password doesn't contain username
Matthew Wild <mwild1@gmail.com>
parents:
4832
diff
changeset
|
100 |
local pw_ok, pw_err, pw_failed_policy = check_password(password, additional_info); |
4832
56eba4bca28f
mod_password_policy: Allow check_password() to indicate the policy that failed
Matthew Wild <mwild1@gmail.com>
parents:
3355
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:
3355
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:
3355
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:
3355
diff
changeset
|
104 |
return true; |
56eba4bca28f
mod_password_policy: Allow check_password() to indicate the policy that failed
Matthew Wild <mwild1@gmail.com>
parents:
3355
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); |