diff options
Diffstat (limited to 'src/mod_privilege.erl')
-rw-r--r-- | src/mod_privilege.erl | 639 |
1 files changed, 312 insertions, 327 deletions
diff --git a/src/mod_privilege.erl b/src/mod_privilege.erl index af6dacec4..50212b7ae 100644 --- a/src/mod_privilege.erl +++ b/src/mod_privilege.erl @@ -1,363 +1,348 @@ -%%%-------------------------------------------------------------------------------------- -%%% File : mod_privilege.erl -%%% Author : Anna Mukharram <amuhar3@gmail.com> -%%% Purpose : This module is an implementation for XEP-0356: Privileged Entity -%%%-------------------------------------------------------------------------------------- - +%%%------------------------------------------------------------------- +%%% @author Evgeny Khramtsov <ekhramtsov@process-one.net> +%%% @copyright (C) 2016, Evgeny Khramtsov +%%% @doc +%%% +%%% @end +%%% Created : 11 Nov 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net> +%%%------------------------------------------------------------------- -module(mod_privilege). --author('amuhar3@gmail.com'). +-behaviour(gen_server). +-behaviour(gen_mod). --protocol({xep, 0356, '0.2.1'}). +%% API +-export([start_link/2]). +-export([start/2, stop/1, mod_opt_type/1, depends/2]). +%% gen_server callbacks +-export([init/1, handle_call/3, handle_cast/2, handle_info/2, + terminate/2, code_change/3]). +-export([component_connected/1, component_disconnected/2, + roster_access/2, process_message/3, + process_presence_out/4, process_presence_in/5]). --export([advertise_permissions/1, initial_presences/1, process_presence/1, - process_roster_presence/1, compare_presences/2, - process_message/4, process_iq/4]). +-include("ejabberd.hrl"). +-include("logger.hrl"). +-include("xmpp.hrl"). --include("ejabberd_service.hrl"). +-record(state, {server_host = <<"">> :: binary(), + permissions = dict:new() :: ?TDICT}). --include("mod_privacy.hrl"). +%%%=================================================================== +%%% API +%%%=================================================================== +start_link(Host, Opts) -> + Proc = gen_mod:get_module_proc(Host, ?MODULE), + gen_server:start_link({local, Proc}, ?MODULE, [Host, Opts], []). -%%%-------------------------------------------------------------------------------------- -%%% Functions to advertise services of allowed permission -%%%-------------------------------------------------------------------------------------- +start(Host, Opts) -> + Proc = gen_mod:get_module_proc(Host, ?MODULE), + PingSpec = {Proc, {?MODULE, start_link, [Host, Opts]}, + transient, 2000, worker, [?MODULE]}, + supervisor:start_child(ejabberd_sup, PingSpec). --spec permissions(binary(), binary(), list()) -> xmlel(). +stop(Host) -> + Proc = gen_mod:get_module_proc(Host, ?MODULE), + gen_server:call(Proc, stop), + supervisor:delete_child(ejabberd_sup, Proc). -permissions(From, To, PrivAccess) -> - Perms = lists:map(fun({Access, Type}) -> - ?DEBUG("Advertise service ~s of allowed permission: ~s = ~s~n", - [To, Access, Type]), - #xmlel{name = <<"perm">>, - attrs = [{<<"access">>, - atom_to_binary(Access,latin1)}, - {<<"type">>, Type}]} - end, PrivAccess), - Stanza = #xmlel{name = <<"privilege">>, - attrs = [{<<"xmlns">> ,?NS_PRIVILEGE}], - children = Perms}, - Id = randoms:get_string(), - #xmlel{name = <<"message">>, - attrs = [{<<"id">>, Id}, {<<"from">>, From}, {<<"to">>, To}], - children = [Stanza]}. +mod_opt_type(roster) -> v_roster(); +mod_opt_type(message) -> v_message(); +mod_opt_type(presence) -> v_presence(); +mod_opt_type(_) -> + [roster, message, presence]. -advertise_permissions(#state{privilege_access = []}) -> ok; -advertise_permissions(StateData) -> - Stanza = - permissions(?MYNAME, StateData#state.host, StateData#state.privilege_access), - ejabberd_service:send_element(StateData, Stanza). +depends(_, _) -> + []. -%%%-------------------------------------------------------------------------------------- -%%% Process presences -%%%-------------------------------------------------------------------------------------- +-spec component_connected(binary()) -> ok. +component_connected(Host) -> + lists:foreach( + fun(ServerHost) -> + Proc = gen_mod:get_module_proc(ServerHost, ?MODULE), + gen_server:cast(Proc, {component_connected, Host}) + end, ?MYHOSTS). -initial_presences(StateData) -> - Pids = ejabberd_sm:get_all_pids(), +-spec component_disconnected(binary(), binary()) -> ok. +component_disconnected(Host, _Reason) -> lists:foreach( - fun(Pid) -> - {User, Server, Resource, PresenceLast} = ejabberd_c2s:get_last_presence(Pid), - From = #jid{user = User, server = Server, resource = Resource}, - To = jid:from_string(StateData#state.host), - PacketNew = jlib:replace_from_to(From, To, PresenceLast), - ejabberd_service:send_element(StateData, PacketNew) - end, Pids). + fun(ServerHost) -> + Proc = gen_mod:get_module_proc(ServerHost, ?MODULE), + gen_server:cast(Proc, {component_disconnected, Host}) + end, ?MYHOSTS). -%% hook user_send_packet(Packet, C2SState, From, To) -> Packet -%% for Managed Entity Presence -process_presence(Pid) -> - fun(#xmlel{name = <<"presence">>} = Packet, _C2SState, From, _To) -> - case fxml:get_attr_s(<<"type">>, Packet#xmlel.attrs) of - T when (T == <<"">>) or (T == <<"unavailable">>) -> - Pid ! {user_presence, Packet, From}; - _ -> ok - end, - Packet; - (Packet, _C2SState, _From, _To) -> - Packet - end. -%% s2s_receive_packet(From, To, Packet) -> ok -%% for Roster Presence -%% From subscription "from" or "both" -process_roster_presence(Pid) -> - fun(From, To, #xmlel{name = <<"presence">>} = Packet) -> - case fxml:get_attr_s(<<"type">>, Packet#xmlel.attrs) of - T when (T == <<"">>) or (T == <<"unavailable">>) -> - Server = To#jid.server, - User = To#jid.user, - PrivList = ejabberd_hooks:run_fold(privacy_get_user_list, - Server, #userlist{}, [User, Server]), - case privacy_check_packet(Server, User, PrivList, From, To, Packet, in) of - allow -> - Pid ! {roster_presence, Packet, From}; - _ -> ok - end, - ok; - _ -> ok - end; - (_From, _To, _Packet) -> ok +-spec process_message(jid(), jid(), stanza()) -> stop | ok. +process_message(#jid{luser = <<"">>, lresource = <<"">>} = From, + #jid{lresource = <<"">>} = To, + #message{lang = Lang, type = T} = Msg) when T /= error -> + Host = From#jid.lserver, + ServerHost = To#jid.lserver, + Permissions = get_permissions(ServerHost), + case dict:find(Host, Permissions) of + {ok, Access} -> + case proplists:get_value(message, Access, none) of + outgoing -> + forward_message(From, To, Msg); + none -> + Txt = <<"Insufficient privilege">>, + Err = xmpp:err_forbidden(Txt, Lang), + ejabberd_router:route_error(To, From, Msg, Err) + end, + stop; + error -> + %% Component is disconnected + ok + end; +process_message(_From, _To, _Stanza) -> + ok. + +-spec roster_access(boolean(), iq()) -> boolean(). +roster_access(true, _) -> + true; +roster_access(false, #iq{from = From, to = To, type = Type}) -> + Host = From#jid.lserver, + ServerHost = To#jid.lserver, + Permissions = get_permissions(ServerHost), + case dict:find(Host, Permissions) of + {ok, Access} -> + Permission = proplists:get_value(roster, Access, none), + (Permission == both) + orelse (Permission == get andalso Type == get) + orelse (Permission == set andalso Type == set); + error -> + %% Component is disconnected + false end. -%%%-------------------------------------------------------------------------------------- -%%% Manage Roster -%%%-------------------------------------------------------------------------------------- +-spec process_presence_out(stanza(), ejabberd_c2s:state(), jid(), jid()) -> stanza(). +process_presence_out(#presence{type = Type} = Pres, _C2SState, + #jid{luser = LUser, lserver = LServer} = From, + #jid{luser = LUser, lserver = LServer, lresource = <<"">>}) + when Type == available; Type == unavailable -> + %% Self-presence processing + Permissions = get_permissions(LServer), + lists:foreach( + fun({Host, Access}) -> + Permission = proplists:get_value(presence, Access, none), + if Permission == roster; Permission == managed_entity -> + To = jid:make(Host), + ejabberd_router:route( + From, To, xmpp:set_from_to(Pres, From, To)); + true -> + ok + end + end, dict:to_list(Permissions)), + Pres; +process_presence_out(Acc, _, _, _) -> + Acc. -process_iq(StateData, FromJID, ToJID, Packet) -> - IQ = jlib:iq_query_or_response_info(Packet), - case IQ of - #iq{xmlns = ?NS_ROSTER} -> - case (ToJID#jid.luser /= <<"">>) and - (FromJID#jid.luser == <<"">>) and - lists:member(ToJID#jid.lserver, ?MYHOSTS) of - true -> - AccessType = - proplists:get_value(roster, StateData#state.privilege_access, none), - case IQ#iq.type of - get when (AccessType == <<"both">>) or (AccessType == <<"get">>) -> - RosterIQ = roster_management(ToJID, FromJID, IQ), - ejabberd_service:send_element(StateData, RosterIQ); - set when (AccessType == <<"both">>) or (AccessType == <<"set">>) -> - %% check if user ToJID exist - #jid{lserver = Server, luser = User} = ToJID, - case ejabberd_auth:is_user_exists(User,Server) of - true -> - ResIQ = roster_management(ToJID, FromJID, IQ), - ejabberd_service:send_element(StateData, ResIQ); - _ -> ok - end; - _ -> - Err = jlib:make_error_reply(Packet, ?ERR_FORBIDDEN), - ejabberd_service:send_element(StateData, Err) - end; - _ -> - ejabberd_router:route(FromJID, ToJID, Packet) - end; - #iq{type = Type, id = Id} when (Type == error) or (Type == result) -> % for XEP-0355 - Hook = {iq, Type, Id}, - Host = ToJID#jid.lserver, - case (ToJID#jid.luser == <<"">>) and - (FromJID#jid.luser == <<"">>) and - lists:member(ToJID#jid.lserver, ?MYHOSTS) of - true -> - case ets:lookup(hooks_tmp, {Hook, Host}) of - [{_, Function, _Timestamp}] -> - catch apply(Function, [Packet]); - [] -> - ejabberd_router:route(FromJID, ToJID, Packet) - end; - _ -> - ejabberd_router:route(FromJID, ToJID, Packet) - end; - _ -> - ejabberd_router:route(FromJID, ToJID, Packet) - end. +-spec process_presence_in(stanza(), ejabberd_c2s:state(), + jid(), jid(), jid()) -> stanza(). +process_presence_in(#presence{type = Type} = Pres, _C2SState, _, + #jid{luser = U, lserver = S} = From, + #jid{luser = LUser, lserver = LServer}) + when {U, S} /= {LUser, LServer} andalso + (Type == available orelse Type == unavailable) -> + Permissions = get_permissions(LServer), + lists:foreach( + fun({Host, Access}) -> + case proplists:get_value(presence, Access, none) of + roster -> + Permission = proplists:get_value(roster, Access, none), + if Permission == both; Permission == get -> + To = jid:make(Host), + ejabberd_router:route( + From, To, xmpp:set_from_to(Pres, From, To)); + true -> + ok + end; + true -> + ok + end + end, dict:to_list(Permissions)), + Pres; +process_presence_in(Acc, _, _, _, _) -> + Acc. -roster_management(FromJID, ToJID, IQ) -> - ResIQ = mod_roster:process_iq(FromJID, FromJID, IQ), - ResXml = jlib:iq_to_xml(ResIQ), - jlib:replace_from_to(FromJID, ToJID, ResXml). +%%%=================================================================== +%%% gen_server callbacks +%%%=================================================================== +init([Host, _Opts]) -> + ejabberd_hooks:add(component_connected, ?MODULE, + component_connected, 50), + ejabberd_hooks:add(component_disconnected, ?MODULE, + component_disconnected, 50), + ejabberd_hooks:add(local_send_to_resource_hook, Host, ?MODULE, + process_message, 50), + ejabberd_hooks:add(roster_remote_access, Host, ?MODULE, + roster_access, 50), + ejabberd_hooks:add(user_send_packet, Host, ?MODULE, + process_presence_out, 50), + ejabberd_hooks:add(user_receive_packet, Host, ?MODULE, + process_presence_in, 50), + {ok, #state{server_host = Host}}. -%%%-------------------------------------------------------------------------------------- -%%% Message permission -%%%-------------------------------------------------------------------------------------- +handle_call(get_permissions, _From, State) -> + {reply, {ok, State#state.permissions}, State}; +handle_call(_Request, _From, State) -> + Reply = ok, + {reply, Reply, State}. -process_message(StateData, FromJID, ToJID, #xmlel{children = Children} = Packet) -> - %% if presence was send from service to server, - case lists:member(ToJID#jid.lserver, ?MYHOSTS) and - (ToJID#jid.luser == <<"">>) and - (FromJID#jid.luser == <<"">>) of %% service - true -> - %% if stanza contains privilege element - case Children of - [#xmlel{name = <<"privilege">>, - attrs = [{<<"xmlns">>, ?NS_PRIVILEGE}], - children = [#xmlel{name = <<"forwarded">>, - attrs = [{<<"xmlns">>, ?NS_FORWARD}], - children = Children2}]}] -> - %% 1 case : privilege service send subscription message - %% on behalf of the client - %% 2 case : privilege service send message on behalf - %% of the client - case Children2 of - %% it isn't case of 0356 extension - [#xmlel{name = <<"presence">>} = Child] -> - forward_subscribe(StateData, Child, Packet); - [#xmlel{name = <<"message">>} = Child] -> %% xep-0356 - forward_message(StateData, Child, Packet); - _ -> - Lang = fxml:get_tag_attr_s(<<"xml:lang">>, Packet), - Txt = <<"invalid forwarded element">>, - Err = jlib:make_error_reply(Packet, ?ERRT_BAD_REQUEST(Lang, Txt)), - ejabberd_service:send_element(StateData, Err) - end; - _ -> - ejabberd_router:route(FromJID, ToJID, Packet) - end; +handle_cast({component_connected, Host}, State) -> + ServerHost = State#state.server_host, + From = jid:make(ServerHost), + To = jid:make(Host), + RosterPerm = get_roster_permission(ServerHost, Host), + PresencePerm = get_presence_permission(ServerHost, Host), + MessagePerm = get_message_permission(ServerHost, Host), + if RosterPerm /= none, PresencePerm /= none, MessagePerm /= none -> + Priv = #privilege{perms = [#privilege_perm{access = message, + type = MessagePerm}, + #privilege_perm{access = roster, + type = RosterPerm}, + #privilege_perm{access = presence, + type = PresencePerm}]}, + ?INFO_MSG("Granting permissions to external " + "component '~s': roster = ~s, presence = ~s, " + "message = ~s", + [Host, RosterPerm, PresencePerm, MessagePerm]), + Msg = #message{from = From, to = To, sub_els = [Priv]}, + ejabberd_router:route(From, To, Msg), + Permissions = dict:store(Host, [{roster, RosterPerm}, + {presence, PresencePerm}, + {message, MessagePerm}], + State#state.permissions), + {noreply, State#state{permissions = Permissions}}; + true -> + ?INFO_MSG("Granting no permissions to external component '~s'", + [Host]), + {noreply, State} + end; +handle_cast({component_disconnected, Host}, State) -> + Permissions = dict:erase(Host, State#state.permissions), + {noreply, State#state{permissions = Permissions}}; +handle_cast(_Msg, State) -> + {noreply, State}. - _ -> - ejabberd_router:route(FromJID, ToJID, Packet) - end. +handle_info(_Info, State) -> + {noreply, State}. -forward_subscribe(StateData, Presence, Packet) -> - PrivAccess = StateData#state.privilege_access, - T = proplists:get_value(roster, PrivAccess, none), - Type = fxml:get_attr_s(<<"type">>, Presence#xmlel.attrs), - if - ((T == <<"both">>) or (T == <<"set">>)) and (Type == <<"subscribe">>) -> - From = fxml:get_attr_s(<<"from">>, Presence#xmlel.attrs), - FromJ = jid:from_string(From), - To = fxml:get_attr_s(<<"to">>, Presence#xmlel.attrs), - ToJ = case To of - <<"">> -> error; - _ -> jid:from_string(To) - end, - if - (ToJ /= error) and (FromJ /= error) -> - Server = FromJ#jid.lserver, - User = FromJ#jid.luser, - case (FromJ#jid.lresource == <<"">>) and - lists:member(Server, ?MYHOSTS) of - true -> - if - (Server /= ToJ#jid.lserver) or - (User /= ToJ#jid.luser) -> - %% 0356 server MUST NOT allow the privileged entity - %% to do anything that the managed entity could not do - try_roster_subscribe(Server,User, FromJ, ToJ, Presence); - true -> %% we don't want presence sent to self - ok - end; - _ -> - Err = jlib:make_error_reply(Packet, ?ERR_FORBIDDEN), - ejabberd_service:send_element(StateData, Err) - end; - true -> - Lang = fxml:get_tag_attr_s(<<"xml:lang">>, Packet), - Txt = <<"Incorrect stanza from/to JID">>, - Err = jlib:make_error_reply(Packet, ?ERRT_BAD_REQUEST(Lang, Txt)), - ejabberd_service:send_element(StateData, Err) - end; - true -> - Err = jlib:make_error_reply(Packet, ?ERR_FORBIDDEN), - ejabberd_service:send_element(StateData, Err) - end. +terminate(_Reason, State) -> + %% Note: we don't remove component_* hooks because they are global + %% and might be registered within a module on another virtual host + Host = State#state.server_host, + ejabberd_hooks:delete(local_send_to_resource_hook, Host, ?MODULE, + process_message, 50), + ejabberd_hooks:delete(roster_remote_access, Host, ?MODULE, + roster_access, 50), + ejabberd_hooks:delete(user_send_packet, Host, ?MODULE, + process_presence_out, 50), + ejabberd_hooks:delete(user_receive_packet, Host, ?MODULE, + process_presence_in, 50). -forward_message(StateData, Message, Packet) -> - PrivAccess = StateData#state.privilege_access, - T = proplists:get_value(message, PrivAccess, none), - if - (T == <<"outgoing">>) -> - From = fxml:get_attr_s(<<"from">>, Message#xmlel.attrs), - FromJ = jid:from_string(From), - To = fxml:get_attr_s(<<"to">>, Message#xmlel.attrs), - ToJ = case To of - <<"">> -> FromJ; - _ -> jid:from_string(To) - end, - if - (ToJ /= error) and (FromJ /= error) -> - Server = FromJ#jid.server, - User = FromJ#jid.user, - case (FromJ#jid.lresource == <<"">>) and - lists:member(Server, ?MYHOSTS) of - true -> - %% there are no restriction on to attribute - PrivList = ejabberd_hooks:run_fold(privacy_get_user_list, - Server, #userlist{}, - [User, Server]), - check_privacy_route(Server, User, PrivList, - FromJ, ToJ, Message); - _ -> - Err = jlib:make_error_reply(Packet, ?ERR_FORBIDDEN), - ejabberd_service:send_element(StateData, Err) - end; - true -> - Lang = fxml:get_tag_attr_s(<<"xml:lang">>, Packet), - Txt = <<"Incorrect stanza from/to JID">>, - Err = jlib:make_error_reply(Packet, ?ERRT_BAD_REQUEST(Lang, Txt)), - ejabberd_service:send_element(StateData, Err) - end; - true -> - Err = jlib:make_error_reply(Packet,?ERR_FORBIDDEN), - ejabberd_service:send_element(StateData, Err) - end. +code_change(_OldVsn, State, _Extra) -> + {ok, State}. -%%%-------------------------------------------------------------------------------------- -%%% helper functions -%%%-------------------------------------------------------------------------------------- +%%%=================================================================== +%%% Internal functions +%%%=================================================================== +get_permissions(ServerHost) -> + Proc = gen_mod:get_module_proc(ServerHost, ?MODULE), + try gen_server:call(Proc, get_permissions) of + {ok, Permissions} -> + Permissions + catch exit:{noproc, _} -> + %% No module is loaded for this virtual host + dict:new() + end. -compare_presences(undefined, _Presence) -> false; -compare_presences(#xmlel{attrs = Attrs, children = Child}, - #xmlel{attrs = Attrs2, children = Child2}) -> - Id1 = fxml:get_attr_s(<<"id">>, Attrs), - Id2 = fxml:get_attr_s(<<"id">>, Attrs2), - if - (Id1 /= Id2) -> - false; - (Id1 /= <<"">>) and (Id1 == Id2) -> - true; - true -> - case not compare_attrs(Attrs, Attrs2) of - true -> false; - _ -> - compare_elements(Child, Child2) - end +forward_message(From, To, Msg) -> + Host = From#jid.lserver, + ServerHost = To#jid.lserver, + case xmpp:get_subtag(Msg, #privilege{}) of + #privilege{forwarded = #forwarded{sub_els = [#message{} = SubEl]}} -> + case SubEl#message.from of + #jid{lresource = <<"">>, lserver = ServerHost} -> + ejabberd_router:route( + xmpp:get_from(SubEl), xmpp:get_to(SubEl), SubEl); + _ -> + Lang = xmpp:get_lang(Msg), + Txt = <<"Invalid 'from' attribute">>, + Err = xmpp:err_forbidden(Txt, Lang), + ejabberd_router:route_error(To, From, Msg, Err) + end; + _ -> + ?ERROR_MSG("got invalid forwarded payload from external " + "component '~s':~n~s", [Host, xmpp:pp(Msg)]), + Lang = xmpp:get_lang(Msg), + Txt = <<"Invalid forwarded payload">>, + Err = xmpp:err_bad_request(Txt, Lang), + ejabberd_router:route_error(To, From, Msg, Err) end. +get_roster_permission(ServerHost, Host) -> + Perms = gen_mod:get_module_opt(ServerHost, ?MODULE, roster, + v_roster(), []), + case match_rule(ServerHost, Host, Perms, both) of + allow -> + both; + deny -> + Get = match_rule(ServerHost, Host, Perms, get), + Set = match_rule(ServerHost, Host, Perms, set), + if Get == allow, Set == allow -> both; + Get == allow -> get; + Set == allow -> set; + true -> none + end + end. -compare_elements([],[]) -> true; -compare_elements(Tags1, Tags2) when length(Tags1) == length(Tags2) -> - compare_tags(Tags1,Tags2); -compare_elements(_Tags1, _Tags2) -> false. +get_message_permission(ServerHost, Host) -> + Perms = gen_mod:get_module_opt(ServerHost, ?MODULE, message, + v_message(), []), + case match_rule(ServerHost, Host, Perms, outgoing) of + allow -> outgoing; + deny -> none + end. -compare_tags([],[]) -> true; -compare_tags([{xmlcdata, CData}|Tags1], [{xmlcdata, CData}|Tags2]) -> - compare_tags(Tags1, Tags2); -compare_tags([{xmlcdata, _CData1}|_Tags1], [{xmlcdata, _CData2}|_Tags2]) -> - false; -compare_tags([#xmlel{} = Stanza1|Tags1], [#xmlel{} = Stanza2|Tags2]) -> - case (Stanza1#xmlel.name == Stanza2#xmlel.name) and - compare_attrs(Stanza1#xmlel.attrs, Stanza2#xmlel.attrs) and - compare_tags(Stanza1#xmlel.children, Stanza2#xmlel.children) of - true -> - compare_tags(Tags1,Tags2); - false -> - false +get_presence_permission(ServerHost, Host) -> + Perms = gen_mod:get_module_opt(ServerHost, ?MODULE, presence, + v_presence(), []), + case match_rule(ServerHost, Host, Perms, roster) of + allow -> + roster; + deny -> + case match_rule(ServerHost, Host, Perms, managed_entity) of + allow -> managed_entity; + deny -> none + end end. -%% attr() :: {Name, Value} --spec compare_attrs([attr()], [attr()]) -> boolean(). -compare_attrs([],[]) -> true; -compare_attrs(Attrs1, Attrs2) when length(Attrs1) == length(Attrs2) -> - lists:foldl(fun(Attr,Acc) -> lists:member(Attr, Attrs2) and Acc end, true, Attrs1); -compare_attrs(_Attrs1, _Attrs2) -> false. +match_rule(ServerHost, Host, Perms, Type) -> + Access = proplists:get_value(Type, Perms, none), + acl:match_rule(ServerHost, Access, jid:make(Host)). -%% Check if privacy rules allow this delivery -%% from ejabberd_c2s.erl -privacy_check_packet(Server, User, PrivList, From, To, Packet , Dir) -> - ejabberd_hooks:run_fold(privacy_check_packet, - Server, allow, [User, Server, PrivList, - {From, To, Packet}, Dir]). +v_roster() -> + fun(Props) -> + lists:map( + fun({both, ACL}) -> {both, acl:access_rules_validator(ACL)}; + ({get, ACL}) -> {get, acl:access_rules_validator(ACL)}; + ({set, ACL}) -> {set, acl:access_rules_validator(ACL)} + end, Props) + end. -check_privacy_route(Server, User, PrivList, From, To, Packet) -> - case privacy_check_packet(Server, User, PrivList, From, To, Packet, out) of - allow -> - ejabberd_router:route(From, To, Packet); - _ -> ok %% who should receive error : service or user? +v_message() -> + fun(Props) -> + lists:map( + fun({outgoing, ACL}) -> {outgoing, acl:access_rules_validator(ACL)} + end, Props) end. -try_roster_subscribe(Server,User, From, To, Packet) -> - Access = - gen_mod:get_module_opt(Server, mod_roster, access, - fun(A) when is_atom(A) -> A end, all), - case acl:match_rule(Server, Access, From) of - deny -> - ok; - allow -> - ejabberd_hooks:run(roster_out_subscription, Server, - [User, Server, To, subscribe]), - PrivList = ejabberd_hooks:run_fold(privacy_get_user_list, - Server, - #userlist{}, - [User, Server]), - check_privacy_route(Server, User, PrivList, From, To, Packet) +v_presence() -> + fun(Props) -> + lists:map( + fun({managed_entity, ACL}) -> + {managed_entity, acl:access_rules_validator(ACL)}; + ({roster, ACL}) -> + {roster, acl:access_rules_validator(ACL)} + end, Props) end. |