diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/ejabberd_access_permissions.erl | 25 | ||||
-rw-r--r-- | src/ejabberd_http.erl | 29 | ||||
-rw-r--r-- | src/ejabberd_sql.erl | 12 | ||||
-rw-r--r-- | src/ejabberd_web_admin.erl | 1 | ||||
-rw-r--r-- | src/mod_http_api.erl | 39 | ||||
-rw-r--r-- | src/mod_muc_admin.erl | 4 |
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], |