24
1
mirror of https://github.com/processone/ejabberd.git synced 2024-06-02 21:17:12 +02:00

Convert ejabberd_xmlrpc to new api_permissions

This commit is contained in:
Paweł Chmielowski 2016-10-14 13:55:50 +02:00
parent d97e777c9b
commit fd6f0f94b5
3 changed files with 63 additions and 24 deletions

View File

@ -129,7 +129,8 @@ init([]) ->
handle_call({can_access, Cmd, CallerInfo}, _From, State) -> handle_call({can_access, Cmd, CallerInfo}, _From, State) ->
CallerModule = maps:get(caller_module, CallerInfo, none), CallerModule = maps:get(caller_module, CallerInfo, none),
Host = maps:get(caller_host, CallerInfo, global), Host = maps:get(caller_host, CallerInfo, global),
{State2, Defs} = get_definitions(State), {State2, Defs0} = get_definitions(State),
Defs = maps:get(extra_permissions, CallerInfo, []) ++ Defs0,
Res = lists:foldl( Res = lists:foldl(
fun({Name, _} = Def, none) -> fun({Name, _} = Def, none) ->
case matches_definition(Def, Cmd, CallerModule, Host, CallerInfo) of case matches_definition(Def, Cmd, CallerModule, Host, CallerInfo) of
@ -257,7 +258,7 @@ get_definitions(#state{definitions = Defs, fragments_generators = Gens} = State)
{State#state{definitions = NDefs}, NDefs}. {State#state{definitions = NDefs}, NDefs}.
matches_definition({_Name, {From, Who, What}}, Cmd, Module, Host, CallerInfo) -> matches_definition({_Name, {From, Who, What}}, Cmd, Module, Host, CallerInfo) ->
case lists:member(Cmd, What) of case What == all orelse lists:member(Cmd, What) of
true -> true ->
case From == [] orelse lists:member(Module, From) of case From == [] orelse lists:member(Module, From) of
true -> true ->

View File

@ -460,7 +460,7 @@ get_commands_definition(Version) ->
lists:foldl(F, [], L). lists:foldl(F, [], L).
execute_command2(Name, Arguments, CallerInfo) -> execute_command2(Name, Arguments, CallerInfo) ->
execute_command(Name, Arguments, CallerInfo, ?DEFAULT_VERSION). execute_command2(Name, Arguments, CallerInfo, ?DEFAULT_VERSION).
execute_command2(Name, Arguments, CallerInfo, Version) -> execute_command2(Name, Arguments, CallerInfo, Version) ->
Command = get_command_definition(Name, Version), Command = get_command_definition(Name, Version),

View File

@ -47,7 +47,8 @@
-record(state, -record(state,
{access_commands = [] :: list(), {access_commands = [] :: list(),
auth = noauth :: noauth | {binary(), binary(), binary()}, auth = noauth :: noauth | {binary(), binary(), binary()},
get_auth = true :: boolean()}). get_auth = true :: boolean(),
ip :: inet:ip_address()}).
%% Test: %% Test:
@ -195,7 +196,7 @@ socket_type() -> raw.
%% ----------------------------- %% -----------------------------
%% HTTP interface %% HTTP interface
%% ----------------------------- %% -----------------------------
process(_, #request{method = 'POST', data = Data, opts = Opts}) -> process(_, #request{method = 'POST', data = Data, opts = Opts, ip = {IP, _}}) ->
AccessCommandsOpts = gen_mod:get_opt(access_commands, Opts, AccessCommandsOpts = gen_mod:get_opt(access_commands, Opts,
fun(L) when is_list(L) -> L end, fun(L) when is_list(L) -> L end,
undefined), undefined),
@ -206,7 +207,7 @@ process(_, #request{method = 'POST', data = Data, opts = Opts}) ->
lists:flatmap( lists:flatmap(
fun({Ac, AcOpts}) -> fun({Ac, AcOpts}) ->
Commands = gen_mod:get_opt( Commands = gen_mod:get_opt(
commands, AcOpts, commands, lists:flatten(AcOpts),
fun(A) when is_atom(A) -> fun(A) when is_atom(A) ->
A; A;
(L) when is_list(L) -> (L) when is_list(L) ->
@ -219,15 +220,15 @@ process(_, #request{method = 'POST', data = Data, opts = Opts}) ->
options, AcOpts, options, AcOpts,
fun(L) when is_list(L) -> L end, fun(L) when is_list(L) -> L end,
[]), []),
[{Ac, Commands, CommOpts}]; [{<<"ejabberd_xmlrpc compatibility shim">>, {[?MODULE], [{access, Ac}], Commands}}];
(Wrong) -> (Wrong) ->
?WARNING_MSG("wrong options format for ~p: ~p", ?WARNING_MSG("wrong options format for ~p: ~p",
[?MODULE, Wrong]), [?MODULE, Wrong]),
[] []
end, AccessCommandsOpts) end, lists:flatten(AccessCommandsOpts))
end, end,
GetAuth = true, GetAuth = true,
State = #state{access_commands = AccessCommands, get_auth = GetAuth}, State = #state{access_commands = AccessCommands, get_auth = GetAuth, ip = IP},
case fxml_stream:parse_element(Data) of case fxml_stream:parse_element(Data) of
{error, _} -> {error, _} ->
{400, [], {400, [],
@ -258,21 +259,35 @@ process(_, _) ->
%% Access verification %% Access verification
%% ----------------------------- %% -----------------------------
get_auth(AuthList) -> extract_auth(AuthList) ->
Admin = ?DEBUG("AUTHLIST ~p", [AuthList]),
case lists:keysearch(admin, 1, AuthList) of
{value, {admin, true}} -> true;
_ -> false
end,
try get_attrs([user, server, token], AuthList) of try get_attrs([user, server, token], AuthList) of
[U, S, T] -> {U, S, {oauth, T}, Admin} [U0, S0, T] ->
U = jid:nodeprep(U0),
S = jid:nameprep(S0),
case ejabberd_oauth:check_token(T) of
{ok, {U, S}, Scope} ->
#{usr => {U, S, <<"">>}, oauth_scope => Scope, caller_server => S};
{false, Reason} ->
{error, Reason};
_ ->
{error, not_found}
end
catch catch
exit:{attribute_not_found, _Attr, _} -> exit:{attribute_not_found, _Attr, _} ->
try get_attrs([user, server, password], AuthList) of try get_attrs([user, server, password], AuthList) of
[U, S, P] -> {U, S, P, Admin} [U0, S0, P] ->
U = jid:nodeprep(U0),
S = jid:nameprep(S0),
case ejabberd_auth:check_password(U, <<"">>, S, P) of
true ->
#{usr => {U, S, <<"">>}, caller_server => S};
false ->
{error, invalid_auth}
end
catch catch
exit:{attribute_not_found, Attr, _} -> exit:{attribute_not_found, _Attr, _} ->
throw({error, missing_auth_arguments, Attr}) #{}
end end
end. end.
@ -300,12 +315,28 @@ get_auth(AuthList) ->
%% xmlrpc:call({127, 0, 0, 1}, 4560, "/", {call, echothis, [{struct, [{user, "badlop"}, {server, "localhost"}, {password, "79C1574A43BC995F2B145A299EF97277"}]}, 152]}). %% xmlrpc:call({127, 0, 0, 1}, 4560, "/", {call, echothis, [{struct, [{user, "badlop"}, {server, "localhost"}, {password, "79C1574A43BC995F2B145A299EF97277"}]}, 152]}).
%% {ok,{response,[152]}} %% {ok,{response,[152]}}
handler(#state{get_auth = true, auth = noauth} = State, handler(#state{get_auth = true, auth = noauth, ip = IP} = State,
{call, Method, {call, Method,
[{struct, AuthList} | Arguments] = AllArgs}) -> [{struct, AuthList} | Arguments] = AllArgs}) ->
try get_auth(AuthList) of try extract_auth(AuthList) of
{error, invalid_auth} ->
build_fault_response(-118,
"Invalid authentication data",
[]);
{error, not_found} ->
build_fault_response(-118,
"Invalid oauth token",
[]);
{error, expired} ->
build_fault_response(-118,
"Invalid oauth token",
[]);
{error, Value} ->
build_fault_response(-118,
"Invalid authentication data: ~p",
[Value]);
Auth -> Auth ->
handler(State#state{get_auth = false, auth = Auth}, handler(State#state{get_auth = false, auth = Auth#{ip => IP, caller_module => ?MODULE}},
{call, Method, Arguments}) {call, Method, Arguments})
catch catch
{error, missing_auth_arguments, _Attr} -> {error, missing_auth_arguments, _Attr} ->
@ -393,9 +424,14 @@ build_fault_response(Code, ParseString, ParseArgs) ->
do_command(AccessCommands, Auth, Command, AttrL, ArgsF, do_command(AccessCommands, Auth, Command, AttrL, ArgsF,
ResultF) -> ResultF) ->
ArgsFormatted = format_args(AttrL, ArgsF), ArgsFormatted = format_args(AttrL, ArgsF),
Auth2 = case AccessCommands of
V when is_list(V) ->
Auth#{extra_permissions => AccessCommands};
_ ->
Auth
end,
Result = Result =
ejabberd_commands:execute_command(AccessCommands, Auth, ejabberd_commands:execute_command2(Command, ArgsFormatted, Auth2),
Command, ArgsFormatted),
ResultFormatted = format_result(Result, ResultF), ResultFormatted = format_result(Result, ResultF),
{command_result, ResultFormatted}. {command_result, ResultFormatted}.
@ -489,6 +525,8 @@ process_unicode_codepoints(Str) ->
format_result({error, Error}, _) -> format_result({error, Error}, _) ->
throw({error, Error}); throw({error, Error});
format_result({error, _Type, _Code, Error}, _) ->
throw({error, Error});
format_result(String, string) -> lists:flatten(String); format_result(String, string) -> lists:flatten(String);
format_result(Atom, {Name, atom}) -> format_result(Atom, {Name, atom}) ->
{struct, {struct,