* src/ejabberd_sm.erl: Added unset_presence_hook

* src/mod_last.erl: Use unset_presence_hook instead of direct call

* src/ejabberd_auth.erl: Splitted into ejabberd_auth_internal.erl,
ejabberd_auth_ldap.erl, and ejabberd_auth_external.erl,
* src/ejabberd_auth_internal.erl: Likewise
* src/ejabberd_auth_ldap.erl: Likewise
* src/ejabberd_auth_external.erl: Likewise

SVN Revision: 290
This commit is contained in:
Alexey Shchepin 2004-12-12 21:00:34 +00:00
parent da58d568b1
commit 591bc42669
7 changed files with 390 additions and 367 deletions

View File

@ -1,3 +1,14 @@
2004-12-12 Alexey Shchepin <alexey@sevcom.net>
* src/ejabberd_sm.erl: Added unset_presence_hook
* src/mod_last.erl: Use unset_presence_hook instead of direct call
* src/ejabberd_auth.erl: Splitted into ejabberd_auth_internal.erl,
ejabberd_auth_ldap.erl, and ejabberd_auth_external.erl,
* src/ejabberd_auth_internal.erl: Likewise
* src/ejabberd_auth_ldap.erl: Likewise
* src/ejabberd_auth_external.erl: Likewise
2004-12-05 Alexey Shchepin <alexey@sevcom.net>
* src/web/ejabberd_web_admin.erl: Changed type of password field

View File

