Mercurial > prosody-modules
view mod_auth_ldap/mod_auth_ldap.lua @ 5170:4d6af8950016
mod_muc_moderation: Derive role from reserved nickname if occupant
When using a different client to moderate than the one used to
participate in the chat, e.g. a command line tool like clix, there's no
occupant and no role to use in the permission check. Previously the
default role based on affiliation was used. Now if you are present in
the room using your reserved nick, the role you have there is used in
the permission check instead of the default affiliation-derived role.
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Sun, 19 Feb 2023 18:17:37 +0100 |
parents | f2b29183ef08 |
children |
line wrap: on
line source
-- mod_auth_ldap local jid_split = require "util.jid".split; local new_sasl = require "util.sasl".new; local lualdap = require "lualdap"; local function ldap_filter_escape(s) return (s:gsub("[*()\\%z]", function(c) return ("\\%02x"):format(c:byte()) end)); end -- Config options local ldap_server = module:get_option_string("ldap_server", "localhost"); local ldap_rootdn = module:get_option_string("ldap_rootdn", ""); local ldap_password = module:get_option_string("ldap_password", ""); local ldap_tls = module:get_option_boolean("ldap_tls"); local ldap_scope = module:get_option_string("ldap_scope", "subtree"); local ldap_filter = module:get_option_string("ldap_filter", "(uid=$user)"):gsub("%%s", "$user", 1); local ldap_base = assert(module:get_option_string("ldap_base"), "ldap_base is a required option for ldap"); local ldap_mode = module:get_option_string("ldap_mode", "bind"); local ldap_admins = module:get_option_string("ldap_admin_filter", module:get_option_string("ldap_admins")); -- COMPAT with mistake in documentation local host = ldap_filter_escape(module:get_option_string("realm", module.host)); -- Initiate connection local ld = nil; module.unload = function() if ld then pcall(ld, ld.close); end end function ldap_do_once(method, ...) if ld == nil then local err; ld, err = lualdap.open_simple(ldap_server, ldap_rootdn, ldap_password, ldap_tls); if not ld then return nil, err, "reconnect"; end end -- luacheck: ignore 411/success local success, iterator, invariant, initial = pcall(ld[method], ld, ...); if not success then ld = nil; return nil, iterator, "search"; end local success, dn, attr = pcall(iterator, invariant, initial); if not success then ld = nil; return success, dn, "iter"; end return dn, attr, "return"; end function ldap_do(method, retry_count, ...) local dn, attr, where; for _=1,1+retry_count do dn, attr, where = ldap_do_once(method, ...); if dn or not(attr) then break; end -- nothing or something found module:log("warn", "LDAP: %s %s (in %s)", tostring(dn), tostring(attr), where); -- otherwise retry end if not dn and attr then module:log("error", "LDAP: %s", tostring(attr)); end return dn, attr; end function get_user(username) module:log("debug", "get_user(%q)", username); return ldap_do("search", 2, { base = ldap_base; scope = ldap_scope; sizelimit = 1; filter = ldap_filter:gsub("%$(%a+)", { user = ldap_filter_escape(username); host = host; }); }); end local provider = {}; function provider.create_user(username, password) -- luacheck: ignore 212 return nil, "Account creation not available with LDAP."; end function provider.user_exists(username) return not not get_user(username); end function provider.set_password(username, password) local dn, attr = get_user(username); if not dn then return nil, attr end if attr.userPassword == password then return true end return ldap_do("modify", 2, dn, { '=', userPassword = password }); end if ldap_mode == "getpasswd" then function provider.get_password(username) local dn, attr = get_user(username); if dn and attr then return attr.userPassword; end end function provider.test_password(username, password) return provider.get_password(username) == password; end function provider.get_sasl_handler() return new_sasl(module.host, { plain = function(sasl, username) -- luacheck: ignore 212/sasl local password = provider.get_password(username); if not password then return "", nil; end return password, true; end }); end elseif ldap_mode == "bind" then local function test_password(userdn, password) local ok, err = lualdap.open_simple(ldap_server, userdn, password, ldap_tls); if not ok then module:log("debug", "ldap open_simple error: %s", err); end return not not ok; end function provider.test_password(username, password) local dn = get_user(username); if not dn then return end return test_password(dn, password) end function provider.get_sasl_handler() return new_sasl(module.host, { plain_test = function(sasl, username, password) -- luacheck: ignore 212/sasl return provider.test_password(username, password), true; end }); end else module:log("error", "Unsupported ldap_mode %s", tostring(ldap_mode)); end if ldap_admins then function provider.is_admin(jid) local username, user_host = jid_split(jid); if user_host ~= module.host then return false; end return ldap_do("search", 2, { base = ldap_base; scope = ldap_scope; sizelimit = 1; filter = ldap_admins:gsub("%$(%a+)", { user = ldap_filter_escape(username); host = host; }); }); end end module:provides("auth", provider);