aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ejabberd_access_permissions.erl25
-rw-r--r--src/ejabberd_http.erl29
-rw-r--r--src/ejabberd_sql.erl12
-rw-r--r--src/ejabberd_web_admin.erl1
-rw-r--r--src/mod_http_api.erl39
-rw-r--r--src/mod_muc_admin.erl4
6 files changed, 66 insertions, 44 deletions
diff --git a/src/ejabberd_access_permissions.erl b/src/ejabberd_access_permissions.erl
index 4d673e753..0c53795b8 100644
--- a/src/ejabberd_access_permissions.erl
+++ b/src/ejabberd_access_permissions.erl
@@ -130,11 +130,12 @@ init([]) ->
handle_call({can_access, Cmd, CallerInfo}, _From, State) ->
CallerModule = maps:get(caller_module, CallerInfo, none),
Host = maps:get(caller_host, CallerInfo, global),
+ Tag = maps:get(tag, CallerInfo, none),
{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
+ case matches_definition(Def, Cmd, CallerModule, Tag, Host, CallerInfo) of
true ->
?DEBUG("Command '~p' execution allowed by rule '~s' (CallerInfo=~p)", [Cmd, Name, CallerInfo]),
allow;
@@ -261,10 +262,12 @@ get_definitions(#state{definitions = none, fragments_generators = Gens} = State)
end,
{State#state{definitions = NDefs}, NDefs}.
-matches_definition({_Name, {From, Who, What}}, Cmd, Module, Host, CallerInfo) ->
+matches_definition({_Name, {From, Who, What}}, Cmd, Module, Tag, Host, CallerInfo) ->
case What == all orelse lists:member(Cmd, What) of
true ->
- case From == [] orelse lists:member(Module, From) of
+ {Tags, Modules} = lists:partition(fun({tag, _}) -> true; (_) -> false end, From),
+ case (Modules == [] orelse lists:member(Module, Modules)) andalso
+ (Tags == [] orelse lists:member({tag, Tag}, Tags)) of
true ->
Scope = maps:get(oauth_scope, CallerInfo, none),
lists:any(
@@ -347,13 +350,15 @@ parse_api_permission(Name, Args0) ->
parse_from(_Name, Module) when is_atom(Module) ->
[Module];
parse_from(Name, Modules) when is_list(Modules) ->
- lists:foreach(fun(Module) when is_atom(Module) ->
- ok;
- (Val) ->
- report_error(<<"Invalid value '~p' used inside 'from' section for api_permission '~s'">>,
- [Val, Name])
- end, Modules),
- Modules;
+ lists:map(
+ fun(Module) when is_atom(Module) ->
+ Module;
+ ([{tag, Tag}]) when is_binary(Tag) ->
+ {tag, Tag};
+ (Val) ->
+ report_error(<<"Invalid value '~p' used inside 'from' section for api_permission '~s'">>,
+ [Val, Name])
+ end, Modules);
parse_from(Name, Val) ->
report_error(<<"Invalid value '~p' used inside 'from' section for api_permission '~s'">>,
[Val, Name]).
diff --git a/src/ejabberd_http.erl b/src/ejabberd_http.erl
index f2928a02e..c226dba1c 100644
--- a/src/ejabberd_http.erl
+++ b/src/ejabberd_http.erl
@@ -852,23 +852,23 @@ code_to_phrase(505) -> <<"HTTP Version Not Supported">>.
-spec parse_auth(binary()) -> {binary(), binary()} | {oauth, binary(), []} | undefined.
parse_auth(<<"Basic ", Auth64/binary>>) ->
- Auth = try base64:decode(Auth64)
- catch _:badarg -> <<>>
- end,
- %% Auth should be a string with the format: user@server:password
- %% Note that password can contain additional characters '@' and ':'
- case str:chr(Auth, $:) of
- 0 ->
- undefined;
- Pos ->
- {User, <<$:, Pass/binary>>} = erlang:split_binary(Auth, Pos-1),
- PassUtf8 = unicode:characters_to_binary(binary_to_list(Pass), utf8),
- {User, PassUtf8}
+ try base64:decode(Auth64) of
+ Auth ->
+ case binary:split(Auth, <<":">>) of
+ [User, Pass] ->
+ PassUtf8 = unicode:characters_to_binary(Pass, utf8),
+ {User, PassUtf8};
+ _ ->
+ invalid
+ end
+ catch _:_ ->
+ invalid
end;
parse_auth(<<"Bearer ", SToken/binary>>) ->
Token = str:strip(SToken),
{oauth, Token, []};
-parse_auth(<<_/binary>>) -> undefined.
+parse_auth(<<_/binary>>) ->
+ invalid.
parse_urlencoded(S) ->
parse_urlencoded(S, nokey, <<>>, key).
@@ -992,6 +992,8 @@ listen_opt_type(http_bind) ->
fun(B) when is_boolean(B) -> B end;
listen_opt_type(xmlrpc) ->
fun(B) when is_boolean(B) -> B end;
+listen_opt_type(tag) ->
+ fun(B) when is_binary(B) -> B end;
listen_opt_type(request_handlers) ->
fun(Hs) ->
Hs1 = lists:map(fun
@@ -1026,5 +1028,6 @@ listen_options() ->
{http_bind, false},
{xmlrpc, false},
{request_handlers, []},
+ {tag, <<>>},
{default_host, undefined},
{custom_headers, []}].
diff --git a/src/ejabberd_sql.erl b/src/ejabberd_sql.erl
index 153479026..2d9c64187 100644
--- a/src/ejabberd_sql.erl
+++ b/src/ejabberd_sql.erl
@@ -1071,9 +1071,9 @@ init_mssql(Host) ->
case filelib:ensure_dir(freetds_config()) of
ok ->
try
- ok = file:write_file(freetds_config(), FreeTDS, [append]),
- ok = file:write_file(odbcinst_config(), ODBCINST),
- ok = file:write_file(odbc_config(), ODBCINI, [append]),
+ ok = write_file_if_new(freetds_config(), FreeTDS),
+ ok = write_file_if_new(odbcinst_config(), ODBCINST),
+ ok = write_file_if_new(odbc_config(), ODBCINI),
os:putenv("ODBCSYSINI", tmp_dir()),
os:putenv("FREETDS", freetds_config()),
os:putenv("FREETDSCONF", freetds_config()),
@@ -1089,6 +1089,12 @@ init_mssql(Host) ->
Err
end.
+write_file_if_new(File, Payload) ->
+ case filelib:is_file(File) of
+ true -> ok;
+ false -> file:write_file(File, Payload)
+ end.
+
tmp_dir() ->
case os:type() of
{win32, _} -> filename:join([os:getenv("HOME"), "conf"]);
diff --git a/src/ejabberd_web_admin.erl b/src/ejabberd_web_admin.erl
index 0bcb87153..967af53ae 100644
--- a/src/ejabberd_web_admin.erl
+++ b/src/ejabberd_web_admin.erl
@@ -254,6 +254,7 @@ get_auth_admin(Auth, HostHTTP, RPath, Method) ->
catch _:{bad_jid, _} ->
{unauthorized, <<"badformed-jid">>}
end;
+ invalid -> {unauthorized, <<"no-auth-provided">>};
undefined -> {unauthorized, <<"no-auth-provided">>}
end.
diff --git a/src/mod_http_api.erl b/src/mod_http_api.erl
index 0d1d7c662..8cc80982a 100644
--- a/src/mod_http_api.erl
+++ b/src/mod_http_api.erl
@@ -137,39 +137,43 @@ depends(_Host, _Opts) ->
%% basic auth
%% ----------
-extract_auth(#request{auth = HTTPAuth, ip = {IP, _}}) ->
+extract_auth(#request{auth = HTTPAuth, ip = {IP, _}, opts = Opts}) ->
Info = case HTTPAuth of
- {SJID, Pass} ->
- try jid:decode(SJID) of
+ {SJID, Pass} ->
+ try jid:decode(SJID) of
#jid{luser = User, lserver = Server} ->
- case ejabberd_auth:check_password(User, <<"">>, Server, Pass) of
+ case ejabberd_auth:check_password(User, <<"">>, Server, Pass) of
true ->
#{usr => {User, Server, <<"">>}, caller_server => Server};
false ->
{error, invalid_auth}
- end
- catch _:{bad_jid, _} ->
- {error, invalid_auth}
- end;
- {oauth, Token, _} ->
+ end
+ catch _:{bad_jid, _} ->
+ {error, invalid_auth}
+ end;
+ {oauth, Token, _} ->
case ejabberd_oauth:check_token(Token) of
{ok, {U, S}, Scope} ->
#{usr => {U, S, <<"">>}, oauth_scope => Scope, caller_server => S};
{false, Reason} ->
{error, Reason}
- end;
- _ ->
+ end;
+ invalid ->
+ {error, invalid_auth};
+ _ ->
#{}
- end,
+ end,
case Info of
Map when is_map(Map) ->
- Map#{caller_module => ?MODULE, ip => IP};
+ Tag = proplists:get_value(tag, Opts, <<>>),
+ Map#{caller_module => ?MODULE, ip => IP, tag => Tag};
_ ->
?DEBUG("Invalid auth data: ~p", [Info]),
Info
end;
-extract_auth(#request{ip = IP}) ->
- #{ip => IP, caller_module => ?MODULE}.
+extract_auth(#request{ip = IP, opts = Opts}) ->
+ Tag = proplists:get_value(tag, Opts, <<>>),
+ #{ip => IP, caller_module => ?MODULE, tag => Tag}.
%% ------------------
%% command processing
@@ -353,7 +357,10 @@ format_args(Args, ArgsFormat) ->
{Args, []}, ArgsFormat),
case ArgsRemaining of
[] -> R;
- L when is_list(L) -> exit({additional_unused_args, L})
+ L when is_list(L) ->
+ throw({invalid_parameter,
+ io_lib:format("Request have unknown arguments: ~w",
+ [[N || {N, _} <- L]])})
end.
format_arg({Elements},
diff --git a/src/mod_muc_admin.erl b/src/mod_muc_admin.erl
index 6a125d848..616d54d28 100644
--- a/src/mod_muc_admin.erl
+++ b/src/mod_muc_admin.erl
@@ -116,14 +116,14 @@ get_commands_spec() ->
module = ?MODULE, function = muc_register_nick,
args_desc = ["Nick", "User JID", "Server Host"],
args_example = [<<"Tim">>, <<"tim@example.org">>, <<"example.org">>],
- args = [{nick, binary}, {jid, binary}, {serverhost, binary}],
+ args = [{nick, binary}, {jid, binary}, {host, binary}],
result = {res, rescode}},
#ejabberd_commands{name = muc_unregister_nick, tags = [muc],
desc = "Unregister the nick registered by that account in the MUC service",
module = ?MODULE, function = muc_unregister_nick,
args_desc = ["User JID", "MUC service"],
args_example = [<<"tim@example.org">>, <<"example.org">>],
- args = [{jid, binary}, {serverhost, binary}],
+ args = [{jid, binary}, {host, binary}],
result = {res, rescode}},
#ejabberd_commands{name = create_room, tags = [muc_room],