25
1
mirror of https://github.com/processone/ejabberd.git synced 2024-11-22 16:20:52 +01: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> 2009-01-30 Jean-Sébastien Pédron <js.pedron@meetic-corp.com>
* doc/api/Makefile: Disable "TODO:" interpretation in eDoc because * doc/api/Makefile: Disable "TODO:" interpretation in eDoc because

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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