24
1
mirror of https://github.com/processone/ejabberd.git synced 2024-06-08 21:43:07 +02:00

o Document the type of the argument(s) and the returned type of every

functions.
o  Add guardians expression to many functions of ejabberd_auth and
ejabberd_auth_anonymous to ensure at an early stage that we were given
the right arguments. Other modules are not changed because they are only
used by ejabberd_auth which already does the check.

PR:		EJABP-1

SVN Revision: 1863
This commit is contained in:
Jean-Sébastien Pédron 2009-02-05 11:13:01 +00:00
parent 4badd3b6ac
commit 8290026940
8 changed files with 672 additions and 92 deletions

View File

@ -1,3 +1,17 @@
2009-02-05 Jean-Sébastien Pédron <js.pedron@meetic-corp.com>
* src/ejabberd_auth.erl, src/ejabberd_auth_anonymous.erl,
src/ejabberd_auth_external.erl, src/ejabberd_auth_internal.erl,
src/ejabberd_auth_ldap.erl, src/ejabberd_auth_odbc.erl,
src/ejabberd_auth_pam.erl: Document the type of the argument(s) and
the returned type of every functions.
* src/ejabberd_auth.erl, src/ejabberd_auth_anonymous.erl: Add
guardians expression to many functions to ensure at an early stage
that we were given the right arguments. Other modules are not changed
because they are only used by ejabberd_auth which already does the
check.
2009-01-30 Jean-Sébastien Pédron <js.pedron@meetic-corp.com>
* doc/api/Makefile: Disable "TODO:" interpretation in eDoc because

View File

