1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
|
local posix = require "posix.grp";
local pam = require "pam";
local new_sasl = require "util.sasl".new;
local sha2 = require "sha2";
local group = module:get_option_string("custom_auth_group", "xmpp");
local pam_module = module:get_option_string("custom_pam_module", "xmpp");
local alias_file = module:get_option_string("custom_alias_file");
local alias_secret_file = module:get_option_string("custom_alias_secret_file");
local log_secrets = module:get_option_boolean("custom_log_secrets", false);
function is_real_user(username)
for i,v in ipairs(posix.getgrnam(group).gr_mem) do
if username == v then
return true;
end
end
return false;
end
function is_alias(username)
local f = assert(io.open(alias_file, "r"));
local found = false;
while true do
local line = f:read("*line");
if line == nil then break; end
if string.lower(line) == string.lower(username .. "@" .. module.host) then found = true; end
end
f:close();
module:log("info", "is_alias(%s) = %s # %s", username, tostring(found), username .. "@" .. module.host);
return found;
end
function alias_pw(username)
local f = assert(io.open(alias_secret_file, "r"));
local secret = f:read("*all");
f:close();
local auth = sha2.sha512hex(username .. "@" .. module.host .. secret);
if log_secrets then
module:log("debug", "Expecting ‘%s’ as auth-secret for %s", auth, username .. "@" .. module.host);
end
return auth;
end
function user_exists(username)
return is_real_user(username) or is_alias(username);
end
function pam_auth(username, password)
local h, err = pam.start(pam_module, username, {
function (t)
local responses = {}
for i,m in ipairs(t) do
if m[1] == pam.PROMPT_ECHO_OFF then
responses[i] = {password, 0};
elseif m[1] == pam.PROMPT_ECHO_ON then
responses[i] = {username, 0};
else
responses[i] = {"", 0};
end
end
return responses
end
});
if h and h:authenticate() and h:endx(pam.SUCCESS) then
return true, true;
end
return nil, true;
end
function get_sasl_handler()
return new_sasl(module.host, {
plain_test = function(sasl, username, password, ...)
if is_alias(username) then
if password == alias_pw(username) then
return true, true;
else
return nil, true;
end
elseif is_real_user(username) then
return pam_auth(username, password);
else
return nil, true;
end
end
});
end
module:provides"auth";
|