mod_isolate_host/mod_isolate_host.lua
author Jonas Schäfer <jonas@wielicki.name>
Sat, 01 Apr 2023 12:03:08 +0200
changeset 5300 0f5657db1cfc
parent 5100 16db0a6e868c
child 5301 4bba2d27ffaf
permissions -rw-r--r--
mod_isolate_host: handle server-generated stanzas The hook for setting the no_host_isolation is only called for c2s sessions. This does not work for stanzas generated by the server, such as PEP notifications or presence probe answers. To handle that, we do per-stanza checks for the case that the origin is local.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
1011
9466efd10af9 mod_isolate_host: Prevent communication between hosts, even internal ones
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     1
local jid = require "util.jid";
5008
bc75fc9400ae mod_isolate_host: Switch to module:may() (back compatible via compat_roles)
Matthew Wild <mwild1@gmail.com>
parents: 1796
diff changeset
     2
local jid_bare, jid_host = jid.bare, jid.host;
1011
9466efd10af9 mod_isolate_host: Prevent communication between hosts, even internal ones
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     3
local set = require "util.set";
9466efd10af9 mod_isolate_host: Prevent communication between hosts, even internal ones
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     4
local st = require "util.stanza";
9466efd10af9 mod_isolate_host: Prevent communication between hosts, even internal ones
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     5
9466efd10af9 mod_isolate_host: Prevent communication between hosts, even internal ones
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     6
local stanza_types = set.new{"message", "presence", "iq"};
9466efd10af9 mod_isolate_host: Prevent communication between hosts, even internal ones
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     7
local jid_types = set.new{"bare", "full", "host"};
9466efd10af9 mod_isolate_host: Prevent communication between hosts, even internal ones
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     8
9466efd10af9 mod_isolate_host: Prevent communication between hosts, even internal ones
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     9
local except_domains = module:get_option_inherited_set("isolate_except_domains", {});
9466efd10af9 mod_isolate_host: Prevent communication between hosts, even internal ones
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    10
local except_users = module:get_option_inherited_set("isolate_except_users", {});
9466efd10af9 mod_isolate_host: Prevent communication between hosts, even internal ones
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    11
5008
bc75fc9400ae mod_isolate_host: Switch to module:may() (back compatible via compat_roles)
Matthew Wild <mwild1@gmail.com>
parents: 1796
diff changeset
    12
if not module.may then
bc75fc9400ae mod_isolate_host: Switch to module:may() (back compatible via compat_roles)
Matthew Wild <mwild1@gmail.com>
parents: 1796
diff changeset
    13
	module:depends("compat_roles");
bc75fc9400ae mod_isolate_host: Switch to module:may() (back compatible via compat_roles)
Matthew Wild <mwild1@gmail.com>
parents: 1796
diff changeset
    14
end
bc75fc9400ae mod_isolate_host: Switch to module:may() (back compatible via compat_roles)
Matthew Wild <mwild1@gmail.com>
parents: 1796
diff changeset
    15
1011
9466efd10af9 mod_isolate_host: Prevent communication between hosts, even internal ones
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    16
function check_stanza(event)
9466efd10af9 mod_isolate_host: Prevent communication between hosts, even internal ones
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    17
	local origin, stanza = event.origin, event.stanza;
9466efd10af9 mod_isolate_host: Prevent communication between hosts, even internal ones
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    18
	if origin.no_host_isolation then return; end
5008
bc75fc9400ae mod_isolate_host: Switch to module:may() (back compatible via compat_roles)
Matthew Wild <mwild1@gmail.com>
parents: 1796
diff changeset
    19
	local to_host = jid_host(event.stanza.attr.to);
1011
9466efd10af9 mod_isolate_host: Prevent communication between hosts, even internal ones
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    20
	if to_host and to_host ~= origin.host and not except_domains:contains(to_host) then
9466efd10af9 mod_isolate_host: Prevent communication between hosts, even internal ones
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    21
		if to_host:match("^[^.]+%.(.+)$") == origin.host then -- Permit subdomains
9466efd10af9 mod_isolate_host: Prevent communication between hosts, even internal ones
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    22
			except_domains:add(to_host);
9466efd10af9 mod_isolate_host: Prevent communication between hosts, even internal ones
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    23
			return;
9466efd10af9 mod_isolate_host: Prevent communication between hosts, even internal ones
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    24
		end
5300
0f5657db1cfc mod_isolate_host: handle server-generated stanzas
Jonas Schäfer <jonas@wielicki.name>
parents: 5100
diff changeset
    25
		if origin.type == "local" then
0f5657db1cfc mod_isolate_host: handle server-generated stanzas
Jonas Schäfer <jonas@wielicki.name>
parents: 5100
diff changeset
    26
			-- this is code-generated, which means that set_session_isolation_flag has never triggered.
0f5657db1cfc mod_isolate_host: handle server-generated stanzas
Jonas Schäfer <jonas@wielicki.name>
parents: 5100
diff changeset
    27
			-- we need to check explicitly.
0f5657db1cfc mod_isolate_host: handle server-generated stanzas
Jonas Schäfer <jonas@wielicki.name>
parents: 5100
diff changeset
    28
			if not is_jid_isolated(jid_bare(event.stanza.attr.from)) then
0f5657db1cfc mod_isolate_host: handle server-generated stanzas
Jonas Schäfer <jonas@wielicki.name>
parents: 5100
diff changeset
    29
				module:log("debug", "server-generated stanza from %s is allowed, as the jid is not isolated", event.stanza.attr.from);
0f5657db1cfc mod_isolate_host: handle server-generated stanzas
Jonas Schäfer <jonas@wielicki.name>
parents: 5100
diff changeset
    30
				return;
