From 56baa07d486f68fc5275d830837bdd918680d28b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Wed, 30 Jan 2019 16:34:29 +0100 Subject: [PATCH] Reject request http_api request that have malformed Authentication header --- src/ejabberd_http.erl | 26 +++++++++++++------------- src/ejabberd_web_admin.erl | 1 + src/mod_http_api.erl | 24 +++++++++++++----------- 3 files changed, 27 insertions(+), 24 deletions(-) diff --git a/src/ejabberd_http.erl b/src/ejabberd_http.erl index b3222fb14..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). 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 d31ca0f11..7a4c73315 100644 --- a/src/mod_http_api.erl +++ b/src/mod_http_api.erl @@ -139,28 +139,30 @@ depends(_Host, _Opts) -> 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) -> Tag = proplists:get_value(tag, Opts, <<>>),