annotate mod_password_policy/mod_password_policy.lua @ 5593:6d0574bfbf5d

mod_client_management: Include software version in table (when known) Showing software versions could be useful for statistical reasons, e.g. determining how quickly (or not) users upgrade, but most importantly for revoking vulnerable clients versions in case of a security issue.
author Kim Alvefur <zash@zash.se>
date Thu, 13 Jul 2023 23:26:02 +0200
parents bfd4af4caddc
children d3b69859553a
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
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);