@ -1,7 +1,7 @@
%%%----------------------------------------------------------------------
%%% File : ejabberd_auth.erl
%%% Author : Alexey Shchepin <alexey@sevcom.net>
%%% Purpose :
%%% Purpose : Authentification
%%% Created : 23 Nov 2002 by Alexey Shchepin <alexey@sevcom.net>
%%% Id : $Id$
%%%----------------------------------------------------------------------
@ -10,10 +10,8 @@
-author('alexey@sevcom.net').
-vsn('$Revision$ ').
-behaviour(gen_server).
%% External exports
-export([start/0, start_link/0,
-export([start/0,
set_password/2,
check_password/2,
check_password/4,
@ -24,387 +22,59 @@
is_user_exists/1,
remove_user/1,
remove_user/2,
plain_password_required/0,
check_password_ldap/2, % TODO: remove
is_user_exists_ldap/1 % TODO: remove
plain_password_required/0
]).
%% gen_server callbacks
-export([init/1,
handle_call/3,
handle_cast/2,
code_change/3,
handle_info/2,
terminate/2]).
-include("eldap/eldap.hrl").
-record(state, {}).
-record(passwd, {user, password}).
%%%----------------------------------------------------------------------
%%% API
%%%----------------------------------------------------------------------
start() ->
case auth_method() of
external ->
extauth:start(ejabberd_config:get_local_option(extauth_program));
_ ->
ok
end,
gen_server:start({local, ejabberd_auth}, ejabberd_auth, [], []).
(auth_module()):start().
start_link() ->
gen_server:start_link({local, ejabberd_auth}, ejabberd_auth, [], []).
plain_password_required() ->
(auth_module()):plain_password_required().
%%%----------------------------------------------------------------------
%%% Callback functions from gen_server
%%%----------------------------------------------------------------------
check_password(User, Password) ->
(auth_module()):check_password(User, Password).
%%----------------------------------------------------------------------
%% Func: init/1
%% Returns: {ok, State} |
%% {ok, State, Timeout} |
%% ignore |
%% {stop, Reason}
%%----------------------------------------------------------------------
init([]) ->
mnesia:create_table(passwd,[{disc_copies, [node()]},
{attributes, record_info(fields, passwd)}]),
case auth_method() of
internal ->
ok;
external ->
ok;
ldap ->
LDAPServers = ejabberd_config:get_local_option(ldap_servers),
RootDN = ejabberd_config:get_local_option(ldap_rootdn),
Password = ejabberd_config:get_local_option(ldap_password),
eldap:start_link("ejabberd", LDAPServers, 389, RootDN, Password),
eldap:start_link("ejabberd_bind", LDAPServers, 389, RootDN, Password)
end,
{ok, #state{}}.
check_password(User, Password, StreamID, Digest) ->
(auth_module()):check_password(User, Password, StreamID, Digest).
%%----------------------------------------------------------------------
%% Func: handle_call/3
%% Returns: {reply, Reply, State} |
%% {reply, Reply, State, Timeout} |
%% {noreply, State} |
%% {noreply, State, Timeout} |
%% {stop, Reason, Reply, State} | (terminate/2 is called)
%% {stop, Reason, State} (terminate/2 is called)
%%----------------------------------------------------------------------
handle_call(_Request, _From, State) ->
Reply = ok,
{reply, Reply, State}.
set_password(User, Password) ->
(auth_module()):set_password(User, Password).
%%----------------------------------------------------------------------
%% Func: handle_cast/2
%% Returns: {noreply, State} |
%% {noreply, State, Timeout} |
%% {stop, Reason, State} (terminate/2 is called)
%%----------------------------------------------------------------------
handle_cast(_Msg, State) ->
{noreply, State}.
try_register(User, Password) ->
(auth_module()):try_register(User, Password).
dirty_get_registered_users() ->
(auth_module()):dirty_get_registered_users().
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
get_password(User) ->
(auth_module()):get_password(User).
%%----------------------------------------------------------------------
%% Func: handle_info/2
%% Returns: {noreply, State} |
%% {noreply, State, Timeout} |
%% {stop, Reason, State} (terminate/2 is called)
%%----------------------------------------------------------------------
handle_info(_Info, State) ->
{noreply, State}.
get_password_s(User) ->
(auth_module()):get_password_s(User).
%%----------------------------------------------------------------------
%% Func: terminate/2
%% Purpose: Shutdown the server
%% Returns: any (ignored by gen_server)
%%----------------------------------------------------------------------
terminate(_Reason, _State) ->
ok.
is_user_exists(User) ->
(auth_module()):is_user_exists(User).
remove_user(User) ->
(auth_module()):remove_user(User).
remove_user(User, Password) ->
(auth_module()):remove_user(User, Password).
%%%----------------------------------------------------------------------
%%% Internal functions
%%%----------------------------------------------------------------------
auth_method() ->
auth_module() ->
case ejabberd_config:get_local_option(auth_method) of
external ->
external;
ejabberd_auth_external;
ldap ->
ldap;
ejabberd_auth_ldap;
_ ->
internal
ejabberd_auth_internal
end.
user_method() ->
case ejabberd_config:get_local_option(user_method) of
ldap ->
ldap;
_ ->
internal
end.
plain_password_required() ->
case auth_method() of
internal ->
false;
external ->
true;
ldap ->
true
end.
check_password(User, Password) ->
case auth_method() of
internal ->
check_password_internal(User, Password);
external ->
check_password_external(User, Password);
ldap ->
check_password_ldap(User, Password)
end.
check_password_external(User, Password) ->
extauth:check_password(User, Password).
set_password_external(User, Password) ->
extauth:set_password(User, Password).
is_user_exists_external(User) ->
extauth:is_user_exists(User).
check_password_internal(User, Password) ->
LUser = jlib:nodeprep(User),
case catch mnesia:dirty_read({passwd, LUser}) of
[#passwd{password = Password}] ->
true;
_ ->
false
end.
check_password(User, Password, StreamID, Digest) ->
case auth_method() of
internal ->
check_password_internal(User, Password, StreamID, Digest);
external ->
check_password_external(User, Password, StreamID, Digest);
ldap ->
check_password_ldap(User, Password, StreamID, Digest)
end.
check_password_internal(User, Password, StreamID, Digest) ->
LUser = jlib:nodeprep(User),
case catch mnesia:dirty_read({passwd, LUser}) of
[#passwd{password = Passwd}] ->
DigRes = if
Digest /= "" ->
Digest == sha:sha(StreamID ++ Passwd);
true ->
false
end,
if DigRes ->
true;
true ->
(Passwd == Password) and (Password /= "")
end;
_ ->
false
end.
set_password(User, Password) ->
case auth_method() of
internal ->
set_password_internal(User,Password);
external ->
set_password_external(User,Password);
ldap -> {error, not_allowed}
end.
set_password_internal(User, Password) ->
case jlib:nodeprep(User) of
error -> {error, invalid_jid};
LUser ->
F = fun() ->
mnesia:write(#passwd{user = LUser,
password = Password})
end,
mnesia:transaction(F)
end.
try_register(User, Password) ->
case auth_method() of
internal ->
try_register_internal(User, Password);
external ->
{error, not_allowed};
ldap ->
{error, not_allowed}
end.
try_register_internal(User, Password) ->
case jlib:nodeprep(User) of
error -> {error, invalid_jid};
LUser ->
F = fun() ->
case mnesia:read({passwd, LUser}) of
[] ->
mnesia:write(#passwd{user = LUser,
password = Password}),
ok;
[_E] ->
exists
end
end,
mnesia:transaction(F)
end.
dirty_get_registered_users() ->
mnesia:dirty_all_keys(passwd).
get_password(User) ->
LUser = jlib:nodeprep(User),
case catch mnesia:dirty_read(passwd, LUser) of
[#passwd{password = Password}] ->
Password;
_ ->
false
end.
get_password_s(User) ->
LUser = jlib:nodeprep(User),
case catch mnesia:dirty_read(passwd, LUser) of
[#passwd{password = Password}] ->
Password;
_ ->
[]
end.
is_user_exists(User) ->
case auth_method() of
internal ->
is_user_exists_internal(User);
external ->
is_user_exists_external(User);
ldap ->
is_user_exists_ldap(User)
end.
is_user_exists_internal(User) ->
LUser = jlib:nodeprep(User),
case catch mnesia:dirty_read({passwd, LUser}) of
[] ->
false;
[_] ->
true;
_ ->
false
end.
remove_user(User) ->
case user_method() of
internal ->
remove_user_internal(User);
ldap ->
{error, not_allowed}
end.
remove_user_internal(User) ->
LUser = jlib:nodeprep(User),
F = fun() ->
mnesia:delete({passwd, LUser})
end,
mnesia:transaction(F),
catch mod_roster:remove_user(User),
catch mod_offline:remove_user(User),
catch mod_last:remove_user(User),
catch mod_vcard:remove_user(User),
catch mod_private:remove_user(User).
remove_user(User, Password) ->
case user_method() of
internal ->
remove_user_internal(User, Password);
ldap ->
not_allowed
end.
remove_user_internal(User, Password) ->
LUser = jlib:nodeprep(User),
F = fun() ->
case mnesia:read({passwd, LUser}) of
[#passwd{password = Password}] ->
mnesia:delete({passwd, LUser}),
ok;
[_] ->
not_allowed;
_ ->
not_exists
end
end,
case mnesia:transaction(F) of
{atomic, ok} ->
catch mod_roster:remove_user(User),
catch mod_offline:remove_user(User),
catch mod_last:remove_user(User),
catch mod_vcard:remove_user(User),
catch mod_private:remove_user(User),
ok;
{atomic, Res} ->
Res;
_ ->
bad_request
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
check_password_ldap(User, Password, StreamID, Digest) ->
check_password_ldap(User, Password).
check_password_external(User, Password, StreamID, Digest) ->
check_password_external(User, Password).
check_password_ldap(User, Password) ->
case find_user_dn(User) of
false ->
false;
DN ->
case eldap:bind("ejabberd_bind", DN, Password) of
ok ->
true;
_ ->
false
end
end.
is_user_exists_ldap(User) ->
case find_user_dn(User) of
false ->
false;
_DN ->
true
end.
find_user_dn(User) ->
Attr = ejabberd_config:get_local_option(ldap_uidattr),
Filter = eldap:equalityMatch(Attr, User),
Base = ejabberd_config:get_local_option(ldap_base),
case eldap:search("ejabberd", [{base, Base},
{filter, Filter},
{attributes, []}]) of
#eldap_search_result{entries = [E | _]} ->
E#eldap_entry.object_name;
_ ->
false
end.

View File

@ -0,0 +1,67 @@
%%%----------------------------------------------------------------------
%%% File : ejabberd_auth_external.erl
%%% Author : Alexey Shchepin <alexey@sevcom.net>
%%% Purpose : Authentification via LDAP external script
%%% Created : 12 Dec 2004 by Alexey Shchepin <alexey@sevcom.net>
%%% Id : $Id$
%%%----------------------------------------------------------------------
-module(ejabberd_auth_external).
-author('alexey@sevcom.net').
-vsn('$Revision$ ').
%% External exports
-export([start/0,
set_password/2,
check_password/2,
check_password/4,
try_register/2,
dirty_get_registered_users/0,
get_password/1,
get_password_s/1,
is_user_exists/1,
remove_user/1,
remove_user/2,
plain_password_required/0
]).
%%%----------------------------------------------------------------------
%%% API
%%%----------------------------------------------------------------------
start() ->
extauth:start(ejabberd_config:get_local_option(extauth_program)),
ok.
plain_password_required() ->
true.
check_password(User, Password) ->
extauth:check_password(User, Password).
check_password(User, Password, _StreamID, _Digest) ->
check_password(User, Password).
set_password(User, Password) ->
extauth:set_password(User, Password).
try_register(_User, _Password) ->
{error, not_allowed}.
dirty_get_registered_users() ->
[].
get_password(_User) ->
false.
get_password_s(_User) ->
"".
is_user_exists(User) ->
extauth:is_user_exists(User).
remove_user(_User) ->
{error, not_allowed}.
remove_user(_User, _Password) ->
not_allowed.

View File

@ -0,0 +1,167 @@
%%%----------------------------------------------------------------------
%%% File : ejabberd_auth_internal.erl
%%% Author : Alexey Shchepin <alexey@sevcom.net>
%%% Purpose : Authentification via mnesia
%%% Created : 12 Dec 2004 by Alexey Shchepin <alexey@sevcom.net>
%%% Id : $Id$
%%%----------------------------------------------------------------------
-module(ejabberd_auth_internal).
-author('alexey@sevcom.net').
-vsn('$Revision$ ').
%% External exports
-export([start/0,
set_password/2,
check_password/2,
check_password/4,
try_register/2,
dirty_get_registered_users/0,
get_password/1,
get_password_s/1,
is_user_exists/1,
remove_user/1,
remove_user/2,
plain_password_required/0
]).
-record(passwd, {user, password}).
%%%----------------------------------------------------------------------
%%% API
%%%----------------------------------------------------------------------
start() ->
mnesia:create_table(passwd,[{disc_copies, [node()]},
{attributes, record_info(fields, passwd)}]),
ok.
plain_password_required() ->
false.
check_password(User, Password) ->
LUser = jlib:nodeprep(User),
case catch mnesia:dirty_read({passwd, LUser}) of
[#passwd{password = Password}] ->
true;
_ ->
false
end.
check_password(User, Password, StreamID, Digest) ->
LUser = jlib:nodeprep(User),
case catch mnesia:dirty_read({passwd, LUser}) of
[#passwd{password = Passwd}] ->
DigRes = if
Digest /= "" ->
Digest == sha:sha(StreamID ++ Passwd);
true ->
false
end,
if DigRes ->
true;
true ->
(Passwd == Password) and (Password /= "")
end;
_ ->
false
end.
set_password(User, Password) ->
case jlib:nodeprep(User) of
error -> {error, invalid_jid};
LUser ->
F = fun() ->
mnesia:write(#passwd{user = LUser,
password = Password})
end,
mnesia:transaction(F)
end.
try_register(User, Password) ->
case jlib:nodeprep(User) of
error -> {error, invalid_jid};
LUser ->
F = fun() ->
case mnesia:read({passwd, LUser}) of
[] ->
mnesia:write(#passwd{user = LUser,
password = Password}),
ok;
[_E] ->
exists
end
end,
mnesia:transaction(F)
end.
dirty_get_registered_users() ->
mnesia:dirty_all_keys(passwd).
get_password(User) ->
LUser = jlib:nodeprep(User),
case catch mnesia:dirty_read(passwd, LUser) of
[#passwd{password = Password}] ->
Password;
_ ->
false
end.
get_password_s(User) ->
LUser = jlib:nodeprep(User),
case catch mnesia:dirty_read(passwd, LUser) of
[#passwd{password = Password}] ->
Password;
_ ->
[]
end.
is_user_exists(User) ->
LUser = jlib:nodeprep(User),
case catch mnesia:dirty_read({passwd, LUser}) of
[] ->
false;
[_] ->
true;
_ ->
false
end.
remove_user(User) ->
LUser = jlib:nodeprep(User),
F = fun() ->
mnesia:delete({passwd, LUser})
end,
mnesia:transaction(F),
catch mod_roster:remove_user(User),
catch mod_offline:remove_user(User),
catch mod_last:remove_user(User),
catch mod_vcard:remove_user(User),
catch mod_private:remove_user(User).
remove_user(User, Password) ->
LUser = jlib:nodeprep(User),
F = fun() ->
case mnesia:read({passwd, LUser}) of
[#passwd{password = Password}] ->
mnesia:delete({passwd, LUser}),
ok;
[_] ->
not_allowed;
_ ->
not_exists
end
end,
case mnesia:transaction(F) of
{atomic, ok} ->
catch mod_roster:remove_user(User),
catch mod_offline:remove_user(User),
catch mod_last:remove_user(User),
catch mod_vcard:remove_user(User),
catch mod_private:remove_user(User),
ok;
{atomic, Res} ->
Res;
_ ->
bad_request
end.

106
src/ejabberd_auth_ldap.erl Normal file
View File

@ -0,0 +1,106 @@
%%%----------------------------------------------------------------------
%%% File : ejabberd_auth_ldap.erl
%%% Author : Alexey Shchepin <alexey@sevcom.net>
%%% Purpose : Authentification via LDAP
%%% Created : 12 Dec 2004 by Alexey Shchepin <alexey@sevcom.net>
%%% Id : $Id$
%%%----------------------------------------------------------------------
-module(ejabberd_auth_ldap).
-author('alexey@sevcom.net').
-vsn('$Revision$ ').
%% External exports
-export([start/0,
set_password/2,
check_password/2,
check_password/4,
try_register/2,
dirty_get_registered_users/0,
get_password/1,
get_password_s/1,
is_user_exists/1,
remove_user/1,
remove_user/2,
plain_password_required/0
]).
-include("eldap/eldap.hrl").
%%%----------------------------------------------------------------------
%%% API
%%%----------------------------------------------------------------------
start() ->
LDAPServers = ejabberd_config:get_local_option(ldap_servers),
RootDN = ejabberd_config:get_local_option(ldap_rootdn),
Password = ejabberd_config:get_local_option(ldap_password),
eldap:start_link("ejabberd", LDAPServers, 389, RootDN, Password),
eldap:start_link("ejabberd_bind", LDAPServers, 389, RootDN, Password),
ok.
plain_password_required() ->
true.
check_password(User, Password) ->
case find_user_dn(User) of
false ->
false;
DN ->
case eldap:bind("ejabberd_bind", DN, Password) of
ok ->
true;
_ ->
false
end
end.
check_password(User, Password, _StreamID, _Digest) ->
check_password(User, Password).
set_password(_User, _Password) ->
{error, not_allowed}.
try_register(_User, _Password) ->
{error, not_allowed}.
dirty_get_registered_users() ->
[].
get_password(_User) ->
false.
get_password_s(_User) ->
"".
is_user_exists(User) ->
case find_user_dn(User) of
false ->
false;
_DN ->
true
end.
remove_user(_User) ->
{error, not_allowed}.
remove_user(_User, _Password) ->
not_allowed.
%%%----------------------------------------------------------------------
%%% Internal functions
%%%----------------------------------------------------------------------
find_user_dn(User) ->
Attr = ejabberd_config:get_local_option(ldap_uidattr),
Filter = eldap:equalityMatch(Attr, User),
Base = ejabberd_config:get_local_option(ldap_base),
case eldap:search("ejabberd", [{base, Base},
{filter, Filter},
{attributes, []}]) of
#eldap_search_result{entries = [E | _]} ->
E#eldap_entry.object_name;
_ ->
false
end.

View File

@ -331,13 +331,12 @@ set_presence(User, Resource, Priority) ->
mnesia:transaction(F).
unset_presence(User, Resource, Status) ->
LUser = jlib:nodeprep(User),
F = fun() ->
UR = {User, Resource},
mnesia:delete({presence, UR})
end,
mnesia:transaction(F),
catch mod_last:on_presence_update(LUser, Status).
ejabberd_hooks:run(unset_presence_hook, [User, Resource, Status]).
get_user_present_resources(LUser) ->
case catch mnesia:dirty_index_read(presence, LUser, #presence.user) of

View File

@ -16,7 +16,7 @@
stop/0,
process_local_iq/3,
process_sm_iq/3,
on_presence_update/2,
on_presence_update/3,
remove_user/1]).
-include("ejabberd.hrl").
@ -34,7 +34,9 @@ start(Opts) ->
gen_iq_handler:add_iq_handler(ejabberd_local, ?NS_LAST,
?MODULE, process_local_iq, IQDisc),
gen_iq_handler:add_iq_handler(ejabberd_sm, ?NS_LAST,
?MODULE, process_sm_iq, IQDisc).
?MODULE, process_sm_iq, IQDisc),
ejabberd_hooks:add(unset_presence_hook,
?MODULE, on_presence_update, 50).
stop() ->
gen_iq_handler:remove_iq_handler(ejabberd_local, ?NS_LAST),
@ -107,7 +109,8 @@ get_last(IQ, SubEl, LUser) ->
on_presence_update(LUser, Status) ->
on_presence_update(User, _Resource, Status) ->
LUser = jlib:nodeprep(User),
{MegaSecs, Secs, _MicroSecs} = now(),
TimeStamp = MegaSecs * 1000000 + Secs,
F = fun() ->