@ -56,9 +56,16 @@
-include("ejabberd.hrl").
%% @type authmodule() = ejabberd_auth_anonymous | ejabberd_auth_external |
%% ejabberd_auth_internal | ejabberd_auth_ldap |
%% ejabberd_auth_odbc | ejabberd_auth_pam | atom().
%%%----------------------------------------------------------------------
%%% API
%%%----------------------------------------------------------------------
%% @spec () -> term()
start() ->
lists:foreach(
fun(Host) ->
@ -68,42 +75,56 @@ start() ->
end, auth_modules(Host))
end, ?MYHOSTS).
plain_password_required(Server) ->
%% @spec (Server) -> bool()
%% Server = string()
plain_password_required(Server) when is_list(Server) ->
lists:any(
fun(M) ->
M:plain_password_required()
end, auth_modules(Server)).
%% @spec (User, Server, Password) -> bool()
%% User = string()
%% Server = string()
%% Password = string()
%% @doc Check if the user and password can login in server.
%% @spec (User::string(), Server::string(), Password::string()) ->
%% true | false
check_password(User, Server, Password) ->
check_password(User, Server, Password)
when is_list(User), is_list(Server), is_list(Password) ->
lists:any(
fun(M) ->
M:check_password(User, Server, Password)
end, auth_modules(Server)).
%% @spec (User, Server, Password, StreamID, Digest) -> bool()
%% User = string()
%% Server = string()
%% Password = string()
%% StreamID = string()
%% Digest = string()
%% @doc Check if the user and password can login in server.
%% @spec (User::string(), Server::string(), Password::string(),
%% StreamID::string(), Digest::string()) ->
%% true | false
check_password(User, Server, Password, StreamID, Digest) ->
check_password(User, Server, Password, StreamID, Digest)
when is_list(User), is_list(Server), is_list(Password),
is_list(StreamID), is_list(Digest) ->
lists:any(
fun(M) ->
M:check_password(User, Server, Password, StreamID, Digest)
end, auth_modules(Server)).
%% @spec (User, Server, Password) -> {true, AuthModule} | false
%% User = string()
%% Server = string()
%% Password = string()
%% AuthModule = authmodule()
%% @doc Check if the user and password can login in server.
%% The user can login if at least an authentication method accepts the user
%% and the password.
%% The first authentication method that accepts the credentials is returned.
%% @spec (User::string(), Server::string(), Password::string()) ->
%% {true, AuthModule} | false
%% where
%% 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_with_authmodule(User, Server, Password)
when is_list(User), is_list(Server), is_list(Password) ->
Res = lists:dropwhile(
fun(M) ->
not apply(M, check_password,
@ -114,7 +135,17 @@ check_password_with_authmodule(User, Server, Password) ->
[AuthMod | _] -> {true, AuthMod}
end.
check_password_with_authmodule(User, Server, Password, StreamID, Digest) ->
%% @spec (User, Server, Password, StreamID, Digest) -> {true, AuthModule} | false
%% User = string()
%% Server = string()
%% Password = string()
%% StreamID = string()
%% Digest = string()
%% AuthModule = authmodule()
check_password_with_authmodule(User, Server, Password, StreamID, Digest)
when is_list(User), is_list(Server), is_list(Password),
is_list(StreamID), is_list(Digest) ->
Res = lists:dropwhile(
fun(M) ->
not apply(M, check_password,
@ -125,13 +156,17 @@ check_password_with_authmodule(User, Server, Password, StreamID, Digest) ->
[AuthMod | _] -> {true, AuthMod}
end.
%% @spec (User::string(), Server::string(), Password::string()) ->
%% ok | {error, ErrorType}
%% where ErrorType = empty_password | not_allowed | invalid_jid
%% @spec (User, Server, Password) -> ok | {error, ErrorType}
%% User = string()
%% Server = string()
%% Password = string()
%% ErrorType = empty_password | not_allowed | invalid_jid
set_password(_User, _Server, "") ->
%% We do not allow empty password
{error, empty_password};
set_password(User, Server, Password) ->
set_password(User, Server, Password)
when is_list(User), is_list(Server), is_list(Password) ->
lists:foldl(
fun(M, {error, _}) ->
M:set_password(User, Server, Password);
@ -140,10 +175,15 @@ set_password(User, Server, Password) ->
end, {error, not_allowed}, auth_modules(Server)).
%% @spec (User, Server, Password) -> {atomic, ok} | {atomic, exists} | {error, not_allowed}
%% User = string()
%% Server = string()
%% Password = string() | nil()
try_register(_User, _Server, "") ->
%% We do not allow empty password
{error, not_allowed};
try_register(User, Server, Password) ->
try_register(User, Server, Password)
when is_list(User), is_list(Server), is_list(Password) ->
case is_user_exists(User,Server) of
true ->
{atomic, exists};
@ -168,27 +208,48 @@ try_register(User, Server, Password) ->
end
end.
%% Registered users list do not include anonymous users logged
%% @spec () -> [{LUser, LServer}]
%% LUser = string()
%% LServer = string()
%% @doc Registered users list do not include anonymous users logged.
dirty_get_registered_users() ->
lists:flatmap(
fun(M) ->
M:dirty_get_registered_users()
end, auth_modules()).
%% Registered users list do not include anonymous users logged
get_vh_registered_users(Server) ->
%% @spec (Server) -> [{LUser, LServer}]
%% Server = string()
%% LUser = string()
%% LServer = string()
%% @doc Registered users list do not include anonymous users logged.
get_vh_registered_users(Server) when is_list(Server) ->
lists:flatmap(
fun(M) ->
M:get_vh_registered_users(Server)
end, auth_modules(Server)).
get_vh_registered_users(Server, Opts) ->
%% @spec (Server, Opts) -> [{LUser, LServer}]
%% Server = string()
%% Opts = [{Opt, Val}]
%% Opt = atom()
%% Val = term()
%% LUser = string()
%% LServer = string()
get_vh_registered_users(Server, Opts) when is_list(Server) ->
lists:flatmap(
fun(M) ->
M:get_vh_registered_users(Server, Opts)
end, auth_modules(Server)).
get_vh_registered_users_number(Server) ->
%% @spec (Server) -> Users_Number
%% Server = string()
%% Users_Number = integer()
get_vh_registered_users_number(Server) when is_list(Server) ->
lists:sum(
lists:map(
fun(M) ->
@ -201,7 +262,14 @@ get_vh_registered_users_number(Server) ->
end
end, auth_modules(Server))).
get_vh_registered_users_number(Server, Opts) ->
%% @spec (Server, Opts) -> Users_Number
%% Server = string()
%% Opts = [{Opt, Val}]
%% Opt = atom()
%% Val = term()
%% Users_Number = integer()
get_vh_registered_users_number(Server, Opts) when is_list(Server) ->
lists:sum(
lists:map(
fun(M) ->
@ -214,9 +282,13 @@ get_vh_registered_users_number(Server, Opts) ->
end
end, auth_modules(Server))).
%% @spec (User, Server) -> Password | false
%% User = string()
%% Server = string()
%% Password = string()
%% @doc Get the password of the user.
%% @spec (User::string(), Server::string()) -> Password::string()
get_password(User, Server) ->
get_password(User, Server) when is_list(User), is_list(Server) ->
lists:foldl(
fun(M, false) ->
M:get_password(User, Server);
@ -224,7 +296,13 @@ get_password(User, Server) ->
Password
end, false, auth_modules(Server)).
get_password_s(User, Server) ->
%% @spec (User, Server) -> Password | nil()
%% User = string()
%% Server = string()
%% Password = string()
%% @doc Get the password of the user.
get_password_s(User, Server) when is_list(User), is_list(Server) ->
case get_password(User, Server) of
false ->
"";
@ -232,10 +310,15 @@ get_password_s(User, Server) ->
Password
end.
%% @spec (User, Server) -> {Password, AuthModule} | {false, none}
%% User = string()
%% Server = string()
%% Password = string()
%% AuthModule = authmodule()
%% @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) ->
get_password_with_authmodule(User, Server)
when is_list(User), is_list(Server) ->
lists:foldl(
fun(M, {false, _}) ->
{M:get_password(User, Server), M};
@ -243,26 +326,39 @@ get_password_with_authmodule(User, Server) ->
{Password, AuthModule}
end, {false, none}, auth_modules(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) ->
%% @spec (User, Server) -> bool()
%% User = string()
%% Server = string()
%% @doc 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) when is_list(User), is_list(Server) ->
lists:any(
fun(M) ->
M:is_user_exists(User, Server)
end, auth_modules(Server)).
%% Check if the user exists in all authentications module except the module
%% passed as parameter
is_user_exists_in_other_modules(Module, User, Server) ->
%% @spec (Module, User, Server) -> bool
%% Module = authmodule()
%% User = string()
%% Server = string()
%% @doc Check if the user exists in all authentications module except
%% the module passed as parameter.
is_user_exists_in_other_modules(Module, User, Server)
when is_list(User), is_list(Server) ->
lists:any(
fun(M) ->
M:is_user_exists(User, Server)
end, auth_modules(Server)--[Module]).
%% @spec (User, Server) -> ok | error | {error, not_allowed}
%% User = string()
%% Server = string()
%% @doc Remove user.
%% Note: it may return ok even if there was some problem removing the user.
remove_user(User, Server) ->
remove_user(User, Server) when is_list(User), is_list(Server) ->
R = lists:foreach(
fun(M) ->
M:remove_user(User, Server)
@ -274,11 +370,16 @@ remove_user(User, Server) ->
R.
%% @spec (User, Server, Password) -> ok | not_exists | not_allowed | bad_request | error
%% User = string()
%% Server = string()
%% Password = string()
%% @doc Try to remove user if the provided password is correct.
%% 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.
remove_user(User, Server, Password) ->
remove_user(User, Server, Password)
when is_list(User), is_list(Server), is_list(Password) ->
R = lists:foldl(
fun(_M, ok = Res) ->
Res;
@ -295,8 +396,11 @@ remove_user(User, Server, Password) ->
%%%----------------------------------------------------------------------
%%% Internal functions
%%%----------------------------------------------------------------------
%% Return the lists of all the auth modules actually used in the
%% configuration
%% @spec () -> [authmodule()]
%% @doc Return the lists of all the auth modules actually used in the
%% configuration.
auth_modules() ->
lists:usort(
lists:flatmap(
@ -304,8 +408,11 @@ auth_modules() ->
auth_modules(Server)
end, ?MYHOSTS)).
%% Return the list of authenticated modules for a given host
auth_modules(Server) ->
%% @spec (Server) -> [authmodule()]
%% Server = string()
%% @doc Return the list of authenticated modules for a given host.
auth_modules(Server) when is_list(Server) ->
LServer = exmpp_stringprep:nameprep(Server),
Method = ejabberd_config:get_local_option({auth_method, LServer}),
Methods = if

View File

@ -53,12 +53,18 @@
remove_user/3,
plain_password_required/0]).
-include_lib("exmpp/include/exmpp_xmpp.hrl").
-include("ejabberd.hrl").
-record(anonymous, {us, sid}).
%% Create the anonymous table if at least one virtual host has anonymous features enabled
%% Register to login / logout events
start(Host) ->
%% @spec (Host) -> ok
%% Host = string()
%% @doc Create the anonymous table if at least one virtual host has
%% anonymous features enabled.
%% Register to login / logout events.
start(Host) when is_list(Host) ->
%% TODO: Check cluster mode
mnesia:create_table(anonymous, [{ram_copies, [node()]},
{type, bag},
@ -70,13 +76,20 @@ start(Host) ->
?MODULE, unregister_connection, 100),
ok.
%% Return true if anonymous is allowed for host or false otherwise
allow_anonymous(Host) ->
%% @spec (Host) -> bool()
%% Host = string()
%% @doc Return true if anonymous is allowed for host or false otherwise.
allow_anonymous(Host) when is_list(Host) ->
lists:member(?MODULE, ejabberd_auth:auth_modules(Host)).
%% Return true if anonymous mode is enabled and if anonymous protocol is SASL
%% anonymous protocol can be: sasl_anon|login_anon|both
is_sasl_anonymous_enabled(Host) ->
%% @spec (Host) -> bool()
%% Host = string()
%% @doc Return true if anonymous mode is enabled and if anonymous
%% protocol is SASL anonymous.
%% protocol can be: sasl_anon|login_anon|both
is_sasl_anonymous_enabled(Host) when is_list(Host) ->
case allow_anonymous(Host) of
false -> false;
true ->
@ -87,10 +100,13 @@ is_sasl_anonymous_enabled(Host) ->
end
end.
%% Return true if anonymous login is enabled on the server
%% @spec (Host) -> bool()
%% Host = string()
%% @doc Return true if anonymous login is enabled on the server.
%% anonymous login can be use using standard authentication method (i.e. with
%% clients that do not support anonymous login)
is_login_anonymous_enabled(Host) ->
is_login_anonymous_enabled(Host) when is_list(Host) ->
case allow_anonymous(Host) of
false -> false;
true ->
@ -101,9 +117,12 @@ is_login_anonymous_enabled(Host) ->
end
end.
%% Return the anonymous protocol to use: sasl_anon|login_anon|both
%% @spec (Host) -> sasl_anon | login_anon | both
%% Host = string()
%% @doc Return the anonymous protocol to use: sasl_anon|login_anon|both.
%% defaults to login_anon
anonymous_protocol(Host) ->
anonymous_protocol(Host) when is_list(Host) ->
case ejabberd_config:get_local_option({anonymous_protocol, Host}) of
sasl_anon -> sasl_anon;
login_anon -> login_anon;
@ -111,16 +130,24 @@ anonymous_protocol(Host) ->
_Other -> sasl_anon
end.
%% Return true if multiple connections have been allowed in the config file
%% @spec (Host) -> bool()
%% Host = string()
%% @doc Return true if multiple connections have been allowed in the
%% config file.
%% defaults to false
allow_multiple_connections(Host) ->
allow_multiple_connections(Host) when is_list(Host) ->
case ejabberd_config:get_local_option({allow_multiple_connections, Host}) of
true -> true;
_Other -> false
end.
%% Check if user exist in the anonymus database
anonymous_user_exist(User, Server) ->
%% @spec (User, Server) -> bool()
%% User = string()
%% Server = string()
%% @doc Check if user exist in the anonymus database.
anonymous_user_exist(User, Server) when is_list(User), is_list(Server) ->
LUser = exmpp_stringprep:nodeprep(User),
LServer = exmpp_stringprep:nameprep(Server),
US = {LUser, LServer},
@ -131,16 +158,26 @@ anonymous_user_exist(User, Server) ->
true
end.
%% Remove connection from Mnesia tables
remove_connection(SID, LUser, LServer) ->
%% @spec (SID, LUser, LServer) -> term()
%% SID = term()
%% LUser = string()
%% LServer = string()
%% @doc Remove connection from Mnesia tables.
remove_connection(SID, LUser, LServer) when is_list(LUser), is_list(LServer) ->
US = {LUser, LServer},
F = fun() ->
mnesia:delete_object({anonymous, US, SID})
end,
mnesia:transaction(F).
%% Register connection
register_connection(SID, JID, Info) ->
%% @spec (SID, JID, Info) -> term()
%% SID = term()
%% JID = exmpp_jid:jid()
%% Info = [term()]
%% @doc Register connection.
register_connection(SID, JID, Info) when ?IS_JID(JID) ->
LUser = exmpp_jid:lnode(JID),
LServer = exmpp_jid:ldomain(JID),
case proplists:get_value(auth_module, Info) of
@ -155,26 +192,40 @@ register_connection(SID, JID, Info) ->
ok
end.
%% Remove an anonymous user from the anonymous users table
unregister_connection(SID, JID, _) ->
%% @spec (SID, JID, Ignored) -> term()
%% SID = term()
%% JID = exmpp_jid:jid()
%% Ignored = term()
%% @doc Remove an anonymous user from the anonymous users table.
unregister_connection(SID, JID, _) when ?IS_JID(JID) ->
LUser = exmpp_jid:lnode(JID),
LServer = exmpp_jid:ldomain(JID),
purge_hook(anonymous_user_exist(LUser, LServer),
LUser, LServer),
remove_connection(SID, LUser, LServer).
%% Launch the hook to purge user data only for anonymous users
%% @spec (bool(), LUser, LServer) -> term()
%% LUser = string()
%% LServer = string()
%% @doc Launch the hook to purge user data only for anonymous users.
purge_hook(false, _LUser, _LServer) ->
ok;
purge_hook(true, LUser, LServer) ->
purge_hook(true, LUser, LServer) when is_list(LUser), is_list(LServer) ->
ejabberd_hooks:run(anonymous_purge_hook, LServer, [LUser, LServer]).
%% ---------------------------------
%% Specific anonymous auth functions
%% ---------------------------------
%% When anonymous login is enabled, check the password for permenant users
%% before allowing access
%% @spec (User, Server, Password) -> bool()
%% User = string()
%% Server = string()
%% Password = string()
%% @doc When anonymous login is enabled, check the password for
%% permenant users before allowing access.
check_password(User, Server, Password) ->
check_password(User, Server, Password, undefined, undefined).
check_password(User, Server, _Password, _StreamID, _Digest) ->
@ -186,6 +237,10 @@ check_password(User, Server, _Password, _StreamID, _Digest) ->
false -> login(User, Server)
end.
%% @spec (User, Server) -> bool()
%% User = string()
%% Server = string()
login(User, Server) ->
case is_login_anonymous_enabled(Server) of
false -> false;
@ -200,8 +255,13 @@ login(User, Server) ->
end
end.
%% When anonymous login is enabled, check that the user is permanent before
%% changing its password
%% @spec (User, Server, Password) -> ok | {error, not_allowed}
%% User = string()
%% Server = string()
%% Password = string()
%% @doc When anonymous login is enabled, check that the user is
%% permanent before changing its password.
set_password(User, Server, _Password) ->
case anonymous_user_exist(User, Server) of
true ->
@ -210,22 +270,41 @@ set_password(User, Server, _Password) ->
{error, not_allowed}
end.
%% When anonymous login is enabled, check if permanent users are allowed on
%% the server:
%% @spec (User, Server, Password) -> {error, not_allowed}
%% User = string()
%% Server = string()
%% Password = string()
%% @doc When anonymous login is enabled, check if permanent users are
%% allowed on the server:
try_register(_User, _Server, _Password) ->
{error, not_allowed}.
%% @spec () -> nil()
dirty_get_registered_users() ->
[].
%% @spec (Server) -> nil()
%% Server = string()
get_vh_registered_users(_Server) ->
[].
%% @spec (User, Server) -> Password | false
%% User = string()
%% Server = string()
%% Password = nil()
%% @doc Return password of permanent user or false for anonymous users.
%% Return password of permanent user or false for anonymous users
get_password(User, Server) ->
get_password(User, Server, "").
%% @spec (User, Server, DefaultValue) -> DefaultValue | false
%% User = string()
%% Server = string()
%% DefaultValue = string()
get_password(User, Server, DefaultValue) ->
case anonymous_user_exist(User, Server) of
%% We return the default value if the user is anonymous
@ -236,17 +315,32 @@ get_password(User, Server, DefaultValue) ->
false
end.
%% Returns true if the user exists in the DB or if an anonymous user is logged
%% under the given name
%% @spec (User, Server) -> bool()
%% User = string()
%% Server = string()
%% @doc 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) ->
anonymous_user_exist(User, Server).
%% @spec (User, Server) -> {error, not_allowed}
%% User = string()
%% Server = string()
remove_user(_User, _Server) ->
{error, not_allowed}.
%% @spec (User, Server, Password) -> {error, not_allowed}
%% User = string()
%% Server = string()
%% Password = string()
remove_user(_User, _Server, _Password) ->
not_allowed.
%% @spec () -> bool()
plain_password_required() ->
false.

View File

@ -46,49 +46,103 @@
%%%----------------------------------------------------------------------
%%% API
%%%----------------------------------------------------------------------
%% @spec (Host) -> ok
%% Host = string()
start(Host) ->
extauth:start(
Host, ejabberd_config:get_local_option({extauth_program, Host})),
ok.
%% @spec () -> bool()
plain_password_required() ->
true.
%% @spec (User, Server, Password) -> bool()
%% User = string()
%% Server = string()
%% Password = string()
check_password(User, Server, Password) ->
extauth:check_password(User, Server, Password) andalso Password /= "".
%% @spec (User, Server, Password, StreamID, Digest) -> bool()
%% User = string()
%% Server = string()
%% Password = string()
%% StreamID = string()
%% Digest = string()
check_password(User, Server, Password, _StreamID, _Digest) ->
check_password(User, Server, Password).
%% @spec (User, Server, Password) -> ok | {error, unknown_problem}
%% User = string()
%% Server = string()
%% Password = string()
set_password(User, Server, Password) ->
case extauth:set_password(User, Server, Password) of
true -> ok;
_ -> {error, unknown_problem}
end.
%% @spec (User, Server, Password) -> {error, not_allowed}
%% User = string()
%% Server = string()
%% Password = string()
try_register(_User, _Server, _Password) ->
{error, not_allowed}.
%% TODO
%% Return the list of all users handled by external
%% @spec () -> nil()
%% @todo Write it.
%% @doc Return the list of all users handled by external.
dirty_get_registered_users() ->
[].
%% @spec (Server) -> nil()
%% Server = string()
get_vh_registered_users(_Server) ->
[].
%% @spec (User, Server) -> bool()
%% User = string()
%% Server = string()
get_password(_User, _Server) ->
false.
%% @spec (User, Server) -> nil()
%% User = string()
%% Server = string()
get_password_s(_User, _Server) ->
"".
%% @spec (User, Server) -> bool()
%% User = string()
%% Server = string()
is_user_exists(User, Server) ->
extauth:is_user_exists(User, Server).
%% @spec (User, Server) -> {error, not_allowed}
%% User = string()
%% Server = string()
remove_user(_User, _Server) ->
{error, not_allowed}.
%% @spec (User, Server, Password) -> not_allowed
%% User = string()
%% Server = string()
%% Password = string()
remove_user(_User, _Server, _Password) ->
not_allowed.

View File

@ -53,15 +53,26 @@
%%%----------------------------------------------------------------------
%%% API
%%%----------------------------------------------------------------------
%% @spec (Host) -> ok
%% Host = string()
start(_Host) ->
mnesia:create_table(passwd, [{disc_copies, [node()]},
{attributes, record_info(fields, passwd)}]),
update_table(),
ok.
%% @spec () -> bool()
plain_password_required() ->
false.
%% @spec (User, Server, Password) -> bool()
%% User = string()
%% Server = string()
%% Password = string()
check_password(User, Server, Password) ->
LUser = exmpp_stringprep:nodeprep(User),
LServer = exmpp_stringprep:nameprep(Server),
@ -73,6 +84,13 @@ check_password(User, Server, Password) ->
false
end.
%% @spec (User, Server, Password, StreamID, Digest) -> bool()
%% User = string()
%% Server = string()
%% Password = string()
%% StreamID = string()
%% Digest = string()
check_password(User, Server, Password, StreamID, Digest) ->
LUser = exmpp_stringprep:nodeprep(User),
LServer = exmpp_stringprep:nameprep(Server),
@ -94,8 +112,11 @@ check_password(User, Server, Password, StreamID, Digest) ->
false
end.
%% @spec (User::string(), Server::string(), Password::string()) ->
%% ok | {error, invalid_jid}
%% @spec (User, Server, Password) -> ok | {error, invalid_jid}
%% User = string()
%% Server = string()
%% Password = string()
set_password(User, Server, Password) ->
LUser = exmpp_stringprep:nodeprep(User),
LServer = exmpp_stringprep:nameprep(Server),
@ -113,6 +134,10 @@ set_password(User, Server, Password) ->
end.
%% @spec (User, Server, Password) -> {atomic, ok} | {atomic, exists} | {error, invalid_jid} | {aborted, Reason}
%% User = string()
%% Server = string()
%% Password = string()
try_register(User, Server, Password) ->
LUser = exmpp_stringprep:nodeprep(User),
LServer = exmpp_stringprep:nameprep(Server),
@ -134,10 +159,19 @@ try_register(User, Server, Password) ->
mnesia:transaction(F)
end.
%% Get all registered users in Mnesia
%% @spec () -> [{LUser, LServer}]
%% LUser = string()
%% LServer = string()
%% @doc Get all registered users in Mnesia.
dirty_get_registered_users() ->
mnesia:dirty_all_keys(passwd).
%% @spec (Server) -> [{LUser, LServer}]
%% Server = string()
%% LUser = string()
%% LServer = string()
get_vh_registered_users(Server) ->
LServer = exmpp_stringprep:nameprep(Server),
mnesia:dirty_select(
@ -146,6 +180,24 @@ get_vh_registered_users(Server) ->
[{'==', {element, 2, '$1'}, LServer}],
['$1']}]).
%% @spec (Server, Opts) -> [{LUser, LServer}]
%% Server = string()
%% Opts = [{Opt, Val}]
%% Opt = atom()
%% Val = term()
%% LUser = string()
%% LServer = string()
%% @doc Return the registered users for the specified host.
%%
%% `Opts' can be one of the following:
%% <ul>
%% <li>`[{from, integer()}, {to, integer()}]'</li>
%% <li>`[{limit, integer()}, {offset, integer()}]'</li>
%% <li>`[{prefix, string()}]'</li>
%% <li>`[{prefix, string()}, {from, integer()}, {to, integer()}]'</li>
%% <li>`[{prefix, string()}, {limit, integer()}, {offset, integer()}]'</li>
%% </ul>
get_vh_registered_users(Server, [{from, Start}, {to, End}])
when is_integer(Start) and is_integer(End) ->
get_vh_registered_users(Server, [{limit, End-Start+1}, {offset, Start}]);
@ -192,10 +244,19 @@ get_vh_registered_users(Server, [{prefix, Prefix}, {limit, Limit}, {offset, Offs
get_vh_registered_users(Server, _) ->
get_vh_registered_users(Server).
%% @spec (Server) -> Users_Number
%% Server = string()
%% Users_Number = integer()
get_vh_registered_users_number(Server) ->
Set = get_vh_registered_users(Server),
length(Set).
%% @spec (Server, [{prefix, Prefix}]) -> Users_Number
%% Server = string()
%% Prefix = string()
%% Users_Number = integer()
get_vh_registered_users_number(Server, [{prefix, Prefix}]) when is_list(Prefix) ->
Set = [{U, S} || {U, S} <- get_vh_registered_users(Server), lists:prefix(Prefix, U)],
length(Set);
@ -203,6 +264,11 @@ get_vh_registered_users_number(Server, [{prefix, Prefix}]) when is_list(Prefix)
get_vh_registered_users_number(Server, _) ->
get_vh_registered_users_number(Server).
%% @spec (User, Server) -> Password | false
%% User = string()
%% Server = string()
%% Password = string()
get_password(User, Server) ->
try
LUser = exmpp_stringprep:nodeprep(User),
@ -219,6 +285,11 @@ get_password(User, Server) ->
false
end.
%% @spec (User, Server) -> Password | nil()
%% User = string()
%% Server = string()
%% Password = string()
get_password_s(User, Server) ->
try
LUser = exmpp_stringprep:nodeprep(User),
@ -235,6 +306,10 @@ get_password_s(User, Server) ->
[]
end.
%% @spec (User, Server) -> bool()
%% User = string()
%% Server = string()
is_user_exists(User, Server) ->
try
LUser = exmpp_stringprep:nodeprep(User),
@ -254,8 +329,11 @@ is_user_exists(User, Server) ->
end.
%% @spec (User, Server) -> ok
%% User = string()
%% Server = string()
%% @doc Remove user.
%% Note: it returns ok even if there was some problem removing the user.
remove_user(User, Server) ->
try
LUser = exmpp_stringprep:nodeprep(User),
@ -272,7 +350,11 @@ remove_user(User, Server) ->
end.
%% @spec (User, Server, Password) -> ok | not_exists | not_allowed | bad_request
%% User = string()
%% Server = string()
%% Password = string()
%% @doc Remove user if the provided password is correct.
remove_user(User, Server, Password) ->
try
LUser = exmpp_stringprep:nodeprep(User),
@ -302,11 +384,15 @@ remove_user(User, Server, Password) ->
bad_request
end.
%% @spec () -> term()
update_table() ->
Fields = record_info(fields, passwd),
case mnesia:table_info(passwd, attributes) of
Fields ->
% No conversion is needed when the table comes from an exmpp-less
% Ejabberd because ejabberd_auth* modules use string() and not
% binary().
ok;
[user, password] ->
?INFO_MSG("Converting passwd table from "

View File

@ -94,6 +94,9 @@ handle_info(_Info, State) ->
%%% API
%%%----------------------------------------------------------------------
%% @spec (Host) -> term()
%% Host = string()
start(Host) ->
Proc = gen_mod:get_module_proc(Host, ?MODULE),
ChildSpec = {
@ -102,19 +105,31 @@ start(Host) ->
},
supervisor:start_child(ejabberd_sup, ChildSpec).
%% @spec (Host) -> term()
%% Host = string()
stop(Host) ->
Proc = gen_mod:get_module_proc(Host, ?MODULE),
gen_server:call(Proc, stop),
supervisor:terminate_child(ejabberd_sup, Proc),
supervisor:delete_child(ejabberd_sup, Proc).
%% @spec (Host) -> term()
%% Host = string()
start_link(Host) ->
Proc = gen_mod:get_module_proc(Host, ?MODULE),
gen_server:start_link({local, Proc}, ?MODULE, Host, []).
%% @hidden
terminate(_Reason, _State) ->
ok.
%% @spec (Host) -> {ok, State}
%% Host = string()
%% State = term()
init(Host) ->
State = parse_options(Host),
eldap_pool:start_link(State#state.eldap_id,
@ -131,9 +146,16 @@ init(Host) ->
State#state.password),
{ok, State}.
%% @spec () -> true
plain_password_required() ->
true.
%% @spec (User, Server, Password) -> bool()
%% User = string()
%% Server = string()
%% Password = string()
check_password(User, Server, Password) ->
%% In LDAP spec: empty password means anonymous authentication.
%% As ejabberd is providing other anonymous authentication mechanisms
@ -147,16 +169,36 @@ check_password(User, Server, Password) ->
end
end.
%% @spec (User, Server, Password, StreamID, Digest) -> bool()
%% User = string()
%% Server = string()
%% Password = string()
%% StreamID = string()
%% Digest = string()
check_password(User, Server, Password, _StreamID, _Digest) ->
check_password(User, Server, Password).
%% @spec (User, Server, Password) -> {error, not_allowed}
%% User = string()
%% Server = string()
%% Password = string()
set_password(_User, _Server, _Password) ->
{error, not_allowed}.
%% @spec (User, Server, Password) -> {error, not_allowed}
%% User = string()
%% Server = string()
%% Password = string()
try_register(_User, _Server, _Password) ->
{error, not_allowed}.
%% @spec () -> [{LUser, LServer}]
%% LUser = string()
%% LServer = string()
dirty_get_registered_users() ->
Servers = ejabberd_config:get_vh_by_auth_method(ldap),
lists:flatmap(
@ -164,21 +206,42 @@ dirty_get_registered_users() ->
get_vh_registered_users(Server)
end, Servers).
%% @spec (Server) -> [{LUser, LServer}]
%% Server = string()
%% LUser = string()
%% LServer = string()
get_vh_registered_users(Server) ->
case catch get_vh_registered_users_ldap(Server) of
{'EXIT', _} -> [];
Result -> Result
end.
%% @spec (Server) -> Users_Number
%% Server = string()
%% Users_Number = integer()
get_vh_registered_users_number(Server) ->
length(get_vh_registered_users(Server)).
%% @spec (User, Server) -> bool()
%% User = string()
%% Server = string()
get_password(_User, _Server) ->
false.
%% @spec (User, Server) -> nil()
%% User = string()
%% Server = string()
get_password_s(_User, _Server) ->
"".
%% @spec (User, Server) -> bool()
%% User = string()
%% Server = string()
is_user_exists(User, Server) ->
case catch is_user_exists_ldap(User, Server) of
{'EXIT', _} ->
@ -187,15 +250,30 @@ is_user_exists(User, Server) ->
Result
end.
%% @spec (User, Server) -> {error, not_allowed}
%% User = string()
%% Server = string()
remove_user(_User, _Server) ->
{error, not_allowed}.
%% @spec (User, Server, Password) -> not_allowed
%% User = string()
%% Server = string()
%% Password = string()
remove_user(_User, _Server, _Password) ->
not_allowed.
%%%----------------------------------------------------------------------
%%% Internal functions
%%%----------------------------------------------------------------------
%% @spec (User, Server, Password) -> bool()
%% User = string()
%% Server = string()
%% Password = string()
check_password_ldap(User, Server, Password) ->
{ok, State} = eldap_utils:get_state(Server, ?MODULE),
case find_user_dn(User, State) of
@ -208,6 +286,11 @@ check_password_ldap(User, Server, Password) ->
end
end.
%% @spec (Server) -> [{LUser, LServer}]
%% Server = string()
%% LUser = string()
%% LServer = string()
get_vh_registered_users_ldap(Server) ->
{ok, State} = eldap_utils:get_state(Server, ?MODULE),
UIDs = State#state.uids,
@ -250,6 +333,10 @@ get_vh_registered_users_ldap(Server) ->
[]
end.
%% @spec (User, Server) -> bool()
%% User = string()
%% Server = string()
is_user_exists_ldap(User, Server) ->
{ok, State} = eldap_utils:get_state(Server, ?MODULE),
case find_user_dn(User, State) of

View File

@ -51,12 +51,23 @@
%%%----------------------------------------------------------------------
%%% API
%%%----------------------------------------------------------------------
%% @spec (Host) -> ok
%% Host = string()
start(_Host) ->
ok.
%% @spec () -> bool()
plain_password_required() ->
false.
%% @spec (User, Server, Password) -> bool()
%% User = string()
%% Server = string()
%% Password = string()
check_password(User, Server, Password) ->
try
LUser = exmpp_stringprep:nodeprep(User),
@ -73,6 +84,13 @@ check_password(User, Server, Password) ->
false
end.
%% @spec (User, Server, Password, StreamID, Digest) -> bool()
%% User = string()
%% Server = string()
%% Password = string()
%% StreamID = string()
%% Digest = string()
check_password(User, Server, Password, StreamID, Digest) ->
try
LUser = exmpp_stringprep:nodeprep(User),
@ -99,8 +117,11 @@ check_password(User, Server, Password, StreamID, Digest) ->
false
end.
%% @spec (User::string(), Server::string(), Password::string()) ->
%% ok | {error, invalid_jid}
%% @spec (User, Server, Password) -> ok | {error, invalid_jid}
%% User = string()
%% Server = string()
%% Password = string()
set_password(User, Server, Password) ->
try
LUser = exmpp_stringprep:nodeprep(User),
@ -118,6 +139,10 @@ set_password(User, Server, Password) ->
%% @spec (User, Server, Password) -> {atomic, ok} | {atomic, exists} | {error, invalid_jid}
%% User = string()
%% Server = string()
%% Password = string()
try_register(User, Server, Password) ->
try
LUser = exmpp_stringprep:nodeprep(User),
@ -135,6 +160,10 @@ try_register(User, Server, Password) ->
{error, invalid_jid}
end.
%% @spec () -> [{LUser, LServer}]
%% LUser = string()
%% LServer = string()
dirty_get_registered_users() ->
Servers = ejabberd_config:get_vh_by_auth_method(odbc),
lists:flatmap(
@ -142,6 +171,11 @@ dirty_get_registered_users() ->
get_vh_registered_users(Server)
end, Servers).
%% @spec (Server) -> [{LUser, LServer}]
%% Server = string()
%% LUser = string()
%% LServer = string()
get_vh_registered_users(Server) ->
LServer = exmpp_stringprep:nameprep(Server),
case catch odbc_queries:list_users(LServer) of
@ -151,6 +185,14 @@ get_vh_registered_users(Server) ->
[]
end.
%% @spec (Server, Opts) -> [{LUser, LServer}]
%% Server = string()
%% Opts = [{Opt, Val}]
%% Opt = atom()
%% Val = term()
%% LUser = string()
%% LServer = string()
get_vh_registered_users(Server, Opts) ->
LServer = exmpp_stringprep:nameprep(Server),
case catch odbc_queries:list_users(LServer, Opts) of
@ -160,6 +202,10 @@ get_vh_registered_users(Server, Opts) ->
[]
end.
%% @spec (Server) -> Users_Number
%% Server = string()
%% Users_Number = integer()
get_vh_registered_users_number(Server) ->
LServer = exmpp_stringprep:nameprep(Server),
case catch odbc_queries:users_number(LServer) of
@ -169,6 +215,13 @@ get_vh_registered_users_number(Server) ->
0
end.
%% @spec (Server, Opts) -> Users_Number
%% Server = string()
%% Opts = [{Opt, Val}]
%% Opt = atom()
%% Val = term()
%% Users_Number = integer()
get_vh_registered_users_number(Server, Opts) ->
LServer = exmpp_stringprep:nameprep(Server),
case catch odbc_queries:users_number(LServer, Opts) of
@ -178,6 +231,11 @@ get_vh_registered_users_number(Server, Opts) ->
0
end.
%% @spec (User, Server) -> Password | false
%% User = string()
%% Server = string()
%% Password = string()
get_password(User, Server) ->
try
LUser = exmpp_stringprep:nodeprep(User),
@ -194,6 +252,11 @@ get_password(User, Server) ->
false
end.
%% @spec (User, Server) -> Password | nil()
%% User = string()
%% Server = string()
%% Password = string()
get_password_s(User, Server) ->
try
LUser = exmpp_stringprep:nodeprep(User),
@ -210,6 +273,10 @@ get_password_s(User, Server) ->
""
end.
%% @spec (User, Server) -> bool()
%% User = string()
%% Server = string()
is_user_exists(User, Server) ->
try
LUser = exmpp_stringprep:nodeprep(User),
@ -227,8 +294,11 @@ is_user_exists(User, Server) ->
end.
%% @spec (User, Server) -> ok | error
%% User = string()
%% Server = string()
%% @doc Remove user.
%% Note: it may return ok even if there was some problem removing the user.
remove_user(User, Server) ->
try
LUser = exmpp_stringprep:nodeprep(User),
@ -242,7 +312,11 @@ remove_user(User, Server) ->
end.
%% @spec (User, Server, Password) -> ok | error | not_exists | not_allowed
%% User = string()
%% Server = string()
%% Password = string()
%% @doc Remove user if the provided password is correct.
remove_user(User, Server, Password) ->
try
LUser = exmpp_stringprep:nodeprep(User),

View File

@ -45,6 +45,10 @@
%%====================================================================
%% API
%%====================================================================
%% @spec (Host) -> ok | term()
%% Host = string()
start(_Host) ->
case epam:start() of
{ok, _} -> ok;
@ -52,55 +56,115 @@ start(_Host) ->
Err -> Err
end.
%% @spec (User, Server, Password) -> {error, not_allowed}
%% User = string()
%% Server = string()
%% Password = string()
set_password(_User, _Server, _Password) ->
{error, not_allowed}.
%% @spec (User, Server, Password, StreamID, Digest) -> bool()
%% User = string()
%% Server = string()
%% Password = string()
%% StreamID = string()
%% Digest = string()
check_password(User, Server, Password, _StreamID, _Digest) ->
check_password(User, Server, Password).
check_password(User, Host, Password) ->
Service = get_pam_service(Host),
%% @spec (User, Server, Password) -> bool()
%% User = string()
%% Server = string()
%% Password = string()
check_password(User, Server, Password) ->
Service = get_pam_service(Server),
case catch epam:authenticate(Service, User, Password) of
true -> true;
_ -> false
end.
%% @spec (User, Server, Password) -> {error, not_allowed}
%% User = string()
%% Server = string()
%% Password = string()
try_register(_User, _Server, _Password) ->
{error, not_allowed}.
%% @spec () -> [{LUser, LServer}]
%% LUser = string()
%% LServer = string()
dirty_get_registered_users() ->
[].
get_vh_registered_users(_Host) ->
%% @spec (Server) -> [{LUser, LServer}]
%% Server = string()
%% LUser = string()
%% LServer = string()
get_vh_registered_users(_Server) ->
[].
%% @spec (User, Server) -> Password | false
%% User = string()
%% Server = string()
%% Password = string()
get_password(_User, _Server) ->
false.
%% @spec (User, Server) -> Password | nil()
%% User = string()
%% Server = string()
%% Password = string()
get_password_s(_User, _Server) ->
"".
is_user_exists(User, Host) ->
Service = get_pam_service(Host),
%% @spec (User, Server) -> bool()
%% User = string()
%% Server = string()
is_user_exists(User, Server) ->
Service = get_pam_service(Server),
case catch epam:acct_mgmt(Service, User) of
true -> true;
_ -> false
end.
%% @spec (User, Server) -> {error, not_allowed}
%% User = string()
%% Server = string()
remove_user(_User, _Server) ->
{error, not_allowed}.
%% @spec (User, Server, Password) -> not_allowed
%% User = string()
%% Server = string()
%% Password = string()
remove_user(_User, _Server, _Password) ->
not_allowed.
%% @spec () -> bool()
plain_password_required() ->
true.
%%====================================================================
%% Internal functions
%%====================================================================
get_pam_service(Host) ->
case ejabberd_config:get_local_option({pam_service, Host}) of
%% @spec (Server) -> string()
%% Server = string()
get_pam_service(Server) ->
case ejabberd_config:get_local_option({pam_service, Server}) of
undefined -> "ejabberd";
Service -> Service
end.