25
1
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:
Alexey Shchepin 2006-04-07 00:39:24 +00:00
parent a5a978946d
commit 9a44fdffab
9 changed files with 154 additions and 52 deletions

View File

@ -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> 2006-04-06 Alexey Shchepin <alexey@sevcom.net>
* src/expat_erl.c: Use binaries for CDATA * src/expat_erl.c: Use binaries for CDATA

View File

@ -25,8 +25,7 @@
-export([behaviour_info/1]). -export([behaviour_info/1]).
behaviour_info(callbacks) -> behaviour_info(callbacks) ->
[{mech_new, 2}, [{mech_new, 3}, {mech_step, 2}];
{mech_step, 2}];
behaviour_info(Other) -> behaviour_info(Other) ->
undefined. undefined.
@ -36,6 +35,7 @@ start() ->
{keypos, #sasl_mechanism.mechanism}]), {keypos, #sasl_mechanism.mechanism}]),
cyrsasl_plain:start([]), cyrsasl_plain:start([]),
cyrsasl_digest:start([]), cyrsasl_digest:start([]),
cyrsasl_anonymous:start([]),
ok. ok.
register_mechanism(Mechanism, Module, RequirePlainPassword) -> register_mechanism(Mechanism, Module, RequirePlainPassword) ->
@ -81,18 +81,19 @@ check_credentials(State, Props) ->
listmech(Host) -> listmech(Host) ->
RequirePlainPassword = ejabberd_auth:plain_password_required(Host), RequirePlainPassword = ejabberd_auth:plain_password_required(Host),
ets:select(sasl_mechanism,
[{#sasl_mechanism{mechanism = '$1', Mechs = ets:select(sasl_mechanism,
require_plain_password = '$2', [{#sasl_mechanism{mechanism = '$1',
_ = '_'}, require_plain_password = '$2',
if _ = '_'},
RequirePlainPassword -> if
[{'==', '$2', false}]; RequirePlainPassword ->
true -> [{'==', '$2', false}];
[] true ->
end, []
['$1']}]). end,
['$1']}]),
filter_anonymous(Host, Mechs).
server_new(Service, ServerFQDN, UserRealm, SecFlags, server_new(Service, ServerFQDN, UserRealm, SecFlags,
GetPassword, CheckPassword) -> GetPassword, CheckPassword) ->
@ -105,8 +106,10 @@ server_new(Service, ServerFQDN, UserRealm, SecFlags,
server_start(State, Mech, ClientIn) -> server_start(State, Mech, ClientIn) ->
case ets:lookup(sasl_mechanism, Mech) of case ets:lookup(sasl_mechanism, Mech) of
[#sasl_mechanism{module = Module}] -> [#sasl_mechanism{module = Module}] ->
{ok, MechState} = Module:mech_new(State#sasl_state.get_password, {ok, MechState} = Module:mech_new(
State#sasl_state.check_password), State#sasl_state.myname,
State#sasl_state.get_password,
State#sasl_state.check_password),
server_step(State#sasl_state{mech_mod = Module, server_step(State#sasl_state{mech_mod = Module,
mech_state = MechState}, mech_state = MechState},
ClientIn); ClientIn);
@ -132,3 +135,10 @@ server_step(State, ClientIn) ->
{error, Error} {error, Error}
end. 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.

View File

@ -12,7 +12,7 @@
-export([start/1, -export([start/1,
stop/0, stop/0,
mech_new/2, mech_new/3,
mech_step/2]). mech_step/2]).
-behaviour(cyrsasl). -behaviour(cyrsasl).
@ -25,7 +25,7 @@ start(_Opts) ->
stop() -> stop() ->
ok. ok.
mech_new(GetPassword, _CheckPassword) -> mech_new(_Host, GetPassword, _CheckPassword) ->
{ok, #state{step = 1, {ok, #state{step = 1,
nonce = randoms:get_string(), nonce = randoms:get_string(),
get_password = GetPassword}}. get_password = GetPassword}}.

View File

