summaryrefslogtreecommitdiff
path: root/mod_auth_custom/mod_auth_custom.lua
blob: 1e996cb237288769805cfab37f12c67820bc5d32 (plain)
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";