mod_deny_omemo: Also reject actual OMEMO messages

Users might send/receive OMEMO messages using sessions established in
the past.  Let mod_deny_omemo also reject those.
This commit is contained in:
Holger Weiss 2018-08-17 02:02:47 +02:00
parent 7191ddd6f3
commit b7b6af8315
2 changed files with 46 additions and 10 deletions

View File

@ -12,7 +12,7 @@ Unless the configured access rule (called 'omemo' by default) returns
Requests to query the devicelist from other users are rejected. Requests Requests to query the devicelist from other users are rejected. Requests
to publish a devicelist are also rejected, and all OMEMO nodes referenced to publish a devicelist are also rejected, and all OMEMO nodes referenced
in that devicelist are removed. Incoming devicelist updates are silently in that devicelist are removed. Incoming devicelist updates are silently
dropped. dropped. OMEMO-encrypted messages are bounced with an error message.
CONFIGURATION CONFIGURATION

View File

@ -80,6 +80,8 @@ depends(_Host, _Opts) ->
%% ejabberd_hooks callbacks. %% ejabberd_hooks callbacks.
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
-spec user_send_packet({stanza() | drop, c2s_state()}) -> hook_result(). -spec user_send_packet({stanza() | drop, c2s_state()}) -> hook_result().
user_send_packet({#message{}, _C2SState} = Acc) ->
maybe_reject_msg(Acc);
user_send_packet({#iq{type = set, user_send_packet({#iq{type = set,
from = #jid{luser = LUser, lserver = LServer}, from = #jid{luser = LUser, lserver = LServer},
to = #jid{luser = LUser, lserver = LServer, to = #jid{luser = LUser, lserver = LServer,
@ -87,7 +89,7 @@ user_send_packet({#iq{type = set,
sub_els = [SubEl]}, _C2SState} = Acc) -> sub_els = [SubEl]}, _C2SState} = Acc) ->
try xmpp:decode(SubEl) of try xmpp:decode(SubEl) of
#pubsub{publish = Publish} -> #pubsub{publish = Publish} ->
maybe_reject(Publish, Acc); maybe_reject_iq(Publish, Acc);
_ -> _ ->
Acc Acc
catch _:{xmpp_codec, _Reason} -> catch _:{xmpp_codec, _Reason} ->
@ -102,7 +104,7 @@ user_send_packet({#iq{type = get,
FromS /= ToS -> FromS /= ToS ->
try xmpp:decode(SubEl) of try xmpp:decode(SubEl) of
#pubsub{items = Items} -> #pubsub{items = Items} ->
maybe_reject(Items, Acc); maybe_reject_iq(Items, Acc);
_ -> _ ->
Acc Acc
catch _:{xmpp_codec, _Reason} -> catch _:{xmpp_codec, _Reason} ->
@ -131,7 +133,7 @@ user_receive_packet({#message{} = Msg,
end end
end; end;
_ -> _ ->
Acc maybe_reject_msg(Acc)
end; end;
user_receive_packet(Acc) -> user_receive_packet(Acc) ->
Acc. Acc.
@ -139,11 +141,30 @@ user_receive_packet(Acc) ->
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
%% Internal functions. %% Internal functions.
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
-spec maybe_reject(ps_publish() | ps_items(), {iq(), c2s_state()}) -spec maybe_reject_msg({message(), c2s_state()})
-> {iq(), c2s_state()} | {stop, {drop, c2s_state()}}. -> {message(), c2s_state()} | {stop, {drop, c2s_state()}}.
maybe_reject(El, {#iq{type = Type, lang = Lang} = IQ, maybe_reject_msg({#message{lang = Lang} = Msg,
#{lserver := LServer, jid := JID} = C2SState} = Acc) -> #{lserver := LServer, jid := JID} = C2SState} = Acc) ->
Access = gen_mod:get_module_opt(LServer, ?MODULE, access), Access = gen_mod:get_module_opt(LServer, ?MODULE, access),
case acl:match_rule(LServer, Access, JID) of
allow ->
Acc;
deny ->
case is_omemo_msg(Msg) of
true ->
?DEBUG("Rejecting message from ~s", [jid:encode(JID)]),
bounce_error(Msg, Lang),
{stop, {drop, C2SState}};
false ->
Acc
end
end.
-spec maybe_reject_iq(ps_publish() | ps_items(), {iq(), c2s_state()})
-> {iq(), c2s_state()} | {stop, {drop, c2s_state()}}.
maybe_reject_iq(El, {#iq{type = Type, lang = Lang} = IQ,
#{lserver := LServer, jid := JID} = C2SState} = Acc) ->
Access = gen_mod:get_module_opt(LServer, ?MODULE, access),
case acl:match_rule(LServer, Access, JID) of case acl:match_rule(LServer, Access, JID) of
allow -> allow ->
Acc; Acc;
@ -157,9 +178,7 @@ maybe_reject(El, {#iq{type = Type, lang = Lang} = IQ,
set -> delete_nodes(JID, Nodes); set -> delete_nodes(JID, Nodes);
get -> ok get -> ok
end, end,
Txt = <<"OMEMO is disabled">>, bounce_error(IQ, Lang),
Err = xmpp:err_policy_violation(Txt, Lang),
ejabberd_router:route_error(IQ, Err),
{stop, {drop, C2SState}} {stop, {drop, C2SState}}
end end
end. end.
@ -198,3 +217,20 @@ delete_nodes(JID, Nodes) ->
lists:foreach(fun(Node) -> lists:foreach(fun(Node) ->
mod_pubsub:delete_node(LJID, Node, JID) mod_pubsub:delete_node(LJID, Node, JID)
end, Nodes). end, Nodes).
-spec is_omemo_msg(message()) -> boolean().
is_omemo_msg(#message{type = error}) ->
false;
is_omemo_msg(#message{sub_els = SubEls}) ->
case lists:keyfind(<<"encrypted">>, #xmlel.name, SubEls) of
#xmlel{attrs = Attrs} ->
lists:member({<<"xmlns">>, <<?NS_AXOLOTL>>}, Attrs);
false ->
false
end.
-spec bounce_error(stanza(), binary()) -> ok.
bounce_error(Pkt, Lang) ->
Txt = <<"OMEMO is disabled">>,
Err = xmpp:err_policy_violation(Txt, Lang),
ejabberd_router:route_error(Pkt, Err).