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";