File

mod_muc_access_control/mod_muc_access_control.lua @ 5705:527c747711f3

mod_http_oauth2: Limit revocation to clients own tokens in strict mode RFC 7009 section 2.1 states: > The authorization server first validates the client credentials (in > case of a confidential client) and then verifies whether the token was > issued to the client making the revocation request. If this > validation fails, the request is refused and the client is informed of > the error by the authorization server as described below. The first part was already covered (in strict mode). This adds the later part using the hash of client_id recorded in 0860497152af It still seems weird to me that revoking a leaked token should not be allowed whoever might have discovered it, as that seems the responsible thing to do.
author Kim Alvefur <zash@zash.se>
date Sun, 29 Oct 2023 11:30:49 +0100
parent 3024:f54c80404ad3
line wrap: on
line source

local st = require "util.stanza";
local jid = require "util.jid";
local nodeprep = require "util.encodings".stringprep.nodeprep;

local unprepped_access_lists = module:get_option("muc_access_lists", {});
local access_lists = {};

-- Make sure all input is prepped
for unprepped_room_name, unprepped_list in pairs(unprepped_access_lists) do
	local prepped_room_name = nodeprep(unprepped_room_name);
	if not prepped_room_name then
		module:log("error", "Invalid room name: %s", unprepped_room_name);
	else
		local prepped_list = {};
		for _, unprepped_jid in ipairs(unprepped_list) do
			local prepped_jid = jid.prep(unprepped_jid);
			if not prepped_jid then
				module:log("error", "Invalid JID: %s", unprepped_jid);
			else
				prepped_list[prepped_jid] = true;
			end
		end
		access_lists[prepped_room_name] = prepped_list;
	end
end

local function is_restricted(room, who)
	local allowed = access_lists[room];

	if allowed == nil or allowed[who] or allowed[select(2, jid.split(who))] then
		return nil;
	end

	return "forbidden";
end

module:hook("presence/full", function(event)
	local stanza = event.stanza;

	if stanza.name == "presence" and stanza.attr.type == "unavailable" then   -- Leaving events get discarded
		return;
	end

	-- Get the room
	local room = jid.split(stanza.attr.to);
        if not room then return; end

	-- Get who has tried to join it
	local who = jid.bare(stanza.attr.from)

	-- Checking whether room is restricted
	local check_restricted = is_restricted(room, who)
	if check_restricted ~= nil then
		event.allowed = false;
		event.stanza.attr.type = 'error';
		return event.origin.send(st.error_reply(event.stanza, "cancel", "forbidden", "You're not allowed to enter this room: " .. check_restricted));
	end
end, 10);