From fedfe5427c7978f7000148f3226a156ff3a3d103 Mon Sep 17 00:00:00 2001 From: Alexey Shchepin Date: Mon, 16 Jan 2017 18:13:48 +0300 Subject: [PATCH] Add mod_block_strangers --- src/ejabberd_c2s.erl | 20 ++++++- src/mod_block_strangers.erl | 107 ++++++++++++++++++++++++++++++++++++ 2 files changed, 126 insertions(+), 1 deletion(-) create mode 100644 src/mod_block_strangers.erl diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index ecd6321d4..113be0910 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -546,7 +546,7 @@ process_iq_in(State, #iq{} = IQ) -> -spec process_message_in(state(), message()) -> {boolean(), state()}. process_message_in(State, #message{type = T} = Msg) -> - case privacy_check_packet(State, Msg, in) of + case filter_incoming_message(State, Msg) of allow -> {true, State}; deny when T == groupchat; T == headline -> @@ -561,6 +561,24 @@ process_message_in(State, #message{type = T} = Msg) -> {false, State} end. +filter_incoming_message(State, Msg) -> + case privacy_check_packet(State, Msg, in) of + allow -> + #{lserver := LServer} = State, + case ejabberd_hooks:run_fold( + c2s_filter_incoming_packet, + LServer, + allow, + [State, Msg]) of + allow -> + allow; + deny -> + deny + end; + deny -> + deny + end. + -spec process_presence_in(state(), presence()) -> {boolean(), state()}. process_presence_in(#{lserver := LServer, pres_a := PresA} = State0, #presence{from = From, to = To, type = T} = Pres) -> diff --git a/src/mod_block_strangers.erl b/src/mod_block_strangers.erl new file mode 100644 index 000000000..947970040 --- /dev/null +++ b/src/mod_block_strangers.erl @@ -0,0 +1,107 @@ +%%%------------------------------------------------------------------- +%%% File : mod_block_strangers.erl +%%% Author : Alexey Shchepin +%%% Purpose : Block packets from non-subscribers +%%% Created : 25 Dec 2016 by Alexey Shchepin +%%% +%%% +%%% ejabberd, Copyright (C) 2002-2017 ProcessOne +%%% +%%% This program is free software; you can redistribute it and/or +%%% modify it under the terms of the GNU General Public License as +%%% published by the Free Software Foundation; either version 2 of the +%%% License, or (at your option) any later version. +%%% +%%% This program is distributed in the hope that it will be useful, +%%% but WITHOUT ANY WARRANTY; without even the implied warranty of +%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%%% General Public License for more details. +%%% +%%% You should have received a copy of the GNU General Public License along +%%% with this program; if not, write to the Free Software Foundation, Inc., +%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +%%% +%%%------------------------------------------------------------------- +-module(mod_block_strangers). + +-author('alexey@process-one.net'). + +-behaviour(gen_mod). + +%% API +-export([start/2, stop/1, + depends/2, mod_opt_type/1]). + +-export([filter_packet/3]). + +-include("xmpp.hrl"). +-include("ejabberd.hrl"). +-include("logger.hrl"). + +-define(SETS, gb_sets). + +start(Host, _Opts) -> + ejabberd_hooks:add(c2s_filter_incoming_packet, Host, + ?MODULE, filter_packet, 50), + ok. + +stop(Host) -> + ejabberd_hooks:delete(c2s_filter_incoming_packet, Host, + ?MODULE, filter_packet, 50), + ok. + +filter_packet(deny = Acc, _State, _Msg) -> + Acc; +filter_packet(Acc, State, Msg) -> + From = Msg#message.from, + LFrom = jid:tolower(From), + LBFrom = jid:remove_resource(LFrom), + #{pres_a := PresA} = State, + case false%ejabberd_router:is_my_route(From#jid.lserver) + orelse (?SETS):is_element(LFrom, PresA) + orelse (?SETS):is_element(LBFrom, PresA) + orelse sets_bare_member(LBFrom, PresA) of + true -> + Acc; + false -> + #{lserver := LServer} = State, + Drop = + gen_mod:get_module_opt(LServer, ?MODULE, drop, + fun(B) when is_boolean(B) -> B end, + true), + Log = + gen_mod:get_module_opt(LServer, ?MODULE, log, + fun(B) when is_boolean(B) -> B end, + false), + if + Log -> + Packet = xmpp:encode(Msg, ?NS_CLIENT), + ?INFO_MSG("Drop packet: ~s", + [fxml:element_to_binary(Packet)]); + true -> + ok + end, + if + Drop -> + deny; + true -> + Acc + end + end. + + +sets_bare_member({U, S, <<"">>} = LBJID, Set) -> + case ?SETS:next(?SETS:iterator_from(LBJID, Set)) of + {{U, S, _}, _} -> true; + _ -> false + end. + + +depends(_Host, _Opts) -> + []. + +mod_opt_type(drop) -> + fun (B) when is_boolean(B) -> B end; +mod_opt_type(log) -> + fun (B) when is_boolean(B) -> B end; +mod_opt_type(_) -> [drop, log].