changeset 1005:591590de34ef

mod_muc_ban_ip: When a user is banned from a MUC, ban their IP from the MUC also (works for remote rooms too)
author Matthew Wild <mwild1@gmail.com>
date Thu, 09 May 2013 10:15:47 +0100
parents 290c21a5e0ee
children 9c88960b0f81
files mod_muc_ban_ip/mod_muc_ban_ip.lua
diffstat 1 files changed, 60 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mod_muc_ban_ip/mod_muc_ban_ip.lua	Thu May 09 10:15:47 2013 +0100
@@ -0,0 +1,60 @@
+module:set_global();
+
+local jid_bare = require "util.jid".bare;
+local st = require "util.stanza";
+local xmlns_muc_user = "http://jabber.org/protocol/muc#user";
+
+local ip_bans = module:shared("bans");
+local full_sessions = prosody.full_sessions;
+
+local function ban_ip(session, from)
+	local ip = session.ip;
+	if not ip then
+		module:log("warn", "Failed to ban IP (IP unknown) for %s", session.full_jid);
+		return;
+	end
+	local banned_from = ip_bans[ip];
+	if not banned_from then
+		banned_from = {};
+		ip_bans[ip] = banned_from;
+	end
+	banned_from[from] = true;
+	module:log("debug", "Banned IP address %s from %s", ip, from);
+end
+
+function check_for_incoming_ban(event)
+	local stanza = event.stanza;
+	local to_session = full_sessions[stanza.attr.to];
+	if to_session then
+		local directed = to_session.directed;
+		local from = stanza.attr.from;
+		if directed and directed[from] and stanza.attr.type == "unavailable" then
+			-- This is a stanza from somewhere we sent directed presence to (may be a MUC)
+			local x = stanza:get_child("x", xmlns_muc_user);
+			if x then
+				for status in x:childtags("status") do
+					if status.attr.code == '301' then
+						ban_ip(to_session, jid_bare(from));
+					end
+				end
+			end
+		end
+	end
+end
+
+function check_for_ban(event)
+	local ip = event.origin.ip;
+	local to = jid_bare(event.stanza.attr.to);
+	if ip_bans[ip] and ip_bans[ip][to] then
+		event.origin.send(st.error_reply(event.stanza, "auth", "forbidden")
+			:tag("x", { xmlns = xmlns_muc_user })
+				:tag("status", { code = '301' }));
+		return true;
+	end
+	module:log("debug", "Not banned: %s from %s", ip, to)
+end
+
+function module.add_host(module)
+	module:hook("presence/full", check_for_incoming_ban);
+	module:hook("pre-presence/full", check_for_ban);
+end