This option is disabled by default.
Important: if you use \modsharedroster{} or \modsharedrosterldap{},
you must disable this option.
+ \titem{access} \ind{options!access}
+ This option can be configured to specify rules to restrict roster management.
+ If a rule returns `deny' on the requested user name,
+ that user cannot modify his personal roster:
+ not add/remove/modify contacts,
+ or subscribe/unsubscribe presence.
+ By default there aren't restrictions.
\end{description}
This example configuration enables Roster Versioning with storage of current id:
...
\end{verbatim}
+With this example configuration, only admins can manage their rosters;
+everybody else cannot modify the roster:
+\begin{verbatim}
+acl:
+ admin:
+ user:
+ - "sarah": "example.org"
+access:
+ roster:
+ admin: allow
+
+modules:
+ ...
+ mod_roster:
+ access: roster
+ ...
+\end{verbatim}
+
\makesubsection{modservicelog}{\modservicelog{}}
\ind{modules!\modservicelog{}}\ind{message auditing}\ind{Bandersnatch}
A = remove_element(LTo, StateData#state.pres_a),
StateData#state{pres_a = A};
<<"subscribe">> ->
- ejabberd_hooks:run(roster_out_subscription, Server,
- [User, Server, To, subscribe]),
- check_privacy_route(From, StateData,
- jlib:jid_remove_resource(From), To, Packet),
+ try_roster_subscribe(subscribe, User, Server, From, To, Packet, StateData),
StateData;
<<"subscribed">> ->
ejabberd_hooks:run(roster_out_subscription, Server,
jlib:jid_remove_resource(From), To, Packet),
StateData;
<<"unsubscribe">> ->
- ejabberd_hooks:run(roster_out_subscription, Server,
- [User, Server, To, unsubscribe]),
- check_privacy_route(From, StateData,
- jlib:jid_remove_resource(From), To, Packet),
+ try_roster_subscribe(unsubscribe, User, Server, From, To, Packet, StateData),
StateData;
<<"unsubscribed">> ->
ejabberd_hooks:run(roster_out_subscription, Server,
allow ==
privacy_check_packet(StateData, From, To, Packet, Dir).
+%%% Check ACL before allowing to send a subscription stanza
+try_roster_subscribe(Type, User, Server, From, To, Packet, StateData) ->
+ JID1 = jlib:make_jid(User, Server, <<"">>),
+ 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, JID1) of
+ deny ->
+ %% Silently drop this (un)subscription request
+ ok;
+ allow ->
+ ejabberd_hooks:run(roster_out_subscription,
+ Server,
+ [User, Server, To, Type]),
+ check_privacy_route(From, StateData, jlib:jid_remove_resource(From),
+ To, Packet)
+ end.
+
%% Send presence when disconnecting
presence_broadcast(StateData, From, JIDSet, Packet) ->
JIDs = ?SETS:to_list(JIDSet),
process_local_iq(From, To, #iq{type = Type} = IQ) ->
case Type of
- set -> process_iq_set(From, To, IQ);
+ set -> try_process_iq_set(From, To, IQ);
get -> process_iq_get(From, To, IQ)
end.
end
end.
+try_process_iq_set(From, To, #iq{sub_el = SubEl} = IQ) ->
+ #jid{server = Server} = From,
+ Access = gen_mod:get_module_opt(Server, ?MODULE, access, fun(A) when is_atom(A) -> A end, all),
+ case acl:match_rule(Server, Access, From) of
+ deny ->
+ IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]};
+ allow ->
+ process_iq_set(From, To, IQ)
+ end.
+
process_iq_set(From, To, #iq{sub_el = SubEl} = IQ) ->
#xmlel{children = Els} = SubEl,
lists:foreach(fun (El) -> process_item_set(From, To, El)
{value, _} ->
UJID = jlib:make_jid(User, Server,
<<"">>),
- process_iq(UJID, UJID,
+ process_iq_set(UJID, UJID,
#iq{type = set,
sub_el =
#xmlel{name =