mirror of
https://github.com/processone/ejabberd.git
synced 2024-12-20 17:27:00 +01:00
* src/ejabberd_sm.erl: SASL Anonymous + Anonymous login support
(thanks to Mickael Remond and Magnus Henoch) * src/ejabberd_c2s.erl: Likewise * src/ejabberd_auth.erl: Likewise * src/ejabberd_auth_anonymous.erl: Likewise * src/cyrsasl.erl: Likewise * src/cyrsasl_anonymous.erl: Likewise * src/ejabberd.cfg.example: Likewise SVN Revision: 527
This commit is contained in:
parent
a5a978946d
commit
9a44fdffab
11
ChangeLog
11
ChangeLog
@ -1,3 +1,14 @@
|
||||
2006-04-07 Alexey Shchepin <alexey@sevcom.net>
|
||||
|
||||
* src/ejabberd_sm.erl: SASL Anonymous + Anonymous login support
|
||||
(thanks to Mickael Remond and Magnus Henoch)
|
||||
* src/ejabberd_c2s.erl: Likewise
|
||||
* src/ejabberd_auth.erl: Likewise
|
||||
* src/ejabberd_auth_anonymous.erl: Likewise
|
||||
* src/cyrsasl.erl: Likewise
|
||||
* src/cyrsasl_anonymous.erl: Likewise
|
||||
* src/ejabberd.cfg.example: Likewise
|
||||
|
||||
2006-04-06 Alexey Shchepin <alexey@sevcom.net>
|
||||
|
||||
* src/expat_erl.c: Use binaries for CDATA
|
||||
|
@ -25,8 +25,7 @@
|
||||
-export([behaviour_info/1]).
|
||||
|
||||
behaviour_info(callbacks) ->
|
||||
[{mech_new, 2},
|
||||
{mech_step, 2}];
|
||||
[{mech_new, 3}, {mech_step, 2}];
|
||||
behaviour_info(Other) ->
|
||||
undefined.
|
||||
|
||||
@ -36,6 +35,7 @@ start() ->
|
||||
{keypos, #sasl_mechanism.mechanism}]),
|
||||
cyrsasl_plain:start([]),
|
||||
cyrsasl_digest:start([]),
|
||||
cyrsasl_anonymous:start([]),
|
||||
ok.
|
||||
|
||||
register_mechanism(Mechanism, Module, RequirePlainPassword) ->
|
||||
@ -81,18 +81,19 @@ check_credentials(State, Props) ->
|
||||
|
||||
listmech(Host) ->
|
||||
RequirePlainPassword = ejabberd_auth:plain_password_required(Host),
|
||||
ets:select(sasl_mechanism,
|
||||
[{#sasl_mechanism{mechanism = '$1',
|
||||
require_plain_password = '$2',
|
||||
_ = '_'},
|
||||
if
|
||||
RequirePlainPassword ->
|
||||
[{'==', '$2', false}];
|
||||
true ->
|
||||
[]
|
||||
end,
|
||||
['$1']}]).
|
||||
|
||||
Mechs = ets:select(sasl_mechanism,
|
||||
[{#sasl_mechanism{mechanism = '$1',
|
||||
require_plain_password = '$2',
|
||||
_ = '_'},
|
||||
if
|
||||
RequirePlainPassword ->
|
||||
[{'==', '$2', false}];
|
||||
true ->
|
||||
[]
|
||||
end,
|
||||
['$1']}]),
|
||||
filter_anonymous(Host, Mechs).
|
||||
|
||||
server_new(Service, ServerFQDN, UserRealm, SecFlags,
|
||||
GetPassword, CheckPassword) ->
|
||||
@ -105,8 +106,10 @@ server_new(Service, ServerFQDN, UserRealm, SecFlags,
|
||||
server_start(State, Mech, ClientIn) ->
|
||||
case ets:lookup(sasl_mechanism, Mech) of
|
||||
[#sasl_mechanism{module = Module}] ->
|
||||
{ok, MechState} = Module:mech_new(State#sasl_state.get_password,
|
||||
State#sasl_state.check_password),
|
||||
{ok, MechState} = Module:mech_new(
|
||||
State#sasl_state.myname,
|
||||
State#sasl_state.get_password,
|
||||
State#sasl_state.check_password),
|
||||
server_step(State#sasl_state{mech_mod = Module,
|
||||
mech_state = MechState},
|
||||
ClientIn);
|
||||
@ -132,3 +135,10 @@ server_step(State, ClientIn) ->
|
||||
{error, Error}
|
||||
end.
|
||||
|
||||
%% Remove the anonymous mechanism from the list if not enabled for the given
|
||||
%% host
|
||||
filter_anonymous(Host, Mechs) ->
|
||||
case ejabberd_auth_anonymous:is_sasl_anonymous_enabled(Host) of
|
||||
true -> Mechs;
|
||||
false -> Mechs -- "ANONYMOUS"
|
||||
end.
|
||||
|
@ -12,7 +12,7 @@
|
||||
|
||||
-export([start/1,
|
||||
stop/0,
|
||||
mech_new/2,
|
||||
mech_new/3,
|
||||
mech_step/2]).
|
||||
|
||||
-behaviour(cyrsasl).
|
||||
@ -25,7 +25,7 @@ start(_Opts) ->
|
||||
stop() ->
|
||||
ok.
|
||||
|
||||
mech_new(GetPassword, _CheckPassword) ->
|
||||
mech_new(_Host, GetPassword, _CheckPassword) ->
|
||||
{ok, #state{step = 1,
|
||||
nonce = randoms:get_string(),
|
||||
get_password = GetPassword}}.
|
||||
|
@ -10,7 +10,7 @@
|
||||
-author('alexey@sevcom.net').
|
||||
-vsn('$Revision$ ').
|
||||
|
||||
-export([start/1, stop/0, mech_new/2, mech_step/2, parse/1]).
|
||||
-export([start/1, stop/0, mech_new/3, mech_step/2, parse/1]).
|
||||
|
||||
-behaviour(cyrsasl).
|
||||
|
||||
@ -23,7 +23,7 @@ start(_Opts) ->
|
||||
stop() ->
|
||||
ok.
|
||||
|
||||
mech_new(_GetPassword, CheckPassword) ->
|
||||
mech_new(_Host, _GetPassword, CheckPassword) ->
|
||||
{ok, #state{check_password = CheckPassword}}.
|
||||
|
||||
mech_step(State, ClientIn) ->
|
||||
|
@ -73,11 +73,11 @@
|
||||
{access, local, [{allow, local}]}.
|
||||
|
||||
|
||||
% Authentification method. If you want to use internal user base, then use
|
||||
% Authentication method. If you want to use internal user base, then use
|
||||
% this line:
|
||||
{auth_method, internal}.
|
||||
|
||||
% For LDAP authentification use these lines instead of above one:
|
||||
% For LDAP authentication use these lines instead of above one:
|
||||
%{auth_method, ldap}.
|
||||
%{ldap_servers, ["localhost"]}. % List of LDAP servers
|
||||
%{ldap_uidattr, "uid"}. % LDAP attribute that holds user ID
|
||||
@ -85,11 +85,11 @@
|
||||
%{ldap_rootdn, "dc=example,dc=com"}. % LDAP manager
|
||||
%{ldap_password, "******"}. % Password to LDAP manager
|
||||
|
||||
% For authentification via external script use the following:
|
||||
% For authentication via external script use the following:
|
||||
%{auth_method, external}.
|
||||
%{extauth_program, "/path/to/authentification/script"}.
|
||||
%{extauth_program, "/path/to/authentication/script"}.
|
||||
|
||||
% For authentification via ODBC use the following:
|
||||
% For authentication via ODBC use the following:
|
||||
%{auth_method, odbc}.
|
||||
%{odbc_server, "DSN=ejabberd;UID=ejabberd;PWD=ejabberd"}.
|
||||
|
||||
@ -98,6 +98,18 @@
|
||||
{hosts, ["localhost"]}.
|
||||
|
||||
|
||||
%% Anonymous login support:
|
||||
%% anonymous_protocol: sasl_anon|login_anon|both
|
||||
%% allow_multiple_connections: true|false
|
||||
%% anon_digest_password: "anonymous" (this is the default password that should
|
||||
%% be use for digest login).
|
||||
%%{host_config, "public.example.org", [{auth_method, anonymous},
|
||||
%% {allow_multiple_connections, false},
|
||||
%% {anonymous_protocol, sasl_anon},
|
||||
%% {anon_digest_password, "anonymous"}]}.
|
||||
%% To use both anonymous and internal authentication:
|
||||
%%{host_config, "public.example.org", [{auth_method, [anonymous, internal]}]}.
|
||||
|
||||
% Default language for server messages
|
||||
{language, "en"}.
|
||||
|
||||
|
@ -3,9 +3,13 @@
|
||||
%%% Author : Alexey Shchepin <alexey@sevcom.net>
|
||||
%%% Purpose : Authentification
|
||||
%%% Created : 23 Nov 2002 by Alexey Shchepin <alexey@sevcom.net>
|
||||
%%% Updated : 23 Feb 2006 by Mickael Remond <mremond@process-one.net>
|
||||
%%% for anonymous login support
|
||||
%%% Id : $Id$
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
%% TODO: Use the functions in ejabberd auth to add and remove users.
|
||||
|
||||
-module(ejabberd_auth).
|
||||
-author('alexey@sevcom.net').
|
||||
-vsn('$Revision$ ').
|
||||
@ -27,6 +31,8 @@
|
||||
ctl_process_get_registered/3
|
||||
]).
|
||||
|
||||
-export([auth_modules/1]).
|
||||
|
||||
-include("ejabberd.hrl").
|
||||
-include("ejabberd_ctl.hrl").
|
||||
|
||||
@ -34,50 +40,102 @@
|
||||
%%% API
|
||||
%%%----------------------------------------------------------------------
|
||||
start() ->
|
||||
lists:foreach(fun(Host) ->
|
||||
(auth_module(Host)):start(Host)
|
||||
end, ?MYHOSTS).
|
||||
lists:foreach(
|
||||
fun(Host) ->
|
||||
lists:foreach(
|
||||
fun(M) ->
|
||||
M:start(Host)
|
||||
end, auth_modules(Host))
|
||||
end, ?MYHOSTS).
|
||||
|
||||
plain_password_required(Server) ->
|
||||
(auth_module(Server)):plain_password_required().
|
||||
lists:any(
|
||||
fun(M) ->
|
||||
M:plain_password_required()
|
||||
end, auth_modules(Server)).
|
||||
|
||||
check_password(User, Server, Password) ->
|
||||
(auth_module(Server)):check_password(User, Server, Password).
|
||||
lists:any(
|
||||
fun(M) ->
|
||||
M:check_password(User, Server, Password)
|
||||
end, auth_modules(Server)).
|
||||
|
||||
check_password(User, Server, Password, StreamID, Digest) ->
|
||||
(auth_module(Server)):check_password(User, Server, Password, StreamID, Digest).
|
||||
lists:any(
|
||||
fun(M) ->
|
||||
M:check_password(User, Server, Password, StreamID, Digest)
|
||||
end, auth_modules(Server)).
|
||||
|
||||
set_password(User, Server, Password) ->
|
||||
(auth_module(Server)):set_password(User, Server, Password).
|
||||
lists:foldl(
|
||||
fun(M, {error, _}) ->
|
||||
M:set_password(User, Server, Password);
|
||||
(_M, Res) ->
|
||||
Res
|
||||
end, {error, not_allowed}, auth_modules(Server)).
|
||||
|
||||
try_register(User, Server, Password) ->
|
||||
case lists:member(jlib:nameprep(Server), ?MYHOSTS) of
|
||||
true ->
|
||||
(auth_module(Server)):try_register(User, Server, Password);
|
||||
lists:foldl(
|
||||
fun(_M, {atomic, ok} = Res) ->
|
||||
Res;
|
||||
(M, _) ->
|
||||
M:try_register(User, Server, Password)
|
||||
end, {error, not_allowed}, auth_modules(Server));
|
||||
false ->
|
||||
{error, not_allowed}
|
||||
end.
|
||||
|
||||
%% Registered users list do not include anonymous users logged
|
||||
dirty_get_registered_users() ->
|
||||
(auth_module(?MYNAME)):dirty_get_registered_users().
|
||||
lists:flatmap(
|
||||
fun(M) ->
|
||||
M:dirty_get_registered_users()
|
||||
end, auth_modules(?MYNAME)).
|
||||
|
||||
%% Registered users list do not include anonymous users logged
|
||||
get_vh_registered_users(Server) ->
|
||||
(auth_module(Server)):get_vh_registered_users(Server).
|
||||
lists:flatmap(
|
||||
fun(M) ->
|
||||
M:get_vh_registered_users(Server)
|
||||
end, auth_modules(Server)).
|
||||
|
||||
get_password(User, Server) ->
|
||||
(auth_module(Server)):get_password(User, Server).
|
||||
lists:foldl(
|
||||
fun(M, false) ->
|
||||
M:get_password(User, Server);
|
||||
(_M, Password) ->
|
||||
Password
|
||||
end, false, auth_modules(Server)).
|
||||
|
||||
get_password_s(User, Server) ->
|
||||
(auth_module(Server)):get_password_s(User, Server).
|
||||
case get_password(User, Server) of
|
||||
false ->
|
||||
"";
|
||||
Password ->
|
||||
Password
|
||||
end.
|
||||
|
||||
%% 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) ->
|
||||
(auth_module(Server)):is_user_exists(User, Server).
|
||||
lists:any(
|
||||
fun(M) ->
|
||||
M:is_user_exists(User, Server)
|
||||
end, auth_modules(Server)).
|
||||
|
||||
remove_user(User, Server) ->
|
||||
(auth_module(Server)):remove_user(User, Server).
|
||||
lists:foreach(
|
||||
fun(M) ->
|
||||
M:remove_user(User, Server)
|
||||
end, auth_modules(Server)).
|
||||
|
||||
remove_user(User, Server, Password) ->
|
||||
(auth_module(Server)):remove_user(User, Server, Password).
|
||||
lists:foreach(
|
||||
fun(M) ->
|
||||
M:remove_user(User, Server, Password)
|
||||
end, auth_modules(Server)).
|
||||
|
||||
|
||||
ctl_process_get_registered(_Val, Host, ["registered-users"]) ->
|
||||
@ -93,9 +151,11 @@ ctl_process_get_registered(Val, _Host, _Args) ->
|
||||
%%%----------------------------------------------------------------------
|
||||
%%% Internal functions
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
auth_module(Server) ->
|
||||
auth_modules(Server) ->
|
||||
LServer = jlib:nameprep(Server),
|
||||
Method = ejabberd_config:get_local_option({auth_method, LServer}),
|
||||
list_to_atom("ejabberd_auth_" ++ atom_to_list(Method)).
|
||||
|
||||
Methods = if
|
||||
is_list(Method) -> Method;
|
||||
is_atom(Method) -> [Method]
|
||||
end,
|
||||
[list_to_atom("ejabberd_auth_" ++ atom_to_list(M)) || M <- Methods].
|
||||
|
@ -217,8 +217,8 @@ remove_user(User, Server, Password) ->
|
||||
LServer = jlib:nameprep(Server),
|
||||
F = fun() ->
|
||||
Result = ejabberd_odbc:sql_query_t(
|
||||
["select password from users where username='",
|
||||
Username, "';"]),
|
||||
["select password from users where username='",
|
||||
Username, "';"]),
|
||||
ejabberd_odbc:sql_query_t(["delete from users "
|
||||
"where username='", Username,
|
||||
"' and password='", Pass, "';"]),
|
||||
|
@ -1158,7 +1158,10 @@ terminate(_Reason, StateName, StateData) ->
|
||||
pres_a = EmptySet,
|
||||
pres_i = EmptySet,
|
||||
pres_invis = false} ->
|
||||
ejabberd_sm:close_session(StateData#state.sid);
|
||||
ejabberd_sm:close_session(StateData#state.sid,
|
||||
StateData#state.user,
|
||||
StateData#state.server,
|
||||
StateData#state.resource);
|
||||
_ ->
|
||||
From = StateData#state.jid,
|
||||
Packet = {xmlelement, "presence",
|
||||
|
@ -15,7 +15,7 @@
|
||||
%% API
|
||||
-export([start_link/0,
|
||||
route/3,
|
||||
open_session/4, close_session/1,
|
||||
open_session/4, close_session/4,
|
||||
bounce_offline_message/3,
|
||||
disconnect_removed_user/2,
|
||||
get_user_resources/2,
|
||||
@ -62,13 +62,19 @@ route(From, To, Packet) ->
|
||||
end.
|
||||
|
||||
open_session(SID, User, Server, Resource) ->
|
||||
set_session(SID, User, Server, Resource, undefined).
|
||||
set_session(SID, User, Server, Resource, undefined),
|
||||
JID = jlib:make_jid(User, Server, Resource),
|
||||
ejabberd_hooks:run(sm_register_connection_hook, JID#jid.lserver,
|
||||
[SID, JID]).
|
||||
|
||||
close_session(SID) ->
|
||||
close_session(SID, User, Server, Resource) ->
|
||||
F = fun() ->
|
||||
mnesia:delete({session, SID})
|
||||
end,
|
||||
mnesia:sync_dirty(F).
|
||||
mnesia:sync_dirty(F),
|
||||
JID = jlib:make_jid(User, Server, Resource),
|
||||
ejabberd_hooks:run(sm_remove_connection_hook, JID#jid.lserver,
|
||||
[SID, JID]).
|
||||
|
||||
bounce_offline_message(From, To, Packet) ->
|
||||
Err = jlib:make_error_reply(Packet, ?ERR_SERVICE_UNAVAILABLE),
|
||||
@ -101,7 +107,7 @@ unset_presence(SID, User, Server, Resource, Status) ->
|
||||
[User, Server, Resource, Status]).
|
||||
|
||||
close_session_unset_presence(SID, User, Server, Resource, Status) ->
|
||||
close_session(SID),
|
||||
close_session(SID, User, Server, Resource),
|
||||
ejabberd_hooks:run(unset_presence_hook, jlib:nameprep(Server),
|
||||
[User, Server, Resource, Status]).
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user