]> granicus.if.org Git - ejabberd/commitdiff
Convert ejabberd_xmlrpc to new api_permissions
authorPaweł Chmielowski <pchmielowski@process-one.net>
Fri, 14 Oct 2016 11:55:50 +0000 (13:55 +0200)
committerPaweł Chmielowski <pchmielowski@process-one.net>
Fri, 14 Oct 2016 11:55:50 +0000 (13:55 +0200)
src/ejabberd_access_permissions.erl
src/ejabberd_commands.erl
src/ejabberd_xmlrpc.erl

index 153be0940e3acefb206812d6fdeea2e382f6493f..7ce75aa9c8523e3f03b3fa5425d2215dd21e4cf0 100644 (file)
@@ -129,7 +129,8 @@ init([]) ->
 handle_call({can_access, Cmd, CallerInfo}, _From, State) ->
     CallerModule = maps:get(caller_module, CallerInfo, none),
     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(
        fun({Name, _} = Def, none) ->
            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}.
 
 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 ->
            case From == [] orelse lists:member(Module, From) of
                true ->
index 173071d6fb868e4bb2080051b4caad7557374d58..8d74ad5a20fbd0d7567a4d159fa9551b141807c7 100644 (file)
@@ -460,7 +460,7 @@ get_commands_definition(Version) ->
     lists:foldl(F, [], L).
 
 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) ->
     Command = get_command_definition(Name, Version),
index 6680451e46e5fda2a49c831544ff1ddbee23ee18..1dd88f837bc7f154cef364820c451c62ea88c7e1 100644 (file)
@@ -47,7 +47,8 @@
 -record(state,
        {access_commands = [] :: list(),
          auth = noauth        :: noauth | {binary(), binary(), binary()},
-         get_auth = true      :: boolean()}).
+         get_auth = true      :: boolean(),
+        ip                   :: inet:ip_address()}).
 
 %% Test:
 
@@ -195,7 +196,7 @@ socket_type() -> raw.
 %% -----------------------------
 %% 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,
                                          fun(L) when is_list(L) -> L end,
                                          undefined),
@@ -206,7 +207,7 @@ process(_, #request{method = 'POST', data = Data, opts = Opts}) ->
                 lists:flatmap(
                   fun({Ac, AcOpts}) ->
                           Commands = gen_mod:get_opt(
-                                       commands, AcOpts,
+                                       commands, lists:flatten(AcOpts),
                                        fun(A) when is_atom(A) ->
                                                A;
                                           (L) when is_list(L) ->
@@ -219,15 +220,15 @@ process(_, #request{method = 'POST', data = Data, opts = Opts}) ->
                                        options, AcOpts,
                                        fun(L) when is_list(L) -> L end,
                                        []),
-                          [{Ac, Commands, CommOpts}];
+                         [{<<"ejabberd_xmlrpc compatibility shim">>, {[?MODULE], [{access, Ac}], Commands}}];
                      (Wrong) ->
                           ?WARNING_MSG("wrong options format for ~p: ~p",
                                        [?MODULE, Wrong]),
                           []
-                  end, AccessCommandsOpts)
+                  end, lists:flatten(AccessCommandsOpts))
         end,
     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
        {error, _} ->
            {400, [],
@@ -258,21 +259,35 @@ process(_, _) ->
 %% Access verification
 %% -----------------------------
 
-get_auth(AuthList) ->
-    Admin =
-        case lists:keysearch(admin, 1, AuthList) of
-            {value, {admin, true}} -> true;
-            _ -> false
-        end,
+extract_auth(AuthList) ->
+    ?DEBUG("AUTHLIST ~p", [AuthList]),
     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
         exit:{attribute_not_found, _Attr, _} ->
             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
-                exit:{attribute_not_found, Attr, _} ->
-                    throw({error, missing_auth_arguments, Attr})
+                exit:{attribute_not_found, _Attr, _} ->
+                    #{}
             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]}).
 %% {ok,{response,[152]}}
 
-handler(#state{get_auth = true, auth = noauth} = State,
+handler(#state{get_auth = true, auth = noauth, ip = IP} = State,
        {call, Method,
         [{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 ->
-            handler(State#state{get_auth = false, auth = Auth},
+            handler(State#state{get_auth = false, auth = Auth#{ip => IP, caller_module => ?MODULE}},
                     {call, Method, Arguments})
     catch
       {error, missing_auth_arguments, _Attr} ->
@@ -393,9 +424,14 @@ build_fault_response(Code, ParseString, ParseArgs) ->
 do_command(AccessCommands, Auth, Command, AttrL, ArgsF,
           ResultF) ->
     ArgsFormatted = format_args(AttrL, ArgsF),
+    Auth2 = case AccessCommands of
+               V when is_list(V) ->
+                   Auth#{extra_permissions => AccessCommands};
+               _ ->
+                   Auth
+           end,
     Result =
-       ejabberd_commands:execute_command(AccessCommands, Auth,
-                                         Command, ArgsFormatted),
+       ejabberd_commands:execute_command2(Command, ArgsFormatted, Auth2),
     ResultFormatted = format_result(Result, ResultF),
     {command_result, ResultFormatted}.
 
@@ -489,6 +525,8 @@ process_unicode_codepoints(Str) ->
 
 format_result({error, Error}, _) ->
     throw({error, Error});
+format_result({error, _Type, _Code, Error}, _) ->
+    throw({error, Error});
 format_result(String, string) -> lists:flatten(String);
 format_result(Atom, {Name, atom}) ->
     {struct,