mirror of
https://github.com/processone/ejabberd.git
synced 2024-12-22 17:28:25 +01:00
Add auth_external_user_exists_check
option
This makes `user_check` hook work better with authentication methods that don't have a way to determine if user exists (like is the case for jwt and cert based authentication), and as result will improve mod_offline and mod_mam handling of offline messages to those users. This reuses information stored by `mod_last` for this purpose. Should fix issue #3377.
This commit is contained in:
parent
9acf591242
commit
12d47455ba
@ -398,15 +398,29 @@ user_exists(_User, <<"">>) ->
|
|||||||
user_exists(User, Server) ->
|
user_exists(User, Server) ->
|
||||||
case validate_credentials(User, Server) of
|
case validate_credentials(User, Server) of
|
||||||
{ok, LUser, LServer} ->
|
{ok, LUser, LServer} ->
|
||||||
lists:any(
|
{Exists, PerformExternalUserCheck} =
|
||||||
fun(M) ->
|
lists:foldl(
|
||||||
case db_user_exists(LUser, LServer, M) of
|
fun(M, {Exists0, PerformExternalUserCheck0}) ->
|
||||||
{error, _} ->
|
case db_user_exists(LUser, LServer, M) of
|
||||||
false;
|
{{error, _}, Check} ->
|
||||||
Else ->
|
{Exists0, PerformExternalUserCheck0 orelse Check};
|
||||||
Else
|
{Else, Check2} ->
|
||||||
end
|
{Exists0 orelse Else, PerformExternalUserCheck0 orelse Check2}
|
||||||
end, auth_modules(LServer));
|
end
|
||||||
|
end, {false, false}, auth_modules(LServer)),
|
||||||
|
case (not Exists) andalso PerformExternalUserCheck andalso
|
||||||
|
ejabberd_option:auth_external_user_exists_check(Server) andalso
|
||||||
|
gen_mod:is_loaded(Server, mod_last) of
|
||||||
|
true ->
|
||||||
|
case mod_last:get_last_info(User, Server) of
|
||||||
|
not_found ->
|
||||||
|
false;
|
||||||
|
_ ->
|
||||||
|
true
|
||||||
|
end;
|
||||||
|
_ ->
|
||||||
|
Exists
|
||||||
|
end;
|
||||||
_ ->
|
_ ->
|
||||||
false
|
false
|
||||||
end.
|
end.
|
||||||
@ -420,11 +434,11 @@ user_exists_in_other_modules_loop([], _User, _Server) ->
|
|||||||
false;
|
false;
|
||||||
user_exists_in_other_modules_loop([AuthModule | AuthModules], User, Server) ->
|
user_exists_in_other_modules_loop([AuthModule | AuthModules], User, Server) ->
|
||||||
case db_user_exists(User, Server, AuthModule) of
|
case db_user_exists(User, Server, AuthModule) of
|
||||||
true ->
|
{true, _} ->
|
||||||
true;
|
true;
|
||||||
false ->
|
{false, _} ->
|
||||||
user_exists_in_other_modules_loop(AuthModules, User, Server);
|
user_exists_in_other_modules_loop(AuthModules, User, Server);
|
||||||
{error, _} ->
|
{{error, _}, _} ->
|
||||||
maybe
|
maybe
|
||||||
end.
|
end.
|
||||||
|
|
||||||
@ -628,9 +642,9 @@ db_get_password(User, Server, Mod) ->
|
|||||||
db_user_exists(User, Server, Mod) ->
|
db_user_exists(User, Server, Mod) ->
|
||||||
case db_get_password(User, Server, Mod) of
|
case db_get_password(User, Server, Mod) of
|
||||||
{ok, _} ->
|
{ok, _} ->
|
||||||
true;
|
{true, false};
|
||||||
not_found ->
|
not_found ->
|
||||||
false;
|
{false, false};
|
||||||
error ->
|
error ->
|
||||||
case {Mod:store_type(Server), use_cache(Mod, Server)} of
|
case {Mod:store_type(Server), use_cache(Mod, Server)} of
|
||||||
{external, true} ->
|
{external, true} ->
|
||||||
@ -649,18 +663,18 @@ db_user_exists(User, Server, Mod) ->
|
|||||||
end,
|
end,
|
||||||
case Val of
|
case Val of
|
||||||
{ok, _} ->
|
{ok, _} ->
|
||||||
true;
|
{true, Mod /= ejabberd_auth_anonymous} ;
|
||||||
not_found ->
|
not_found ->
|
||||||
false;
|
{false, Mod /= ejabberd_auth_anonymous};
|
||||||
error ->
|
error ->
|
||||||
false;
|
{false, Mod /= ejabberd_auth_anonymous};
|
||||||
{error, _} = Err ->
|
{error, _} = Err ->
|
||||||
Err
|
{Err, Mod /= ejabberd_auth_anonymous}
|
||||||
end;
|
end;
|
||||||
{external, false} ->
|
{external, false} ->
|
||||||
ets_cache:untag(Mod:user_exists(User, Server));
|
{ets_cache:untag(Mod:user_exists(User, Server)), Mod /= ejabberd_auth_anonymous};
|
||||||
_ ->
|
_ ->
|
||||||
false
|
{false, false}
|
||||||
end
|
end
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
-export([auth_cache_life_time/0]).
|
-export([auth_cache_life_time/0]).
|
||||||
-export([auth_cache_missed/0]).
|
-export([auth_cache_missed/0]).
|
||||||
-export([auth_cache_size/0]).
|
-export([auth_cache_size/0]).
|
||||||
|
-export([auth_external_user_exists_check/0, auth_external_user_exists_check/1]).
|
||||||
-export([auth_method/0, auth_method/1]).
|
-export([auth_method/0, auth_method/1]).
|
||||||
-export([auth_opts/0, auth_opts/1]).
|
-export([auth_opts/0, auth_opts/1]).
|
||||||
-export([auth_password_format/0, auth_password_format/1]).
|
-export([auth_password_format/0, auth_password_format/1]).
|
||||||
@ -224,6 +225,13 @@ auth_cache_missed() ->
|
|||||||
auth_cache_size() ->
|
auth_cache_size() ->
|
||||||
ejabberd_config:get_option({auth_cache_size, global}).
|
ejabberd_config:get_option({auth_cache_size, global}).
|
||||||
|
|
||||||
|
-spec auth_external_user_exists_check() -> boolean().
|
||||||
|
auth_external_user_exists_check() ->
|
||||||
|
auth_external_user_exists_check(global).
|
||||||
|
-spec auth_external_user_exists_check(global | binary()) -> boolean().
|
||||||
|
auth_external_user_exists_check(Host) ->
|
||||||
|
ejabberd_config:get_option({auth_external_user_exists_check, Host}).
|
||||||
|
|
||||||
-spec auth_method() -> [atom()].
|
-spec auth_method() -> [atom()].
|
||||||
auth_method() ->
|
auth_method() ->
|
||||||
auth_method(global).
|
auth_method(global).
|
||||||
|
@ -81,6 +81,8 @@ opt_type(auth_password_format) ->
|
|||||||
econf:enum([plain, scram]);
|
econf:enum([plain, scram]);
|
||||||
opt_type(auth_scram_hash) ->
|
opt_type(auth_scram_hash) ->
|
||||||
econf:enum([sha, sha256, sha512]);
|
econf:enum([sha, sha256, sha512]);
|
||||||
|
opt_type(auth_external_user_exists_check) ->
|
||||||
|
econf:bool();
|
||||||
opt_type(auth_use_cache) ->
|
opt_type(auth_use_cache) ->
|
||||||
econf:bool();
|
econf:bool();
|
||||||
opt_type(c2s_cafile) ->
|
opt_type(c2s_cafile) ->
|
||||||
@ -542,6 +544,7 @@ options() ->
|
|||||||
{auth_opts, []},
|
{auth_opts, []},
|
||||||
{auth_password_format, plain},
|
{auth_password_format, plain},
|
||||||
{auth_scram_hash, sha},
|
{auth_scram_hash, sha},
|
||||||
|
{auth_external_user_exists_check, true},
|
||||||
{auth_use_cache,
|
{auth_use_cache,
|
||||||
fun(Host) -> ejabberd_config:get_option({use_cache, Host}) end},
|
fun(Host) -> ejabberd_config:get_option({use_cache, Host}) end},
|
||||||
{c2s_cafile, undefined},
|
{c2s_cafile, undefined},
|
||||||
|
@ -395,6 +395,13 @@ doc() ->
|
|||||||
"You shouldn't change this if you already have passwords generated with "
|
"You shouldn't change this if you already have passwords generated with "
|
||||||
"a different algorithm - users that have such passwords will not be able "
|
"a different algorithm - users that have such passwords will not be able "
|
||||||
"to authenticate. The default value is 'sha'.")}},
|
"to authenticate. The default value is 'sha'.")}},
|
||||||
|
{auth_external_user_exists_check,
|
||||||
|
#{value => "true | false",
|
||||||
|
desc =>
|
||||||
|
?T("Supplement check for user existence based on 'mod_last' data, for authentication "
|
||||||
|
"methods that don't have a way to reliable tell if user exists (like is the case for "
|
||||||
|
"'jwt' and certificate based authentication). This helps with processing offline message "
|
||||||
|
"for those users. The default value is 'true'.")}},
|
||||||
{auth_use_cache,
|
{auth_use_cache,
|
||||||
#{value => "true | false",
|
#{value => "true | false",
|
||||||
desc =>
|
desc =>
|
||||||
|
Loading…
Reference in New Issue
Block a user