0f5657db1cfc mod_isolate_host: handle server-generated stanzas
Jonas Schäfer <jonas@wielicki.name>
parents: 5100
diff changeset
    31
			end
0f5657db1cfc mod_isolate_host: handle server-generated stanzas
Jonas Schäfer <jonas@wielicki.name>
parents: 5100
diff changeset
    32
		end
1011
9466efd10af9 mod_isolate_host: Prevent communication between hosts, even internal ones
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    33
		module:log("warn", "Forbidding stanza from %s to %s", stanza.attr.from or origin.full_jid, stanza.attr.to);
9466efd10af9 mod_isolate_host: Prevent communication between hosts, even internal ones
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    34
		origin.send(st.error_reply(stanza, "auth", "forbidden", "Communication with "..to_host.." is not available"));
9466efd10af9 mod_isolate_host: Prevent communication between hosts, even internal ones
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    35
		return true;
9466efd10af9 mod_isolate_host: Prevent communication between hosts, even internal ones
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    36
	end
9466efd10af9 mod_isolate_host: Prevent communication between hosts, even internal ones
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    37
end
9466efd10af9 mod_isolate_host: Prevent communication between hosts, even internal ones
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    38
9466efd10af9 mod_isolate_host: Prevent communication between hosts, even internal ones
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    39
for stanza_type in stanza_types do
9466efd10af9 mod_isolate_host: Prevent communication between hosts, even internal ones
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    40
	for jid_type in jid_types do
1796
8e19b943c2cd mod_isolate_host: Bump event hook priorities to make sure they are above the core plugins
Kim Alvefur <zash@zash.se>
parents: 1011
diff changeset
    41
		module:hook("pre-"..stanza_type.."/"..jid_type, check_stanza, 1);
1011
9466efd10af9 mod_isolate_host: Prevent communication between hosts, even internal ones
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    42
	end
9466efd10af9 mod_isolate_host: Prevent communication between hosts, even internal ones
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    43
end
9466efd10af9 mod_isolate_host: Prevent communication between hosts, even internal ones
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    44
5008
bc75fc9400ae mod_isolate_host: Switch to module:may() (back compatible via compat_roles)
Matthew Wild <mwild1@gmail.com>
parents: 1796
diff changeset
    45
module:default_permission("prosody:admin", "xmpp:federate");
bc75fc9400ae mod_isolate_host: Switch to module:may() (back compatible via compat_roles)
Matthew Wild <mwild1@gmail.com>
parents: 1796
diff changeset
    46
5300
0f5657db1cfc mod_isolate_host: handle server-generated stanzas
Jonas Schäfer <jonas@wielicki.name>
parents: 5100
diff changeset
    47
function is_jid_isolated(bare_jid)
0f5657db1cfc mod_isolate_host: handle server-generated stanzas
Jonas Schäfer <jonas@wielicki.name>
parents: 5100
diff changeset
    48
	if module:may("xmpp:federate", bare_jid) or except_users:contains(bare_jid) then
0f5657db1cfc mod_isolate_host: handle server-generated stanzas
Jonas Schäfer <jonas@wielicki.name>
parents: 5100
diff changeset
    49
		return false;
0f5657db1cfc mod_isolate_host: handle server-generated stanzas
Jonas Schäfer <jonas@wielicki.name>
parents: 5100
diff changeset
    50
	else
0f5657db1cfc mod_isolate_host: handle server-generated stanzas
Jonas Schäfer <jonas@wielicki.name>
parents: 5100
diff changeset
    51
		return true;
0f5657db1cfc mod_isolate_host: handle server-generated stanzas
Jonas Schäfer <jonas@wielicki.name>
parents: 5100
diff changeset
    52
	end
0f5657db1cfc mod_isolate_host: handle server-generated stanzas
Jonas Schäfer <jonas@wielicki.name>
parents: 5100
diff changeset
    53
end
0f5657db1cfc mod_isolate_host: handle server-generated stanzas
Jonas Schäfer <jonas@wielicki.name>
parents: 5100
diff changeset
    54
0f5657db1cfc mod_isolate_host: handle server-generated stanzas
Jonas Schäfer <jonas@wielicki.name>
parents: 5100
diff changeset
    55
function set_session_isolation_flag(event)
1011
9466efd10af9 mod_isolate_host: Prevent communication between hosts, even internal ones
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    56
	local session = event.session;
9466efd10af9 mod_isolate_host: Prevent communication between hosts, even internal ones
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    57
	local bare_jid = jid_bare(session.full_jid);
5300
0f5657db1cfc mod_isolate_host: handle server-generated stanzas
Jonas Schäfer <jonas@wielicki.name>
parents: 5100
diff changeset
    58
	if not is_jid_isolated(bare_jid) then
1011
9466efd10af9 mod_isolate_host: Prevent communication between hosts, even internal ones
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    59
		session.no_host_isolation = true;
9466efd10af9 mod_isolate_host: Prevent communication between hosts, even internal ones
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    60
	end
9466efd10af9 mod_isolate_host: Prevent communication between hosts, even internal ones
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    61
	module:log("debug", "%s is %sisolated", session.full_jid or "[?]", session.no_host_isolation and "" or "not ");
9466efd10af9 mod_isolate_host: Prevent communication between hosts, even internal ones
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    62
end
9466efd10af9 mod_isolate_host: Prevent communication between hosts, even internal ones
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    63
5300
0f5657db1cfc mod_isolate_host: handle server-generated stanzas
Jonas Schäfer <jonas@wielicki.name>
parents: 5100
diff changeset
    64
module:hook("resource-bind", set_session_isolation_flag);