summaryrefslogtreecommitdiff
path: root/src/ejabberd_auth.erl
diff options
context:
space:
mode:
authorBadlop <badlop@process-one.net>2013-03-14 10:33:02 +0100
committerBadlop <badlop@process-one.net>2013-03-14 10:33:02 +0100
commit9deb294328bb3f9eb6bd2c0e7cd500732e9b5830 (patch)
tree7e1066c130250627ee0abab44a135f583a28d07f /src/ejabberd_auth.erl
parentlist_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.erl523
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).