mirror of
https://github.com/processone/ejabberd.git
synced 2024-06-14 22:00:16 +02:00
Convert ejabberd_xmlrpc to new api_permissions
This commit is contained in:
parent
d97e777c9b
commit
fd6f0f94b5
|
@ -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 ->
|
||||||
|
|
|
@ -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),
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Reference in New Issue
Block a user