diff options
author | Badlop <badlop@process-one.net> | 2013-03-14 10:33:02 +0100 |
---|---|---|
committer | Badlop <badlop@process-one.net> | 2013-03-14 10:33:02 +0100 |
commit | 9deb294328bb3f9eb6bd2c0e7cd500732e9b5830 (patch) | |
tree | 7e1066c130250627ee0abab44a135f583a28d07f /src/ejabberd_auth.erl | |
parent | list_to_integer/2 only works in OTP R14 and newer (diff) |
Accumulated patch to binarize and indent code
Diffstat (limited to 'src/ejabberd_auth.erl')
-rw-r--r-- | src/ejabberd_auth.erl | 523 |
1 files changed, 289 insertions, 234 deletions
diff --git a/src/ejabberd_auth.erl b/src/ejabberd_auth.erl index 7485f823..298cdf1e 100644 --- a/src/ejabberd_auth.erl +++ b/src/ejabberd_auth.erl @@ -27,32 +27,21 @@ %% TODO: Use the functions in ejabberd auth to add and remove users. -module(ejabberd_auth). + -author('alexey@process-one.net'). %% External exports --export([start/0, - set_password/3, - check_password/3, - check_password/5, - check_password_with_authmodule/3, - check_password_with_authmodule/5, - try_register/3, - dirty_get_registered_users/0, - get_vh_registered_users/1, - get_vh_registered_users/2, +-export([start/0, set_password/3, check_password/3, + check_password/5, check_password_with_authmodule/3, + check_password_with_authmodule/5, try_register/3, + dirty_get_registered_users/0, get_vh_registered_users/1, + get_vh_registered_users/2, export/1, get_vh_registered_users_number/1, - get_vh_registered_users_number/2, - get_password/2, - get_password_s/2, - get_password_with_authmodule/2, - is_user_exists/2, - is_user_exists_in_other_modules/3, - remove_user/2, - remove_user/3, - plain_password_required/1, - store_type/1, - entropy/1 - ]). + get_vh_registered_users_number/2, get_password/2, + get_password_s/2, get_password_with_authmodule/2, + is_user_exists/2, is_user_exists_in_other_modules/3, + remove_user/2, remove_user/3, plain_password_required/1, + store_type/1, entropy/1]). -export([auth_modules/1]). @@ -61,55 +50,80 @@ %%%---------------------------------------------------------------------- %%% API %%%---------------------------------------------------------------------- -start() -> - lists:foreach( - fun(Host) -> - lists:foreach( - fun(M) -> - M:start(Host) - end, auth_modules(Host)) - end, ?MYHOSTS). +-type opts() :: [{prefix, binary()} | {from, integer()} | + {to, integer()} | {limit, integer()} | + {offset, integer()}]. + +-callback start(binary()) -> any(). +-callback plain_password_required() -> boolean(). +-callback store_type() -> plain | external | scram. +-callback set_password(binary(), binary(), binary()) -> ok | {error, atom()}. +-callback remove_user(binary(), binary()) -> any(). +-callback remove_user(binary(), binary(), binary()) -> any(). +-callback is_user_exists(binary(), binary()) -> boolean() | {error, atom()}. +-callback check_password(binary(), binary(), binary()) -> boolean(). +-callback check_password(binary(), binary(), binary(), binary(), + fun((binary()) -> binary())) -> boolean(). +-callback try_register(binary(), binary(), binary()) -> {atomic, atom()} | + {error, atom()}. +-callback dirty_get_registered_users() -> [{binary(), binary()}]. +-callback get_vh_registered_users(binary()) -> [{binary(), binary()}]. +-callback get_vh_registered_users(binary(), opts()) -> [{binary(), binary()}]. +-callback get_vh_registered_users_number(binary()) -> number(). +-callback get_vh_registered_users_number(binary(), opts()) -> number(). +-callback get_password(binary(), binary()) -> false | binary(). +-callback get_password_s(binary(), binary()) -> binary(). +start() -> %% This is only executed by ejabberd_c2s for non-SASL auth client + lists:foreach(fun (Host) -> + lists:foreach(fun (M) -> M:start(Host) end, + auth_modules(Host)) + end, + ?MYHOSTS). + plain_password_required(Server) -> - lists:any( - fun(M) -> - M:plain_password_required() - end, auth_modules(Server)). + lists:any(fun (M) -> M:plain_password_required() end, + auth_modules(Server)). store_type(Server) -> - lists:foldl( - fun(_, external) -> - external; - (M, scram) -> - case M:store_type() of - external -> - external; - _Else -> - scram - end; - (M, plain) -> - M:store_type() - end, plain, auth_modules(Server)). - %% @doc Check if the user and password can login in server. %% @spec (User::string(), Server::string(), Password::string()) -> %% true | false + lists:foldl(fun (_, external) -> external; + (M, scram) -> + case M:store_type() of + external -> external; + _Else -> scram + end; + (M, plain) -> M:store_type() + end, + plain, auth_modules(Server)). + +-spec check_password(binary(), binary(), binary()) -> boolean(). + check_password(User, Server, Password) -> - case check_password_with_authmodule(User, Server, Password) of - {true, _AuthModule} -> true; - false -> false + case check_password_with_authmodule(User, Server, + Password) + of + {true, _AuthModule} -> true; + false -> false end. %% @doc Check if the user and password can login in server. %% @spec (User::string(), Server::string(), Password::string(), %% Digest::string(), DigestGen::function()) -> %% true | false -check_password(User, Server, Password, Digest, DigestGen) -> - case check_password_with_authmodule(User, Server, Password, - Digest, DigestGen) of - {true, _AuthModule} -> true; - false -> false +-spec check_password(binary(), binary(), binary(), binary(), + fun((binary()) -> binary())) -> boolean(). + +check_password(User, Server, Password, Digest, + DigestGen) -> + case check_password_with_authmodule(User, Server, + Password, Digest, DigestGen) + of + {true, _AuthModule} -> true; + false -> false end. %% @doc Check if the user and password can login in server. @@ -122,199 +136,224 @@ check_password(User, Server, Password, Digest, DigestGen) -> %% AuthModule = ejabberd_auth_anonymous | ejabberd_auth_external %% | ejabberd_auth_internal | ejabberd_auth_ldap %% | ejabberd_auth_odbc | ejabberd_auth_pam -check_password_with_authmodule(User, Server, Password) -> - check_password_loop(auth_modules(Server), [User, Server, Password]). +-spec check_password_with_authmodule(binary(), binary(), binary()) -> false | + {true, atom()}. -check_password_with_authmodule(User, Server, Password, Digest, DigestGen) -> - check_password_loop(auth_modules(Server), [User, Server, Password, - Digest, DigestGen]). +check_password_with_authmodule(User, Server, + Password) -> + check_password_loop(auth_modules(Server), + [User, Server, Password]). -check_password_loop([], _Args) -> - false; +-spec check_password_with_authmodule(binary(), binary(), binary(), binary(), + fun((binary()) -> binary())) -> false | + {true, atom()}. + +check_password_with_authmodule(User, Server, Password, + Digest, DigestGen) -> + check_password_loop(auth_modules(Server), + [User, Server, Password, Digest, DigestGen]). + +check_password_loop([], _Args) -> false; check_password_loop([AuthModule | AuthModules], Args) -> case apply(AuthModule, check_password, Args) of - true -> - {true, AuthModule}; - false -> - check_password_loop(AuthModules, Args) + true -> {true, AuthModule}; + false -> check_password_loop(AuthModules, Args) end. +-spec set_password(binary(), binary(), binary()) -> ok | + {error, atom()}. %% @spec (User::string(), Server::string(), Password::string()) -> %% ok | {error, ErrorType} %% where ErrorType = empty_password | not_allowed | invalid_jid -set_password(_User, _Server, "") -> - %% We do not allow empty password +set_password(_User, _Server, <<"">>) -> {error, empty_password}; set_password(User, Server, Password) -> - lists:foldl( - fun(M, {error, _}) -> - M:set_password(User, Server, Password); - (_M, Res) -> - Res - end, {error, not_allowed}, auth_modules(Server)). - %% @spec (User, Server, Password) -> {atomic, ok} | {atomic, exists} | {error, not_allowed} -try_register(_User, _Server, "") -> - %% We do not allow empty password - {error, not_allowed}; + lists:foldl(fun (M, {error, _}) -> + M:set_password(User, Server, Password); + (_M, Res) -> Res + end, + {error, not_allowed}, auth_modules(Server)). + +-spec try_register(binary(), binary(), binary()) -> {atomic, atom()} | + {error, atom()}. + +try_register(_User, _Server, <<"">>) -> + {error, not_allowed}; try_register(User, Server, Password) -> - case is_user_exists(User,Server) of - true -> - {atomic, exists}; - false -> - case lists:member(jlib:nameprep(Server), ?MYHOSTS) of - true -> - Res = lists:foldl( - fun(_M, {atomic, ok} = Res) -> - Res; - (M, _) -> - M:try_register(User, Server, Password) - end, {error, not_allowed}, auth_modules(Server)), - case Res of - {atomic, ok} -> - ejabberd_hooks:run(register_user, Server, - [User, Server]), - {atomic, ok}; - _ -> Res - end; - false -> - {error, not_allowed} - end + case is_user_exists(User, Server) of + true -> {atomic, exists}; + false -> + case lists:member(jlib:nameprep(Server), ?MYHOSTS) of + true -> + Res = lists:foldl(fun (_M, {atomic, ok} = Res) -> Res; + (M, _) -> + M:try_register(User, Server, Password) + end, + {error, not_allowed}, auth_modules(Server)), + case Res of + {atomic, ok} -> + ejabberd_hooks:run(register_user, Server, + [User, Server]), + {atomic, ok}; + _ -> Res + end; + false -> {error, not_allowed} + end end. %% Registered users list do not include anonymous users logged +-spec dirty_get_registered_users() -> [{binary(), binary()}]. + dirty_get_registered_users() -> - lists:flatmap( - fun(M) -> - M:dirty_get_registered_users() - end, auth_modules()). + lists:flatmap(fun (M) -> M:dirty_get_registered_users() + end, + auth_modules()). + +-spec get_vh_registered_users(binary()) -> [{binary(), binary()}]. %% Registered users list do not include anonymous users logged get_vh_registered_users(Server) -> - lists:flatmap( - fun(M) -> - M:get_vh_registered_users(Server) - end, auth_modules(Server)). + lists:flatmap(fun (M) -> + M:get_vh_registered_users(Server) + end, + auth_modules(Server)). + +-spec get_vh_registered_users(binary(), opts()) -> [{binary(), binary()}]. get_vh_registered_users(Server, Opts) -> - lists:flatmap( - fun(M) -> - case erlang:function_exported( - M, get_vh_registered_users, 2) of - true -> - M:get_vh_registered_users(Server, Opts); - false -> - M:get_vh_registered_users(Server) - end - end, auth_modules(Server)). + lists:flatmap(fun (M) -> + case erlang:function_exported(M, + get_vh_registered_users, + 2) + of + true -> M:get_vh_registered_users(Server, Opts); + false -> M:get_vh_registered_users(Server) + end + end, + auth_modules(Server)). get_vh_registered_users_number(Server) -> - lists:sum( - lists:map( - fun(M) -> - case erlang:function_exported( - M, get_vh_registered_users_number, 1) of - true -> - M:get_vh_registered_users_number(Server); - false -> - length(M:get_vh_registered_users(Server)) - end - end, auth_modules(Server))). + lists:sum(lists:map(fun (M) -> + case erlang:function_exported(M, + get_vh_registered_users_number, + 1) + of + true -> + M:get_vh_registered_users_number(Server); + false -> + length(M:get_vh_registered_users(Server)) + end + end, + auth_modules(Server))). + +-spec get_vh_registered_users_number(binary(), opts()) -> number(). get_vh_registered_users_number(Server, Opts) -> - lists:sum( - lists:map( - fun(M) -> - case erlang:function_exported( - M, get_vh_registered_users_number, 2) of - true -> - M:get_vh_registered_users_number(Server, Opts); - false -> - length(M:get_vh_registered_users(Server)) - end - end, auth_modules(Server))). - %% @doc Get the password of the user. %% @spec (User::string(), Server::string()) -> Password::string() + lists:sum(lists:map(fun (M) -> + case erlang:function_exported(M, + get_vh_registered_users_number, + 2) + of + true -> + M:get_vh_registered_users_number(Server, + Opts); + false -> + length(M:get_vh_registered_users(Server)) + end + end, + auth_modules(Server))). + +-spec get_password(binary(), binary()) -> false | binary(). + get_password(User, Server) -> - lists:foldl( - fun(M, false) -> - M:get_password(User, Server); - (_M, Password) -> - Password - end, false, auth_modules(Server)). + lists:foldl(fun (M, false) -> + M:get_password(User, Server); + (_M, Password) -> Password + end, + false, auth_modules(Server)). + +-spec get_password_s(binary(), binary()) -> binary(). get_password_s(User, Server) -> case get_password(User, Server) of - false -> - ""; - Password when is_list(Password) -> - Password; - _ -> - "" + false -> <<"">>; + Password -> Password end. %% @doc Get the password of the user and the auth module. %% @spec (User::string(), Server::string()) -> %% {Password::string(), AuthModule::atom()} | {false, none} -get_password_with_authmodule(User, Server) -> - lists:foldl( - fun(M, {false, _}) -> - {M:get_password(User, Server), M}; - (_M, {Password, AuthModule}) -> - {Password, AuthModule} - end, {false, none}, auth_modules(Server)). +-spec get_password_with_authmodule(binary(), binary()) -> {false | binary(), atom()}. +get_password_with_authmodule(User, Server) -> %% Returns true if the user exists in the DB or if an anonymous user is logged %% under the given name -is_user_exists(User, Server) -> - lists:any( - fun(M) -> - case M:is_user_exists(User, Server) of - {error, Error} -> - ?ERROR_MSG("The authentication module ~p returned an " - "error~nwhen checking user ~p in server ~p~n" - "Error message: ~p", - [M, User, Server, Error]), - false; - Else -> - Else - end - end, auth_modules(Server)). + lists:foldl(fun (M, {false, _}) -> + {M:get_password(User, Server), M}; + (_M, {Password, AuthModule}) -> {Password, AuthModule} + end, + {false, none}, auth_modules(Server)). +-spec is_user_exists(binary(), binary()) -> boolean(). + +is_user_exists(User, Server) -> %% Check if the user exists in all authentications module except the module %% passed as parameter %% @spec (Module::atom(), User, Server) -> true | false | maybe + lists:any(fun (M) -> + case M:is_user_exists(User, Server) of + {error, Error} -> + ?ERROR_MSG("The authentication module ~p returned " + "an error~nwhen checking user ~p in server " + "~p~nError message: ~p", + [M, User, Server, Error]), + false; + Else -> Else + end + end, + auth_modules(Server)). + +-spec is_user_exists_in_other_modules(atom(), binary(), binary()) -> boolean() | maybe. + is_user_exists_in_other_modules(Module, User, Server) -> - is_user_exists_in_other_modules_loop( - auth_modules(Server)--[Module], - User, Server). -is_user_exists_in_other_modules_loop([], _User, _Server) -> + is_user_exists_in_other_modules_loop(auth_modules(Server) + -- [Module], + User, Server). + +is_user_exists_in_other_modules_loop([], _User, + _Server) -> false; -is_user_exists_in_other_modules_loop([AuthModule|AuthModules], User, Server) -> +is_user_exists_in_other_modules_loop([AuthModule + | AuthModules], + User, Server) -> case AuthModule:is_user_exists(User, Server) of - true -> - true; - false -> - is_user_exists_in_other_modules_loop(AuthModules, User, Server); - {error, Error} -> - ?DEBUG("The authentication module ~p returned an error~nwhen " - "checking user ~p in server ~p~nError message: ~p", - [AuthModule, User, Server, Error]), - maybe + true -> true; + false -> + is_user_exists_in_other_modules_loop(AuthModules, User, + Server); + {error, Error} -> + ?DEBUG("The authentication module ~p returned " + "an error~nwhen checking user ~p in server " + "~p~nError message: ~p", + [AuthModule, User, Server, Error]), + maybe end. +-spec remove_user(binary(), binary()) -> ok. %% @spec (User, Server) -> ok %% @doc Remove user. %% Note: it may return ok even if there was some problem removing the user. remove_user(User, Server) -> - lists:foreach( - fun(M) -> - M:remove_user(User, Server) - end, auth_modules(Server)), - ejabberd_hooks:run(remove_user, jlib:nameprep(Server), [User, Server]), + lists:foreach(fun (M) -> M:remove_user(User, Server) + end, + auth_modules(Server)), + ejabberd_hooks:run(remove_user, jlib:nameprep(Server), + [User, Server]), ok. %% @spec (User, Server, Password) -> ok | not_exists | not_allowed | bad_request | error @@ -322,41 +361,49 @@ remove_user(User, Server) -> %% The removal is attempted in each auth method provided: %% when one returns 'ok' the loop stops; %% if no method returns 'ok' then it returns the error message indicated by the last method attempted. +-spec remove_user(binary(), binary(), binary()) -> any(). + remove_user(User, Server, Password) -> - R = lists:foldl( - fun(_M, ok = Res) -> - Res; - (M, _) -> - M:remove_user(User, Server, Password) - end, error, auth_modules(Server)), + R = lists:foldl(fun (_M, ok = Res) -> Res; + (M, _) -> M:remove_user(User, Server, Password) + end, + error, auth_modules(Server)), case R of - ok -> ejabberd_hooks:run(remove_user, jlib:nameprep(Server), [User, Server]); - _ -> none + ok -> + ejabberd_hooks:run(remove_user, jlib:nameprep(Server), + [User, Server]); + _ -> none end, R. %% @spec (IOList) -> non_negative_float() %% @doc Calculate informational entropy. -entropy(IOList) -> - case binary_to_list(iolist_to_binary(IOList)) of - "" -> - 0.0; - S -> - Set = lists:foldl( - fun(C, [Digit, Printable, LowLetter, HiLetter, Other]) -> - if C >= $a, C =< $z -> - [Digit, Printable, 26, HiLetter, Other]; - C >= $0, C =< $9 -> - [9, Printable, LowLetter, HiLetter, Other]; - C >= $A, C =< $Z -> - [Digit, Printable, LowLetter, 26, Other]; - C >= 16#21, C =< 16#7e -> - [Digit, 33, LowLetter, HiLetter, Other]; - true -> - [Digit, Printable, LowLetter, HiLetter, 128] - end - end, [0, 0, 0, 0, 0], S), - length(S) * math:log(lists:sum(Set))/math:log(2) +entropy(B) -> + case binary_to_list(B) of + "" -> 0.0; + S -> + Set = lists:foldl(fun (C, + [Digit, Printable, LowLetter, HiLetter, + Other]) -> + if C >= $a, C =< $z -> + [Digit, Printable, 26, HiLetter, + Other]; + C >= $0, C =< $9 -> + [9, Printable, LowLetter, HiLetter, + Other]; + C >= $A, C =< $Z -> + [Digit, Printable, LowLetter, 26, + Other]; + C >= 33, C =< 126 -> + [Digit, 33, LowLetter, HiLetter, + Other]; + true -> + [Digit, Printable, LowLetter, + HiLetter, 128] + end + end, + [0, 0, 0, 0, 0], S), + length(S) * math:log(lists:sum(Set)) / math:log(2) end. %%%---------------------------------------------------------------------- @@ -365,19 +412,27 @@ entropy(IOList) -> %% Return the lists of all the auth modules actually used in the %% configuration auth_modules() -> - lists:usort( - lists:flatmap( - fun(Server) -> - auth_modules(Server) - end, ?MYHOSTS)). + lists:usort(lists:flatmap(fun (Server) -> + auth_modules(Server) + end, + ?MYHOSTS)). + +-spec auth_modules(binary()) -> [atom()]. %% Return the list of authenticated modules for a given host auth_modules(Server) -> LServer = jlib:nameprep(Server), - Method = ejabberd_config:get_local_option({auth_method, LServer}), - Methods = if - Method == undefined -> []; - is_list(Method) -> Method; - is_atom(Method) -> [Method] - end, - [list_to_atom("ejabberd_auth_" ++ atom_to_list(M)) || M <- Methods]. + Methods = ejabberd_config:get_local_option( + {auth_method, LServer}, + fun(V) when is_list(V) -> + true = lists:all(fun is_atom/1, V), + V; + (V) when is_atom(V) -> + [V] + end, []), + [jlib:binary_to_atom(<<"ejabberd_auth_", + (jlib:atom_to_binary(M))/binary>>) + || M <- Methods]. + +export(Server) -> + ejabberd_auth_internal:export(Server). |