Add access rule to mod_roster (EJAB-72)

This commit is contained in:
Badlop 2013-12-04 14:55:21 +01:00
parent 9c17163b55
commit 5a1300bc70
3 changed files with 55 additions and 10 deletions

View File

@ -4039,6 +4039,13 @@ Options:
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:
@ -4051,6 +4058,24 @@ modules:
...
\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}

View File

@ -1879,10 +1879,7 @@ presence_track(From, To, Packet, StateData) ->
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,
@ -1891,10 +1888,7 @@ presence_track(From, To, Packet, StateData) ->
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,
@ -1943,6 +1937,22 @@ is_privacy_allow(StateData, From, To, Packet, Dir) ->
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),

View File

@ -142,7 +142,7 @@ process_iq(From, To, IQ) ->
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.
@ -455,6 +455,16 @@ get_roster_by_jid_t(LUser, LServer, LJID, odbc) ->
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)
@ -1508,7 +1518,7 @@ user_roster_item_parse_query(User, Server, Items,
{value, _} ->
UJID = jlib:make_jid(User, Server,
<<"">>),
process_iq(UJID, UJID,
process_iq_set(UJID, UJID,
#iq{type = set,
sub_el =
#xmlel{name =