diff --git a/rebar.config b/rebar.config index 9809c28b6..4f477ebfa 100644 --- a/rebar.config +++ b/rebar.config @@ -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"}}, diff --git a/src/ejabberd_auth.erl b/src/ejabberd_auth.erl index fff63e811..1c5eddfd8 100644 --- a/src/ejabberd_auth.erl +++ b/src/ejabberd_auth.erl @@ -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 -> diff --git a/src/ejabberd_auth_anonymous.erl b/src/ejabberd_auth_anonymous.erl index 805076aff..efccdd8a7 100644 --- a/src/ejabberd_auth_anonymous.erl +++ b/src/ejabberd_auth_anonymous.erl @@ -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. diff --git a/src/ejabberd_auth_external.erl b/src/ejabberd_auth_external.erl index bae540e21..c5aac836a 100644 --- a/src/ejabberd_auth_external.erl +++ b/src/ejabberd_auth_external.erl @@ -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}}. diff --git a/src/ejabberd_auth_ldap.erl b/src/ejabberd_auth_ldap.erl index d52e7a1c0..3f5429395 100644 --- a/src/ejabberd_auth_ldap.erl +++ b/src/ejabberd_auth_ldap.erl @@ -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. %%%---------------------------------------------------------------------- diff --git a/src/ejabberd_auth_mnesia.erl b/src/ejabberd_auth_mnesia.erl index 5c252b277..efd6be19f 100644 --- a/src/ejabberd_auth_mnesia.erl +++ b/src/ejabberd_auth_mnesia.erl @@ -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) -> diff --git a/src/ejabberd_auth_pam.erl b/src/ejabberd_auth_pam.erl index 840fa9f40..9051f4c88 100644 --- a/src/ejabberd_auth_pam.erl +++ b/src/ejabberd_auth_pam.erl @@ -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 -> <> - 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 -> <> + 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 -> <> 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. diff --git a/src/ejabberd_auth_riak.erl b/src/ejabberd_auth_riak.erl index 00f3f5227..839bbc720 100644 --- a/src/ejabberd_auth_riak.erl +++ b/src/ejabberd_auth_riak.erl @@ -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) -> diff --git a/src/ejabberd_auth_sql.erl b/src/ejabberd_auth_sql.erl index 0d7ff1b81..413c6a02f 100644 --- a/src/ejabberd_auth_sql.erl +++ b/src/ejabberd_auth_sql.erl @@ -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) ->