Use new ets_cache API in ejabberd_auth

This commit is contained in:
Evgeny Khramtsov 2019-06-30 17:15:43 +03:00
parent a2a061c1c8
commit 253ec13971
9 changed files with 98 additions and 95 deletions

View File

@ -20,7 +20,7 @@
{deps, [{lager, ".*", {git, "https://github.com/erlang-lager/lager", "3.6.10"}},
{p1_utils, ".*", {git, "https://github.com/processone/p1_utils", "2887223"}},
{cache_tab, ".*", {git, "https://github.com/processone/cache_tab", {tag, "1.0.19"}}},
{cache_tab, ".*", {git, "https://github.com/processone/cache_tab", "8c4487c"}},
{fast_tls, ".*", {git, "https://github.com/processone/fast_tls", {tag, "1.1.1"}}},
{stringprep, ".*", {git, "https://github.com/processone/stringprep", {tag, "1.0.16"}}},
{fast_xml, ".*", {git, "https://github.com/processone/fast_xml", "7fd02f3a2f"}},

View File

@ -72,14 +72,16 @@
-callback reload(binary()) -> any().
-callback plain_password_required(binary()) -> boolean().
-callback store_type(binary()) -> plain | external | scram.
-callback set_password(binary(), binary(), binary()) -> ok | {error, atom()}.
-callback remove_user(binary(), binary()) -> ok | {error, any()}.
-callback user_exists(binary(), binary()) -> boolean() | {error, atom()}.
-callback check_password(binary(), binary(), binary(), binary()) -> boolean().
-callback try_register(binary(), binary(), password()) -> ok | {error, atom()}.
-callback set_password(binary(), binary(), password()) ->
{ets_cache:tag(), {ok, password()} | {error, db_failure}}.
-callback remove_user(binary(), binary()) -> ok | {error, db_failure | not_allowed}.
-callback user_exists(binary(), binary()) -> {ets_cache:tag(), boolean() | {error, db_failure}}.
-callback check_password(binary(), binary(), binary(), binary()) -> {ets_cache:tag(), boolean()}.
-callback try_register(binary(), binary(), password()) ->
{ets_cache:tag(), {ok, password()} | {error, exists | db_failure | not_allowed}}.
-callback get_users(binary(), opts()) -> [{binary(), binary()}].
-callback count_users(binary(), opts()) -> number().
-callback get_password(binary(), binary()) -> {ok, password()} | error.
-callback get_password(binary(), binary()) -> {ets_cache:tag(), {ok, password()} | error}.
-callback use_cache(binary()) -> boolean().
-callback cache_nodes(binary()) -> boolean().
@ -610,9 +612,6 @@ db_user_exists(User, Server, Mod) ->
cache_tab(Mod), {User, Server},
fun() ->
case Mod:user_exists(User, Server) of
true -> {ok, exists};
false -> error;
{error, _} = Err -> Err;
{CacheTag, true} -> {CacheTag, {ok, exists}};
{CacheTag, false} -> {CacheTag, error};
{_, {error, _}} = Err -> Err
@ -645,8 +644,6 @@ db_check_password(User, AuthzId, Server, ProvidedPassword,
fun() ->
case Mod:check_password(
User, AuthzId, Server, ProvidedPassword) of
true -> {ok, ProvidedPassword};
false -> error;
{CacheTag, true} -> {CacheTag, {ok, ProvidedPassword}};
{CacheTag, false} -> {CacheTag, error}
end
@ -667,7 +664,7 @@ db_check_password(User, AuthzId, Server, ProvidedPassword,
db_remove_user(User, Server, Mod) ->
case erlang:function_exported(Mod, remove_user, 2) of
true ->
case ets_cache:untag(Mod:remove_user(User, Server)) of
case Mod:remove_user(User, Server) of
ok ->
case use_cache(Mod, Server) of
true ->
@ -686,7 +683,7 @@ db_remove_user(User, Server, Mod) ->
db_get_users(Server, Opts, Mod) ->
case erlang:function_exported(Mod, get_users, 2) of
true ->
ets_cache:untag(Mod:get_users(Server, Opts));
Mod:get_users(Server, Opts);
false ->
case use_cache(Mod, Server) of
true ->
@ -704,7 +701,7 @@ db_get_users(Server, Opts, Mod) ->
db_count_users(Server, Opts, Mod) ->
case erlang:function_exported(Mod, count_users, 2) of
true ->
ets_cache:untag(Mod:count_users(Server, Opts));
Mod:count_users(Server, Opts);
false ->
case use_cache(Mod, Server) of
true ->

View File

@ -148,16 +148,14 @@ unregister_connection(_SID,
%% Specific anonymous auth functions
%% ---------------------------------
check_password(User, _AuthzId, Server, _Password) ->
case
ejabberd_auth:user_exists_in_other_modules(?MODULE,
User, Server)
of
%% If user exists in other module, reject anonnymous authentication
true -> false;
%% If we are not sure whether the user exists in other module, reject anon auth
maybe -> false;
false -> login(User, Server)
end.
{nocache,
case ejabberd_auth:user_exists_in_other_modules(?MODULE, User, Server) of
%% If user exists in other module, reject anonnymous authentication
true -> false;
%% If we are not sure whether the user exists in other module, reject anon auth
maybe -> false;
false -> login(User, Server)
end}.
login(User, Server) ->
case is_login_anonymous_enabled(Server) of
@ -180,7 +178,7 @@ count_users(Server, Opts) ->
length(get_users(Server, Opts)).
user_exists(User, Server) ->
anonymous_user_exist(User, Server).
{nocache, anonymous_user_exist(User, Server)}.
plain_password_required(_) ->
false.

View File

@ -53,27 +53,27 @@ store_type(_) -> external.
check_password(User, AuthzId, Server, Password) ->
if AuthzId /= <<>> andalso AuthzId /= User ->
false;
{nocache, false};
true ->
check_password_extauth(User, AuthzId, Server, Password)
end.
set_password(User, Server, Password) ->
case extauth:set_password(User, Server, Password) of
Res when is_boolean(Res) -> ok;
Res when is_boolean(Res) -> {cache, {ok, Password}};
{error, Reason} -> failure(User, Server, set_password, Reason)
end.
try_register(User, Server, Password) ->
case extauth:try_register(User, Server, Password) of
true -> ok;
false -> {error, not_allowed};
true -> {cache, {ok, Password}};
false -> {cache, {error, not_allowed}};
{error, Reason} -> failure(User, Server, try_register, Reason)
end.
user_exists(User, Server) ->
case extauth:user_exists(User, Server) of
Res when is_boolean(Res) -> Res;
Res when is_boolean(Res) -> {cache, Res};
{error, Reason} -> failure(User, Server, user_exists, Reason)
end.
@ -81,23 +81,25 @@ remove_user(User, Server) ->
case extauth:remove_user(User, Server) of
false -> {error, not_allowed};
true -> ok;
{error, Reason} -> failure(User, Server, remove_user, Reason)
{error, Reason} ->
{_, Err} = failure(User, Server, remove_user, Reason),
Err
end.
check_password_extauth(User, _AuthzId, Server, Password) ->
if Password /= <<"">> ->
case extauth:check_password(User, Server, Password) of
Res when is_boolean(Res) -> Res;
Res when is_boolean(Res) -> {cache, Res};
{error, Reason} ->
_ = failure(User, Server, check_password, Reason),
false
{Tag, _} = failure(User, Server, check_password, Reason),
{Tag, false}
end;
true ->
false
{nocache, false}
end.
-spec failure(binary(), binary(), atom(), any()) -> {error, db_failure}.
-spec failure(binary(), binary(), atom(), any()) -> {nocache, {error, db_failure}}.
failure(User, Server, Fun, Reason) ->
?ERROR_MSG("External authentication program failed when calling "
"'~s' for ~s@~s: ~p", [Fun, User, Server, Reason]),
{error, db_failure}.
{nocache, {error, db_failure}}.

View File

@ -111,26 +111,25 @@ store_type(_) -> external.
check_password(User, AuthzId, Server, Password) ->
if AuthzId /= <<>> andalso AuthzId /= User ->
false;
{nocache, false};
Password == <<"">> ->
{nocache, false};
true ->
if Password == <<"">> -> false;
true ->
case catch check_password_ldap(User, Server, Password) of
{'EXIT', _} -> false;
Result -> Result
end
case catch check_password_ldap(User, Server, Password) of
{'EXIT', _} -> {nocache, false};
Result -> {cache, Result}
end
end.
set_password(User, Server, Password) ->
{ok, State} = eldap_utils:get_state(Server, ?MODULE),
case find_user_dn(User, State) of
false -> {error, notfound};
false -> {cache, {error, db_failure}};
DN ->
case eldap_pool:modify_passwd(State#state.eldap_id, DN,
Password) of
ok -> ok;
_Err -> {error, db_failure}
ok -> {cache, {ok, Password}};
_Err -> {nocache, {error, db_failure}}
end
end.
@ -146,8 +145,8 @@ count_users(Server, Opts) ->
%% @spec (User, Server) -> true | false | {error, Error}
user_exists(User, Server) ->
case catch user_exists_ldap(User, Server) of
{'EXIT', _Error} -> {error, db_failure};
Result -> Result
{'EXIT', _Error} -> {nocache, {error, db_failure}};
Result -> {cache, Result}
end.
%%%----------------------------------------------------------------------

View File

@ -93,10 +93,10 @@ set_password(User, Server, Password) ->
end,
case mnesia:transaction(F) of
{atomic, ok} ->
ok;
{cache, {ok, Password}};
{aborted, Reason} ->
?ERROR_MSG("Mnesia transaction failed: ~p", [Reason]),
{error, db_failure}
{nocache, {error, db_failure}}
end.
try_register(User, Server, Password) ->
@ -106,17 +106,17 @@ try_register(User, Server, Password) ->
[] ->
mnesia:write(#passwd{us = US, password = Password}),
mnesia:dirty_update_counter(reg_users_counter, Server, 1),
ok;
{ok, Password};
[_] ->
{error, exists}
end
end,
case mnesia:transaction(F) of
{atomic, Res} ->
Res;
{cache, Res};
{aborted, Reason} ->
?ERROR_MSG("Mnesia transaction failed: ~p", [Reason]),
{error, db_failure}
{nocache, {error, db_failure}}
end.
get_users(Server, []) ->
@ -181,9 +181,9 @@ count_users(Server, _) ->
get_password(User, Server) ->
case mnesia:dirty_read(passwd, {User, Server}) of
[#passwd{password = Password}] ->
{ok, Password};
{cache, {ok, Password}};
_ ->
error
{cache, error}
end.
remove_user(User, Server) ->

View File

@ -39,19 +39,18 @@ stop(_Host) ->
check_password(User, AuthzId, Host, Password) ->
if AuthzId /= <<>> andalso AuthzId /= User ->
false;
true ->
Service = get_pam_service(Host),
UserInfo = case get_pam_userinfotype(Host) of
username -> User;
jid -> <<User/binary, "@", Host/binary>>
end,
case catch epam:authenticate(Service, UserInfo,
Password)
of
true -> true;
_ -> false
end
false;
true ->
Service = get_pam_service(Host),
UserInfo = case get_pam_userinfotype(Host) of
username -> User;
jid -> <<User/binary, "@", Host/binary>>
end,
case catch epam:authenticate(Service, UserInfo, Password) of
true -> {cache, true};
false -> {cache, false};
_ -> {nocache, false}
end
end.
user_exists(User, Host) ->
@ -61,9 +60,9 @@ user_exists(User, Host) ->
jid -> <<User/binary, "@", Host/binary>>
end,
case catch epam:acct_mgmt(Service, UserInfo) of
true -> true;
false -> false;
_Err -> {error, db_failure}
true -> {cache, true};
false -> {cache, false};
_Err -> {nocache, {error, db_failure}}
end.
plain_password_required(_) -> true.

View File

@ -56,21 +56,27 @@ passwd_schema() ->
{record_info(fields, passwd), #passwd{}}.
set_password(User, Server, Password) ->
ejabberd_riak:put(#passwd{us = {User, Server}, password = Password},
passwd_schema(),
[{'2i', [{<<"host">>, Server}]}]).
case ejabberd_riak:put(#passwd{us = {User, Server}, password = Password},
passwd_schema(),
[{'2i', [{<<"host">>, Server}]}]) of
ok -> {cache, {ok, Password}};
{error, _} -> {nocache, {error, db_failure}}
end.
try_register(User, Server, Password) ->
US = {User, Server},
case ejabberd_riak:get(passwd, passwd_schema(), US) of
{error, notfound} ->
ejabberd_riak:put(#passwd{us = US, password = Password},
passwd_schema(),
[{'2i', [{<<"host">>, Server}]}]);
case ejabberd_riak:put(#passwd{us = US, password = Password},
passwd_schema(),
[{'2i', [{<<"host">>, Server}]}]) of
ok -> {cache, {ok, Password}};
{error, _} -> {nocache, {error, db_failure}}
end;
{ok, _} ->
{error, exists};
{error, _} = Err ->
Err
{cache, {error, exists}};
{error, _} ->
{nocache, {error, db_failure}}
end.
get_users(Server, _) ->
@ -92,9 +98,11 @@ count_users(Server, _) ->
get_password(User, Server) ->
case ejabberd_riak:get(passwd, passwd_schema(), {User, Server}) of
{ok, Password} ->
{ok, Password};
{cache, {ok, Password}};
{error, notfound} ->
{cache, error};
{error, _} ->
error
{nocache, error}
end.
remove_user(User, Server) ->

View File

@ -68,9 +68,9 @@ set_password(User, Server, Password) ->
end,
case ejabberd_sql:sql_transaction(Server, F) of
{atomic, _} ->
ok;
{cache, {ok, Password}};
{aborted, _} ->
{error, db_failure}
{nocache, {error, db_failure}}
end.
try_register(User, Server, Password) ->
@ -83,8 +83,8 @@ try_register(User, Server, Password) ->
add_user(Server, User, Password)
end,
case Res of
{updated, 1} -> ok;
_ -> {error, exists}
{updated, 1} -> {cache, {ok, Password}};
_ -> {nocache, {error, exists}}
end.
get_users(Server, Opts) ->
@ -104,16 +104,16 @@ count_users(Server, Opts) ->
get_password(User, Server) ->
case get_password_scram(Server, User) of
{selected, [{Password, <<>>, <<>>, 0}]} ->
{ok, Password};
{cache, {ok, Password}};
{selected, [{StoredKey, ServerKey, Salt, IterationCount}]} ->
{ok, #scram{storedkey = StoredKey,
serverkey = ServerKey,
salt = Salt,
iterationcount = IterationCount}};
{cache, {ok, #scram{storedkey = StoredKey,
serverkey = ServerKey,
salt = Salt,
iterationcount = IterationCount}}};
{selected, []} ->
error;
{cache, error};
_ ->
error
{nocache, error}
end.
remove_user(User, Server) ->