@ -10,7 +10,7 @@
-author('alexey@sevcom.net'). -author('alexey@sevcom.net').
-vsn('$Revision$ '). -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). -behaviour(cyrsasl).
@ -23,7 +23,7 @@ start(_Opts) ->
stop() -> stop() ->
ok. ok.
mech_new(_GetPassword, CheckPassword) -> mech_new(_Host, _GetPassword, CheckPassword) ->
{ok, #state{check_password = CheckPassword}}. {ok, #state{check_password = CheckPassword}}.
mech_step(State, ClientIn) -> mech_step(State, ClientIn) ->

View File

@ -73,11 +73,11 @@
{access, local, [{allow, local}]}. {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: % this line:
{auth_method, internal}. {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}. %{auth_method, ldap}.
%{ldap_servers, ["localhost"]}. % List of LDAP servers %{ldap_servers, ["localhost"]}. % List of LDAP servers
%{ldap_uidattr, "uid"}. % LDAP attribute that holds user ID %{ldap_uidattr, "uid"}. % LDAP attribute that holds user ID
@ -85,11 +85,11 @@
%{ldap_rootdn, "dc=example,dc=com"}. % LDAP manager %{ldap_rootdn, "dc=example,dc=com"}. % LDAP manager
%{ldap_password, "******"}. % Password to 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}. %{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}. %{auth_method, odbc}.
%{odbc_server, "DSN=ejabberd;UID=ejabberd;PWD=ejabberd"}. %{odbc_server, "DSN=ejabberd;UID=ejabberd;PWD=ejabberd"}.
@ -98,6 +98,18 @@
{hosts, ["localhost"]}. {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 % Default language for server messages
{language, "en"}. {language, "en"}.

View File

@ -3,9 +3,13 @@
%%% Author : Alexey Shchepin <alexey@sevcom.net> %%% Author : Alexey Shchepin <alexey@sevcom.net>
%%% Purpose : Authentification %%% Purpose : Authentification
%%% Created : 23 Nov 2002 by Alexey Shchepin <alexey@sevcom.net> %%% 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$ %%% Id : $Id$
%%%---------------------------------------------------------------------- %%%----------------------------------------------------------------------
%% TODO: Use the functions in ejabberd auth to add and remove users.
-module(ejabberd_auth). -module(ejabberd_auth).
-author('alexey@sevcom.net'). -author('alexey@sevcom.net').
-vsn('$Revision$ '). -vsn('$Revision$ ').
@ -27,6 +31,8 @@
ctl_process_get_registered/3 ctl_process_get_registered/3
]). ]).
-export([auth_modules/1]).
-include("ejabberd.hrl"). -include("ejabberd.hrl").
-include("ejabberd_ctl.hrl"). -include("ejabberd_ctl.hrl").
@ -34,50 +40,102 @@
%%% API %%% API
%%%---------------------------------------------------------------------- %%%----------------------------------------------------------------------
start() -> start() ->
lists:foreach(fun(Host) -> lists:foreach(
(auth_module(Host)):start(Host) fun(Host) ->
end, ?MYHOSTS). lists:foreach(
fun(M) ->
M:start(Host)
end, auth_modules(Host))
end, ?MYHOSTS).
plain_password_required(Server) -> 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) -> 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) -> 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) -> 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) -> try_register(User, Server, Password) ->
case lists:member(jlib:nameprep(Server), ?MYHOSTS) of case lists:member(jlib:nameprep(Server), ?MYHOSTS) of
true -> 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 -> false ->
{error, not_allowed} {error, not_allowed}
end. end.
%% Registered users list do not include anonymous users logged
dirty_get_registered_users() -> 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) -> 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) -> 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) -> 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) -> 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) -> 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) -> 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"]) -> ctl_process_get_registered(_Val, Host, ["registered-users"]) ->
@ -93,9 +151,11 @@ ctl_process_get_registered(Val, _Host, _Args) ->
%%%---------------------------------------------------------------------- %%%----------------------------------------------------------------------
%%% Internal functions %%% Internal functions
%%%---------------------------------------------------------------------- %%%----------------------------------------------------------------------
auth_modules(Server) ->
auth_module(Server) ->
LServer = jlib:nameprep(Server), LServer = jlib:nameprep(Server),
Method = ejabberd_config:get_local_option({auth_method, LServer}), 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].

View File

@ -217,8 +217,8 @@ remove_user(User, Server, Password) ->
LServer = jlib:nameprep(Server), LServer = jlib:nameprep(Server),
F = fun() -> F = fun() ->
Result = ejabberd_odbc:sql_query_t( Result = ejabberd_odbc:sql_query_t(
["select password from users where username='", ["select password from users where username='",
Username, "';"]), Username, "';"]),
ejabberd_odbc:sql_query_t(["delete from users " ejabberd_odbc:sql_query_t(["delete from users "
"where username='", Username, "where username='", Username,
"' and password='", Pass, "';"]), "' and password='", Pass, "';"]),

View File

@ -1158,7 +1158,10 @@ terminate(_Reason, StateName, StateData) ->
pres_a = EmptySet, pres_a = EmptySet,
pres_i = EmptySet, pres_i = EmptySet,
pres_invis = false} -> 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, From = StateData#state.jid,
Packet = {xmlelement, "presence", Packet = {xmlelement, "presence",

View File

@ -15,7 +15,7 @@
%% API %% API
-export([start_link/0, -export([start_link/0,
route/3, route/3,
open_session/4, close_session/1, open_session/4, close_session/4,
bounce_offline_message/3, bounce_offline_message/3,
disconnect_removed_user/2, disconnect_removed_user/2,
get_user_resources/2, get_user_resources/2,
@ -62,13 +62,19 @@ route(From, To, Packet) ->
end. end.
open_session(SID, User, Server, Resource) -> 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() -> F = fun() ->
mnesia:delete({session, SID}) mnesia:delete({session, SID})
end, 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) -> bounce_offline_message(From, To, Packet) ->
Err = jlib:make_error_reply(Packet, ?ERR_SERVICE_UNAVAILABLE), Err = jlib:make_error_reply(Packet, ?ERR_SERVICE_UNAVAILABLE),
@ -101,7 +107,7 @@ unset_presence(SID, User, Server, Resource, Status) ->
[User, Server, Resource, Status]). [User, Server, Resource, Status]).
close_session_unset_presence(SID, 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), ejabberd_hooks:run(unset_presence_hook, jlib:nameprep(Server),
[User, Server, Resource, Status]). [User, Server, Resource, Status]).