From cb5bdc12af23d3af0ae5fd3e132a7b59f6f5773c Mon Sep 17 00:00:00 2001 From: Matthew Stickney Date: Sat, 18 Jan 2025 13:57:26 -0500 Subject: [PATCH] Accept non-privileged IQs from XEP-0356 privileged components. mod_privilege current drops any non-privileged IQ received from a component with an error about it not being properly wrapped. While this might represent a mistake on the part of the component, it means that well- behaved components can no longer send non-privileged IQs (something they normally can do if mod_privilege isn't enabled). Since mod_privilege is intended to grant additional permissions, and not remove existing ones, route non-privileged IQs received from the component normally. This also removes the special-case for roster-query IQ stanzas, since those are also non-privileged and will be routed along with any other non-privileged IQ packet. This mirrors the privileged-IQ/everything-else structure of the XEP, which defined the handling of privileged IQ stanzas and leaves all other IQ stanzas as defined in their own specs. To make this clearer, the predicate function now returns distinct results indicating privileged IQs, non-privileged IQs, and error conditions, rather than treating non-privilege IQs as an error that gets handled by routing the packet normally. --- src/mod_privilege.erl | 31 +++++++++---------------------- 1 file changed, 9 insertions(+), 22 deletions(-) diff --git a/src/mod_privilege.erl b/src/mod_privilege.erl index bdf512f34fd..862f0c0be9e 100644 --- a/src/mod_privilege.erl +++ b/src/mod_privilege.erl @@ -272,7 +272,7 @@ component_send_packet({#iq{from = From, Permissions = get_permissions(ServerHost), Result = case {maps:find(Host, Permissions), get_iq_encapsulated_details(IQ)} of - {{ok, Access}, {ok, EncapType, EncapNs, EncapFrom, EncIq}} + {{ok, Access}, {privileged_iq, EncapType, EncapNs, EncapFrom, EncIq}} when (EncapType == Type) and ((EncapFrom == undefined) or (EncapFrom == To)) -> NsPermissions = proplists:get_value(iq, Access, []), Permission = @@ -297,20 +297,18 @@ component_send_packet({#iq{from = From, %% Component is disconnected ?INFO_MSG("IQ not forwarded: Component seems disconnected", []), drop; - {_, {ok, E, _, _, _}} when E /= Type -> + {_, {privileged_iq, E, _, _, _}} when E /= Type -> ?INFO_MSG("IQ not forwarded: The encapsulated IQ stanza type=~p " "does not match the top-level IQ stanza type=~p", [E, Type]), drop; - {_, {ok, _, _, EF, _}} when (EF /= undefined) and (EF /= To) -> + {_, {privileged_iq, _, _, EF, _}} when (EF /= undefined) and (EF /= To) -> ?INFO_MSG("IQ not forwarded: The FROM attribute in the encapsulated " "IQ stanza and the TO in top-level IQ stanza do not match", []), drop; - {_, {error, no_privileged_iq, _Err}} -> - ?INFO_MSG("IQ not forwarded: Component tried to send not wrapped IQ stanza.", []), - drop; - {_, {error, roster_query, _Err}} -> + {_, {unprivileged_iq}} -> + ?DEBUG("Component ~ts sent a not-wrapped IQ stanza, routing it as-is.", [From#jid.lserver]), IQ; {_, {error, ErrType, _Err}} -> ?INFO_MSG("IQ not forwarded: Component tried to send not valid IQ stanza: ~p.", @@ -566,7 +564,8 @@ forward_message(#message{to = To} = Msg) -> %% @format-begin -spec get_iq_encapsulated_details(iq()) -> - {ok, iq_type(), binary(), jid(), iq()} | + {privileged_iq, iq_type(), binary(), jid(), iq()} | + {unprivileged_iq} | {error, Why :: atom(), stanza_error()}. get_iq_encapsulated_details(#iq{sub_els = [IqSub]} = Msg) -> Lang = xmpp:get_lang(Msg), @@ -575,21 +574,9 @@ get_iq_encapsulated_details(#iq{sub_els = [IqSub]} = Msg) -> [IqSubSub] = xmpp:get_els(IqSub), [Element] = xmpp:get_els(IqSubSub), Ns = xmpp:get_ns(Element), - {ok, EncapsulatedType, Ns, From, EncIq}; + {privileged_iq, EncapsulatedType, Ns, From, EncIq}; _ -> - try xmpp:try_subtag(Msg, #roster_query{}) of - #roster_query{} -> - {error, roster_query, xmpp:err_bad_request()}; - _ -> - Txt = ?T("No element found"), - Err = xmpp:err_bad_request(Txt, Lang), - {error, no_privileged_iq, Err} - catch - _:{xmpp_codec, Why} -> - Txt = xmpp:io_format_error(Why), - Err = xmpp:err_bad_request(Txt, Lang), - {error, codec_error, Err} - end + {unprivileged_iq} catch _:{xmpp_codec, Why} -> Txt = xmpp:io_format_error(Why),