25
1
mirror of https://github.com/processone/ejabberd.git synced 2024-12-04 16:40:36 +01:00

Merged the Process One contributions ( Virtual Hosting )

SVN Revision: 307
This commit is contained in:
tmallard 2005-04-17 18:08:34 +00:00
parent 13de45118d
commit 374446f847
46 changed files with 6472 additions and 1305 deletions

View File

@ -13,17 +13,19 @@
-export([start/0,
register_mechanism/2,
listmech/0,
server_new/4,
server_new/6,
server_start/3,
server_step/2]).
-record(sasl_mechanism, {mechanism, module}).
-record(sasl_state, {service, myname, realm, mech_mod, mech_state}).
-record(sasl_state, {service, myname, realm,
get_password, check_password,
mech_mod, mech_state}).
-export([behaviour_info/1]).
behaviour_info(callbacks) ->
[{mech_new, 0},
[{mech_new, 2},
{mech_step, 2}];
behaviour_info(Other) ->
undefined.
@ -80,15 +82,19 @@ listmech() ->
[{#sasl_mechanism{mechanism = '$1', _ = '_'}, [], ['$1']}]).
server_new(Service, ServerFQDN, UserRealm, SecFlags) ->
server_new(Service, ServerFQDN, UserRealm, SecFlags,
GetPassword, CheckPassword) ->
#sasl_state{service = Service,
myname = ServerFQDN,
realm = UserRealm}.
realm = UserRealm,
get_password = GetPassword,
check_password = CheckPassword}.
server_start(State, Mech, ClientIn) ->
case ets:lookup(sasl_mechanism, Mech) of
[#sasl_mechanism{module = Module}] ->
{ok, MechState} = Module:mech_new(),
{ok, MechState} = Module:mech_new(State#sasl_state.get_password,
State#sasl_state.check_password),
server_step(State#sasl_state{mech_mod = Module,
mech_state = MechState},
ClientIn);

View File

@ -12,15 +12,14 @@
-export([start/1,
stop/0,
mech_new/0,
mech_new/2,
mech_step/2]).
-behaviour(cyrsasl).
%-behaviour(gen_mod).
-record(state, {step, nonce, username, authzid}).
-record(state, {step, nonce, username, authzid, get_password}).
start(Opts) ->
start(_Opts) ->
case ejabberd_auth:plain_password_required() of
true ->
ok;
@ -32,15 +31,15 @@ start(Opts) ->
stop() ->
ok.
mech_new() ->
mech_new(GetPassword, _CheckPassword) ->
{ok, #state{step = 1,
nonce = randoms:get_string()}}.
nonce = randoms:get_string(),
get_password = GetPassword}}.
mech_step(#state{step = 1, nonce = Nonce} = State, _) ->
{continue,
"nonce=\"" ++ Nonce ++
"\",qop=\"auth\",charset=utf-8,algorithm=md5-sess",
%"\",qop=\"auth,auth-int\",charset=utf-8,algorithm=md5-sess",
State#state{step = 3}};
mech_step(#state{step = 3, nonce = Nonce} = State, ClientIn) ->
case parse(ClientIn) of
@ -49,7 +48,7 @@ mech_step(#state{step = 3, nonce = Nonce} = State, ClientIn) ->
KeyVals ->
UserName = xml:get_attr_s("username", KeyVals),
AuthzId = xml:get_attr_s("authzid", KeyVals),
case ejabberd_auth:get_password(UserName) of
case (State#state.get_password)(UserName) of
false ->
{error, "not-authorized"};
Passwd ->
@ -72,7 +71,7 @@ mech_step(#state{step = 3, nonce = Nonce} = State, ClientIn) ->
end;
mech_step(#state{step = 5,
username = UserName,
authzid = AuthzId} = State, "") ->
authzid = AuthzId}, "") ->
{ok, [{username, UserName}, {authzid, AuthzId}]};
mech_step(A, B) ->
io:format("SASL DIGEST: A ~p B ~p", [A,B]),
@ -88,7 +87,7 @@ parse1([C | Cs], S, Ts) ->
parse1(Cs, [C | S], Ts);
parse1([], [], T) ->
lists:reverse(T);
parse1([], S, T) ->
parse1([], _S, _T) ->
bad.
parse2([$" | Cs], Key, Val, Ts) ->
@ -148,13 +147,13 @@ response(KeyVals, User, Passwd, Nonce, AuthzId, A2Prefix) ->
crypto:md5(User ++ ":" ++ Realm ++ ":" ++ Passwd)) ++
":" ++ Nonce ++ ":" ++ CNonce ++ ":" ++ AuthzId
end,
case QOP of
"auth" ->
A2 = A2Prefix ++ ":" ++ DigestURI;
_ ->
A2 = A2Prefix ++ ":" ++ DigestURI ++
":00000000000000000000000000000000"
end,
A2 = case QOP of
"auth" ->
A2Prefix ++ ":" ++ DigestURI;
_ ->
A2Prefix ++ ":" ++ DigestURI ++
":00000000000000000000000000000000"
end,
T = hex(binary_to_list(crypto:md5(A1))) ++ ":" ++ Nonce ++ ":" ++
NC ++ ":" ++ CNonce ++ ":" ++ QOP ++ ":" ++
hex(binary_to_list(crypto:md5(A2))),

View File

@ -10,25 +10,26 @@
-author('alexey@sevcom.net').
-vsn('$Revision$ ').
-export([start/1, stop/0, mech_new/0, mech_step/2, parse/1]).
-export([start/1, stop/0, mech_new/2, mech_step/2, parse/1]).
-behaviour(cyrsasl).
%-behaviour(gen_mod).
start(Opts) ->
-record(state, {check_password}).
start(_Opts) ->
cyrsasl:register_mechanism("PLAIN", ?MODULE),
ok.
stop() ->
ok.
mech_new() ->
{ok, []}.
mech_new(_GetPassword, CheckPassword) ->
{ok, #state{check_password = CheckPassword}}.
mech_step(State, ClientIn) ->
case parse(ClientIn) of
[AuthzId, User, Password] ->
case ejabberd_auth:check_password(User, Password) of
case (State#state.check_password)(User, Password) of
true ->
{ok, [{username, User}, {authzid, AuthzId}]};
_ ->

View File

@ -27,10 +27,9 @@
[self(),?MODULE,?LINE]++Args)).
%-define(MYNAME,"e.localhost").
-define(MYNAME, ejabberd_config:get_global_option(host)).
-define(MYHOSTS, ejabberd_config:get_global_option(hosts)).
-define(MYNAME, hd(ejabberd_config:get_global_option(hosts))).
-define(S2STIMEOUT, 600000).
%-define(S2STIMEOUT, 6000).
-define(MYLANG, ejabberd_config:get_global_option(language)).
-define(MSGS_DIR, "msgs").

View File

@ -12,16 +12,17 @@
%% External exports
-export([start/0,
set_password/2,
check_password/2,
check_password/4,
try_register/2,
set_password/3,
check_password/3,
check_password/5,
try_register/3,
dirty_get_registered_users/0,
get_password/1,
get_password_s/1,
is_user_exists/1,
remove_user/1,
get_vh_registered_users/1,
get_password/2,
get_password_s/2,
is_user_exists/2,
remove_user/2,
remove_user/3,
plain_password_required/0
]).
@ -34,35 +35,38 @@ start() ->
plain_password_required() ->
(auth_module()):plain_password_required().
check_password(User, Password) ->
(auth_module()):check_password(User, Password).
check_password(User, Server, Password) ->
(auth_module()):check_password(User, Server, Password).
check_password(User, Password, StreamID, Digest) ->
(auth_module()):check_password(User, Password, StreamID, Digest).
check_password(User, Server, Password, StreamID, Digest) ->
(auth_module()):check_password(User, Server, Password, StreamID, Digest).
set_password(User, Password) ->
(auth_module()):set_password(User, Password).
set_password(User, Server, Password) ->
(auth_module()):set_password(User, Server, Password).
try_register(User, Password) ->
(auth_module()):try_register(User, Password).
try_register(User, Server, Password) ->
(auth_module()):try_register(User, Server, Password).
dirty_get_registered_users() ->
(auth_module()):dirty_get_registered_users().
get_password(User) ->
(auth_module()):get_password(User).
get_vh_registered_users(Server) ->
(auth_module()):get_vh_registered_users(Server).
get_password_s(User) ->
(auth_module()):get_password_s(User).
get_password(User, Server) ->
(auth_module()):get_password(User, Server).
is_user_exists(User) ->
(auth_module()):is_user_exists(User).
get_password_s(User, Server) ->
(auth_module()):get_password_s(User, Server).
remove_user(User) ->
(auth_module()):remove_user(User).
is_user_exists(User, Server) ->
(auth_module()):is_user_exists(User, Server).
remove_user(User, Password) ->
(auth_module()):remove_user(User, Password).
remove_user(User, Server) ->
(auth_module()):remove_user(User, Server).
remove_user(User, Server, Password) ->
(auth_module()):remove_user(User, Server, Password).
%%%----------------------------------------------------------------------
%%% Internal functions

View File

@ -12,16 +12,17 @@
%% External exports
-export([start/0,
set_password/2,
check_password/2,
check_password/4,
try_register/2,
set_password/3,
check_password/3,
check_password/5,
try_register/3,
dirty_get_registered_users/0,
get_password/1,
get_password_s/1,
is_user_exists/1,
remove_user/1,
get_vh_registered_users/1,
get_password/2,
get_password_s/2,
is_user_exists/2,
remove_user/2,
remove_user/3,
plain_password_required/0
]).
@ -35,33 +36,36 @@ start() ->
plain_password_required() ->
true.
check_password(User, Password) ->
check_password(User, _Server, Password) ->
extauth:check_password(User, Password).
check_password(User, Password, _StreamID, _Digest) ->
check_password(User, Password).
check_password(User, Server, Password, _StreamID, _Digest) ->
check_password(User, Server, Password).
set_password(User, Password) ->
set_password(User, _Server, Password) ->
extauth:set_password(User, Password).
try_register(_User, _Password) ->
try_register(_User, _Server, _Password) ->
{error, not_allowed}.
dirty_get_registered_users() ->
[].
get_password(_User) ->
get_vh_registered_users(_Server) ->
[].
get_password(_User, _Server) ->
false.
get_password_s(_User) ->
get_password_s(_User, _Server) ->
"".
is_user_exists(User) ->
is_user_exists(User, _Server) ->
extauth:is_user_exists(User).
remove_user(_User) ->
remove_user(_User, _Server) ->
{error, not_allowed}.
remove_user(_User, _Password) ->
remove_user(_User, _Server, _Password) ->
not_allowed.

View File

@ -12,44 +12,52 @@
%% External exports
-export([start/0,
set_password/2,
check_password/2,
check_password/4,
try_register/2,
set_password/3,
check_password/3,
check_password/5,
try_register/3,
dirty_get_registered_users/0,
get_password/1,
get_password_s/1,
is_user_exists/1,
remove_user/1,
get_vh_registered_users/1,
get_password/2,
get_password_s/2,
is_user_exists/2,
remove_user/2,
remove_user/3,
plain_password_required/0
]).
-record(passwd, {user, password}).
-include("ejabberd.hrl").
-record(passwd, {us, password}).
%%%----------------------------------------------------------------------
%%% API
%%%----------------------------------------------------------------------
start() ->
mnesia:create_table(passwd,[{disc_copies, [node()]},
{attributes, record_info(fields, passwd)}]),
mnesia:create_table(passwd, [{disc_copies, [node()]},
{attributes, record_info(fields, passwd)}]),
update_table(),
ok.
plain_password_required() ->
false.
check_password(User, Password) ->
check_password(User, Server, Password) ->
LUser = jlib:nodeprep(User),
case catch mnesia:dirty_read({passwd, LUser}) of
LServer = jlib:nameprep(Server),
US = {LUser, LServer},
case catch mnesia:dirty_read({passwd, US}) of
[#passwd{password = Password}] ->
true;
_ ->
false
end.
check_password(User, Password, StreamID, Digest) ->
check_password(User, Server, Password, StreamID, Digest) ->
LUser = jlib:nodeprep(User),
case catch mnesia:dirty_read({passwd, LUser}) of
LServer = jlib:nameprep(Server),
US = {LUser, LServer},
case catch mnesia:dirty_read({passwd, US}) of
[#passwd{password = Passwd}] ->
DigRes = if
Digest /= "" ->
@ -66,26 +74,34 @@ check_password(User, Password, StreamID, Digest) ->
false
end.
set_password(User, Password) ->
case jlib:nodeprep(User) of
error -> {error, invalid_jid};
LUser ->
set_password(User, Server, Password) ->
LUser = jlib:nodeprep(User),
LServer = jlib:nameprep(Server),
US = {LUser, LServer},
if
(LUser == error) or (LServer == error) ->
{error, invalid_jid};
true ->
F = fun() ->
mnesia:write(#passwd{user = LUser,
mnesia:write(#passwd{us = US,
password = Password})
end,
mnesia:transaction(F)
end.
try_register(User, Password) ->
case jlib:nodeprep(User) of
error -> {error, invalid_jid};
LUser ->
try_register(User, Server, Password) ->
LUser = jlib:nodeprep(User),
LServer = jlib:nameprep(Server),
US = {LUser, LServer},
if
(LUser == error) or (LServer == error) ->
{error, invalid_jid};
true ->
F = fun() ->
case mnesia:read({passwd, LUser}) of
case mnesia:read({passwd, US}) of
[] ->
mnesia:write(#passwd{user = LUser,
mnesia:write(#passwd{us = US,
password = Password}),
ok;
[_E] ->
@ -98,27 +114,41 @@ try_register(User, Password) ->
dirty_get_registered_users() ->
mnesia:dirty_all_keys(passwd).
get_password(User) ->
get_vh_registered_users(Server) ->
LServer = jlib:nameprep(Server),
mnesia:dirty_select(
passwd,
[{#passwd{us = '$1', _ = '_'},
[{'==', {element, 2, '$1'}, LServer}],
['$1']}]).
get_password(User, Server) ->
LUser = jlib:nodeprep(User),
case catch mnesia:dirty_read(passwd, LUser) of
LServer = jlib:nameprep(Server),
US = {LUser, LServer},
case catch mnesia:dirty_read(passwd, US) of
[#passwd{password = Password}] ->
Password;
_ ->
false
end.
get_password_s(User) ->
get_password_s(User, Server) ->
LUser = jlib:nodeprep(User),
case catch mnesia:dirty_read(passwd, LUser) of
LServer = jlib:nameprep(Server),
US = {LUser, LServer},
case catch mnesia:dirty_read(passwd, US) of
[#passwd{password = Password}] ->
Password;
_ ->
[]
end.
is_user_exists(User) ->
is_user_exists(User, Server) ->
LUser = jlib:nodeprep(User),
case catch mnesia:dirty_read({passwd, LUser}) of
LServer = jlib:nameprep(Server),
US = {LUser, LServer},
case catch mnesia:dirty_read({passwd, US}) of
[] ->
false;
[_] ->
@ -127,20 +157,24 @@ is_user_exists(User) ->
false
end.
remove_user(User) ->
remove_user(User, Server) ->
LUser = jlib:nodeprep(User),
LServer = jlib:nameprep(Server),
US = {LUser, LServer},
F = fun() ->
mnesia:delete({passwd, LUser})
mnesia:delete({passwd, US})
end,
mnesia:transaction(F),
ejabberd_hooks:run(remove_user, [User]).
ejabberd_hooks:run(remove_user, [User, Server]).
remove_user(User, Password) ->
remove_user(User, Server, Password) ->
LUser = jlib:nodeprep(User),
LServer = jlib:nameprep(Server),
US = {LUser, LServer},
F = fun() ->
case mnesia:read({passwd, LUser}) of
case mnesia:read({passwd, US}) of
[#passwd{password = Password}] ->
mnesia:delete({passwd, LUser}),
mnesia:delete({passwd, US}),
ok;
[_] ->
not_allowed;
@ -150,10 +184,56 @@ remove_user(User, Password) ->
end,
case mnesia:transaction(F) of
{atomic, ok} ->
ejabberd_hooks:run(remove_user, [User]),
ejabberd_hooks:run(remove_user, [User, Server]),
ok;
{atomic, Res} ->
Res;
_ ->
bad_request
end.
update_table() ->
Fields = record_info(fields, passwd),
case mnesia:table_info(passwd, attributes) of
Fields ->
ok;
[user, password] ->
?INFO_MSG("Converting passwd table from "
"{user, password} format", []),
Host = ?MYNAME,
{atomic, ok} = mnesia:create_table(
ejabberd_auth_internal_tmp_table,
[{disc_only_copies, [node()]},
{type, bag},
{local_content, true},
{record_name, passwd},
{attributes, record_info(fields, passwd)}]),
mnesia:transform_table(passwd, ignore, Fields),
F1 = fun() ->
mnesia:write_lock_table(ejabberd_auth_internal_tmp_table),
mnesia:foldl(
fun(#passwd{us = U} = R, _) ->
mnesia:dirty_write(
ejabberd_auth_internal_tmp_table,
R#passwd{us = {U, Host}})
end, ok, passwd)
end,
mnesia:transaction(F1),
mnesia:clear_table(passwd),
F2 = fun() ->
mnesia:write_lock_table(passwd),
mnesia:foldl(
fun(R, _) ->
mnesia:dirty_write(R)
end, ok, ejabberd_auth_internal_tmp_table)
end,
mnesia:transaction(F2),
mnesia:delete_table(ejabberd_auth_internal_tmp_table);
_ ->
?INFO_MSG("Recreating passwd table", []),
mnesia:transform_table(passwd, ignore, Fields)
end.

View File

@ -12,16 +12,17 @@
%% External exports
-export([start/0,
set_password/2,
check_password/2,
check_password/4,
try_register/2,
set_password/3,
check_password/3,
check_password/5,
try_register/3,
dirty_get_registered_users/0,
get_password/1,
get_password_s/1,
is_user_exists/1,
remove_user/1,
get_vh_registered_users/1,
get_password/2,
get_password_s/2,
is_user_exists/2,
remove_user/2,
remove_user/3,
plain_password_required/0
]).
@ -41,7 +42,7 @@ start() ->
plain_password_required() ->
true.
check_password(User, Password) ->
check_password(User, _Server, Password) ->
case find_user_dn(User) of
false ->
false;
@ -54,25 +55,28 @@ check_password(User, Password) ->
end
end.
check_password(User, Password, _StreamID, _Digest) ->
check_password(User, Password).
check_password(User, Server, Password, _StreamID, _Digest) ->
check_password(User, Server, Password).
set_password(_User, _Password) ->
set_password(_User, _Server, _Password) ->
{error, not_allowed}.
try_register(_User, _Password) ->
try_register(_User, _Server, _Password) ->
{error, not_allowed}.
dirty_get_registered_users() ->
[].
get_password(_User) ->
get_vh_registered_users(_Server) ->
[].
get_password(_User, _Server) ->
false.
get_password_s(_User) ->
get_password_s(_User, _Server) ->
"".
is_user_exists(User) ->
is_user_exists(User, _Server) ->
case find_user_dn(User) of
false ->
false;
@ -80,10 +84,10 @@ is_user_exists(User) ->
true
end.
remove_user(_User) ->
remove_user(_User, _Server) ->
{error, not_allowed}.
remove_user(_User, _Password) ->
remove_user(_User, _Server, _Password) ->
not_allowed.

View File

@ -12,16 +12,16 @@
%% External exports
-export([start/0,
set_password/2,
check_password/2,
check_password/4,
try_register/2,
set_password/3,
check_password/3,
check_password/5,
try_register/3,
dirty_get_registered_users/0,
get_password/1,
get_password_s/1,
is_user_exists/1,
remove_user/1,
get_password/2,
get_password_s/2,
is_user_exists/2,
remove_user/2,
remove_user/3,
plain_password_required/0
]).
@ -36,7 +36,7 @@ start() ->
plain_password_required() ->
false.
check_password(User, Password) ->
check_password(User, _Server, Password) ->
case jlib:nodeprep(User) of
error ->
false;
@ -52,7 +52,7 @@ check_password(User, Password) ->
end
end.
check_password(User, Password, StreamID, Digest) ->
check_password(User, _Server, Password, StreamID, Digest) ->
case jlib:nodeprep(User) of
error ->
false;
@ -78,7 +78,7 @@ check_password(User, Password, StreamID, Digest) ->
end
end.
set_password(User, Password) ->
set_password(User, _Server, Password) ->
case jlib:nodeprep(User) of
error ->
{error, invalid_jid};
@ -93,7 +93,7 @@ set_password(User, Password) ->
end.
try_register(User, Password) ->
try_register(User, _Server, Password) ->
case jlib:nodeprep(User) of
error ->
{error, invalid_jid};
@ -118,7 +118,10 @@ dirty_get_registered_users() ->
[]
end.
get_password(User) ->
dirty_get_registered_users(Server) ->
dirty_get_registered_users().
get_password(User, _Server) ->
case jlib:nodeprep(User) of
error ->
false;
@ -134,7 +137,7 @@ get_password(User) ->
end
end.
get_password_s(User) ->
get_password_s(User, _Server) ->
case jlib:nodeprep(User) of
error ->
"";
@ -150,7 +153,7 @@ get_password_s(User) ->
end
end.
is_user_exists(User) ->
is_user_exists(User, _Server) ->
case jlib:nodeprep(User) of
error ->
false;
@ -166,7 +169,7 @@ is_user_exists(User) ->
end
end.
remove_user(User) ->
remove_user(User, _Server) ->
case jlib:nodeprep(User) of
error ->
error;
@ -177,7 +180,7 @@ remove_user(User) ->
ejabberd_hooks:run(remove_user, [User])
end.
remove_user(User, Password) ->
remove_user(User, _Server, Password) ->
case jlib:nodeprep(User) of
error ->
error;

View File

@ -83,6 +83,8 @@
xml:element_to_string(?SERR_INVALID_NAMESPACE)).
-define(INVALID_XML_ERR,
xml:element_to_string(?SERR_XML_NOT_WELL_FORMED)).
-define(HOST_UNKNOWN_ERR,
xml:element_to_string(?SERR_HOST_UNKNOWN)).
-define(POLICY_VIOLATION_ERR(Lang, Text),
xml:element_to_string(?SERRT_POLICY_VIOLATION(Lang, Text))).
@ -164,89 +166,114 @@ wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData) ->
end,
case xml:get_attr_s("xmlns:stream", Attrs) of
?NS_STREAM ->
Lang = xml:get_attr_s("xml:lang", Attrs),
case xml:get_attr_s("version", Attrs) of
"1.0" ->
Header = io_lib:format(?STREAM_HEADER,
[StateData#state.streamid,
?MYNAME,
" version='1.0'",
DefaultLang]),
send_text(StateData, Header),
case StateData#state.authentificated of
false ->
SASLState =
cyrsasl:server_new("jabber", ?MYNAME, "", []),
Mechs = lists:map(
fun(S) ->
{xmlelement, "mechanism", [],
[{xmlcdata, S}]}
end, cyrsasl:listmech()),
TLS = StateData#state.tls,
TLSEnabled = StateData#state.tls_enabled,
TLSRequired = StateData#state.tls_required,
SockMod = StateData#state.sockmod,
TLSFeature =
case (TLS == true) andalso
(TLSEnabled == false) andalso
(SockMod == gen_tcp) of
true ->
case TLSRequired of
Server = jlib:nameprep(xml:get_attr_s("to", Attrs)),
case lists:member(Server, ?MYHOSTS) of
true ->
Lang = xml:get_attr_s("xml:lang", Attrs),
case xml:get_attr_s("version", Attrs) of
"1.0" ->
Header = io_lib:format(?STREAM_HEADER,
[StateData#state.streamid,
Server,
" version='1.0'",
DefaultLang]),
send_text(StateData, Header),
case StateData#state.authentificated of
false ->
SASLState =
cyrsasl:server_new(
"jabber", Server, "", [],
fun(U) ->
ejabberd_auth:get_password(
U, Server)
end,
fun(U, P) ->
ejabberd_auth:check_password(
U, Server, P)
end),
Mechs = lists:map(
fun(S) ->
{xmlelement, "mechanism", [],
[{xmlcdata, S}]}
end, cyrsasl:listmech()),
TLS = StateData#state.tls,
TLSEnabled = StateData#state.tls_enabled,
TLSRequired = StateData#state.tls_required,
SockMod = StateData#state.sockmod,
TLSFeature =
case (TLS == true) andalso
(TLSEnabled == false) andalso
(SockMod == gen_tcp) of
true ->
[{xmlelement, "starttls",
[{"xmlns", ?NS_TLS}],
[{xmlelement, "required",
[], []}]}];
_ ->
[{xmlelement, "starttls",
[{"xmlns", ?NS_TLS}], []}]
end;
false ->
[]
end,
send_element(StateData,
{xmlelement, "stream:features", [],
TLSFeature ++
[{xmlelement, "mechanisms",
[{"xmlns", ?NS_SASL}],
Mechs},
{xmlelement, "register",
[{"xmlns", ?NS_FEATURE_IQREGISTER}],
[]}]}),
{next_state, wait_for_feature_request,
StateData#state{sasl_state = SASLState,
lang = Lang}};
_ ->
case StateData#state.resource of
"" ->
send_element(
StateData,
{xmlelement, "stream:features", [],
[{xmlelement, "bind",
[{"xmlns", ?NS_BIND}], []},
{xmlelement, "session",
[{"xmlns", ?NS_SESSION}], []}]}),
{next_state, wait_for_bind,
StateData#state{lang = Lang}};
case TLSRequired of
true ->
[{xmlelement, "starttls",
[{"xmlns", ?NS_TLS}],
[{xmlelement, "required",
[], []}]}];
_ ->
[{xmlelement, "starttls",
[{"xmlns", ?NS_TLS}], []}]
end;
false ->
[]
end,
send_element(StateData,
{xmlelement, "stream:features", [],
TLSFeature ++
[{xmlelement, "mechanisms",
[{"xmlns", ?NS_SASL}],
Mechs},
{xmlelement, "register",
[{"xmlns", ?NS_FEATURE_IQREGISTER}],
[]}]}),
{next_state, wait_for_feature_request,
StateData#state{server = Server,
sasl_state = SASLState,
lang = Lang}};
_ ->
send_element(
StateData,
{xmlelement, "stream:features", [], []}),
{next_state, wait_for_session,
StateData#state{lang = Lang}}
end
case StateData#state.resource of
"" ->
send_element(
StateData,
{xmlelement, "stream:features", [],
[{xmlelement, "bind",
[{"xmlns", ?NS_BIND}], []},
{xmlelement, "session",
[{"xmlns", ?NS_SESSION}], []}]}),
{next_state, wait_for_bind,
StateData#state{server = Server,
lang = Lang}};
_ ->
send_element(
StateData,
{xmlelement, "stream:features", [], []}),
{next_state, wait_for_session,
StateData#state{server = Server,
lang = Lang}}
end
end;
_ ->
Header = io_lib:format(
?STREAM_HEADER,
[StateData#state.streamid, Server, "", DefaultLang]),
send_text(StateData, Header),
{next_state, wait_for_auth,
StateData#state{server = Server,
lang = Lang}}
end;
_ ->
Header = io_lib:format(
?STREAM_HEADER,
[StateData#state.streamid, ?MYNAME, "", DefaultLang]),
send_text(StateData, Header),
{next_state, wait_for_auth, StateData#state{lang = Lang}}
send_text(StateData,
Header ++ ?HOST_UNKNOWN_ERR ++ ?STREAM_TRAILER),
{stop, normal, StateData}
end;
_ ->
Header = io_lib:format(
?STREAM_HEADER,
[StateData#state.streamid, ?MYNAME, "", ""]),
[StateData#state.streamid, ?MYNAME, "", DefaultLang]),
send_text(StateData,
Header ++ ?INVALID_NS_ERR ++ ?STREAM_TRAILER),
{stop, normal, StateData}
@ -297,19 +324,20 @@ wait_for_auth({xmlstreamelement, El}, StateData) ->
send_element(StateData, Err),
{next_state, wait_for_auth, StateData};
{auth, _ID, set, {U, P, D, R}} ->
io:format("AUTH: ~p~n", [{U, P, D, R}]),
JID = jlib:make_jid(U, StateData#state.server, R),
case (JID /= error) andalso
(acl:match_rule(StateData#state.access, JID) == allow) of
true ->
case ejabberd_auth:check_password(
U, P, StateData#state.streamid, D) of
U, StateData#state.server, P,
StateData#state.streamid, D) of
true ->
?INFO_MSG(
"(~w) Accepted legacy authentication for ~s",
[StateData#state.socket,
jlib:jid_to_string(JID)]),
ejabberd_sm:open_session(U, R),
ejabberd_sm:open_session(
U, StateData#state.server, R),
Res1 = jlib:make_result_iq_reply(El),
Res = setelement(4, Res1, []),
send_element(StateData, Res),
@ -317,13 +345,14 @@ wait_for_auth({xmlstreamelement, El}, StateData) ->
{Fs, Ts} = ejabberd_hooks:run_fold(
roster_get_subscription_lists,
{[], []},
[U]),
[U, StateData#state.server]),
LJID = jlib:jid_tolower(
jlib:jid_remove_resource(JID)),
Fs1 = [LJID | Fs],
Ts1 = [LJID | Ts],
PrivList =
case catch mod_privacy:get_user_list(U) of
case catch mod_privacy:get_user_list(
U, StateData#state.server) of
{'EXIT', _} -> none;
PL -> PL
end,
@ -368,8 +397,10 @@ wait_for_auth({xmlstreamelement, El}, StateData) ->
case jlib:iq_query_info(El) of
#iq{xmlns = ?NS_REGISTER} = IQ ->
ResIQ = mod_register:process_iq(
{"", "", ""}, {"", ?MYNAME, ""}, IQ),
Res1 = jlib:replace_from_to({"", ?MYNAME, ""},
{"", "", ""},
jlib:make_jid("", StateData#state.server, ""),
IQ),
Res1 = jlib:replace_from_to({"", StateData#state.server, ""},
{"", "", ""},
jlib:iq_to_xml(ResIQ)),
Res = jlib:remove_attr("to", Res1),
@ -414,8 +445,7 @@ wait_for_feature_request({xmlstreamelement, El}, StateData) ->
?INFO_MSG("(~w) Accepted authentication for ~s",
[StateData#state.socket, U]),
{next_state, wait_for_stream,
StateData#state{streamid = new_id(),
authentificated = true,
StateData#state{authentificated = true,
user = U
}};
{continue, ServerOut, NewSASLState} ->
@ -445,7 +475,6 @@ wait_for_feature_request({xmlstreamelement, El}, StateData) ->
{next_state, wait_for_stream,
StateData#state{sockmod = tls,
socket = TLSSocket,
streamid = new_id(),
tls_enabled = true
}};
_ ->
@ -461,8 +490,10 @@ wait_for_feature_request({xmlstreamelement, El}, StateData) ->
case jlib:iq_query_info(El) of
#iq{xmlns = ?NS_REGISTER} = IQ ->
ResIQ = mod_register:process_iq(
{"", "", ""}, {"", ?MYNAME, ""}, IQ),
Res1 = jlib:replace_from_to({"", ?MYNAME, ""},
{"", "", ""},
jlib:make_jid("", StateData#state.server, ""),
IQ),
Res1 = jlib:replace_from_to({"", StateData#state.server, ""},
{"", "", ""},
jlib:iq_to_xml(ResIQ)),
Res = jlib:remove_attr("to", Res1),
@ -502,8 +533,7 @@ wait_for_sasl_response({xmlstreamelement, El}, StateData) ->
?INFO_MSG("(~w) Accepted authentication for ~s",
[StateData#state.socket, U]),
{next_state, wait_for_stream,
StateData#state{streamid = new_id(),
authentificated = true,
StateData#state{authentificated = true,
user = U
}};
{continue, ServerOut, NewSASLState} ->
@ -525,8 +555,10 @@ wait_for_sasl_response({xmlstreamelement, El}, StateData) ->
case jlib:iq_query_info(El) of
#iq{xmlns = ?NS_REGISTER} = IQ ->
ResIQ = mod_register:process_iq(
{"", "", ""}, {"", ?MYNAME, ""}, IQ),
Res1 = jlib:replace_from_to({"", ?MYNAME, ""},
{"", "", ""},
jlib:make_jid("", StateData#state.server, ""),
IQ),
Res1 = jlib:replace_from_to({"", StateData#state.server, ""},
{"", "", ""},
jlib:iq_to_xml(ResIQ)),
Res = jlib:remove_attr("to", Res1),
@ -601,26 +633,27 @@ wait_for_session({xmlstreamelement, El}, StateData) ->
#iq{type = set, xmlns = ?NS_SESSION} ->
U = StateData#state.user,
R = StateData#state.resource,
io:format("SASLAUTH: ~p~n", [{U, R}]),
JID = StateData#state.jid,
case acl:match_rule(StateData#state.access, JID) of
allow ->
?INFO_MSG("(~w) Opened session for ~s",
[StateData#state.socket,
jlib:jid_to_string(JID)]),
ejabberd_sm:open_session(U, R),
ejabberd_sm:open_session(
U, StateData#state.server, R),
Res = jlib:make_result_iq_reply(El),
send_element(StateData, Res),
change_shaper(StateData, JID),
{Fs, Ts} = ejabberd_hooks:run_fold(
roster_get_subscription_lists,
{[], []},
[U]),
[U, StateData#state.server]),
LJID = jlib:jid_tolower(jlib:jid_remove_resource(JID)),
Fs1 = [LJID | Fs],
Ts1 = [LJID | Ts],
PrivList =
case catch mod_privacy:get_user_list(U) of
case catch mod_privacy:get_user_list(
U, StateData#state.server) of
{'EXIT', _} -> none;
PL -> PL
end,
@ -835,6 +868,7 @@ handle_info({route, From, To, Packet}, StateName, StateData) ->
%-ifdef(PRIVACY_SUPPORT).
case catch mod_privacy:check_packet(
StateData#state.user,
StateData#state.server,
StateData#state.privacy_list,
{From, To, Packet},
in) of
@ -884,6 +918,7 @@ handle_info({route, From, To, Packet}, StateName, StateData) ->
#iq{} ->
case catch mod_privacy:check_packet(
StateData#state.user,
StateData#state.server,
StateData#state.privacy_list,
{From, To, Packet},
in) of
@ -905,6 +940,7 @@ handle_info({route, From, To, Packet}, StateName, StateData) ->
"message" ->
case catch mod_privacy:check_packet(
StateData#state.user,
StateData#state.server,
StateData#state.privacy_list,
{From, To, Packet},
in) of
@ -955,6 +991,7 @@ terminate(_Reason, StateName, StateData) ->
[{xmlelement, "status", [],
[{xmlcdata, "Replaced by new connection"}]}]},
ejabberd_sm:unset_presence(StateData#state.user,
StateData#state.server,
StateData#state.resource,
"Replaced by new connection"),
presence_broadcast(
@ -966,6 +1003,7 @@ terminate(_Reason, StateName, StateData) ->
[StateData#state.socket,
jlib:jid_to_string(StateData#state.jid)]),
ejabberd_sm:close_session(StateData#state.user,
StateData#state.server,
StateData#state.resource),
Tmp = ?SETS:new(),
@ -980,6 +1018,7 @@ terminate(_Reason, StateName, StateData) ->
Packet = {xmlelement, "presence",
[{"type", "unavailable"}], []},
ejabberd_sm:unset_presence(StateData#state.user,
StateData#state.server,
StateData#state.resource,
""),
presence_broadcast(
@ -1070,6 +1109,7 @@ process_presence_probe(From, To, StateData) ->
%-ifdef(PRIVACY_SUPPORT).
case catch mod_privacy:check_packet(
StateData#state.user,
StateData#state.server,
StateData#state.privacy_list,
{To, From, Packet},
out) of
@ -1102,6 +1142,7 @@ presence_update(From, Packet, StateData) ->
xml:get_tag_cdata(StatusTag)
end,
ejabberd_sm:unset_presence(StateData#state.user,
StateData#state.server,
StateData#state.resource,
Status),
presence_broadcast(StateData, From, StateData#state.pres_a, Packet),
@ -1173,6 +1214,7 @@ presence_track(From, To, Packet, StateData) ->
{xmlelement, _Name, Attrs, _Els} = Packet,
LTo = jlib:jid_tolower(To),
User = StateData#state.user,
Server = StateData#state.server,
case xml:get_attr_s("type", Attrs) of
"unavailable" ->
ejabberd_router:route(From, To, Packet),
@ -1189,22 +1231,22 @@ presence_track(From, To, Packet, StateData) ->
"subscribe" ->
ejabberd_router:route(jlib:jid_remove_resource(From), To, Packet),
ejabberd_hooks:run(roster_out_subscription,
[User, To, subscribe]),
[User, Server, To, subscribe]),
StateData;
"subscribed" ->
ejabberd_router:route(jlib:jid_remove_resource(From), To, Packet),
ejabberd_hooks:run(roster_out_subscription,
[User, To, subscribed]),
[User, Server, To, subscribed]),
StateData;
"unsubscribe" ->
ejabberd_router:route(jlib:jid_remove_resource(From), To, Packet),
ejabberd_hooks:run(roster_out_subscription,
[User, To, unsubscribe]),
[User, Server, To, unsubscribe]),
StateData;
"unsubscribed" ->
ejabberd_router:route(jlib:jid_remove_resource(From), To, Packet),
ejabberd_hooks:run(roster_out_subscription,
[User, To, unsubscribed]),
[User, Server, To, unsubscribed]),
StateData;
"error" ->
ejabberd_router:route(From, To, Packet),
@ -1216,6 +1258,7 @@ presence_track(From, To, Packet, StateData) ->
%-ifdef(PRIVACY_SUPPORT).
case catch mod_privacy:check_packet(
StateData#state.user,
StateData#state.server,
StateData#state.privacy_list,
{From, To, Packet},
out) of
@ -1239,6 +1282,7 @@ presence_broadcast(StateData, From, JIDSet, Packet) ->
%-ifdef(PRIVACY_SUPPORT).
case catch mod_privacy:check_packet(
StateData#state.user,
StateData#state.server,
StateData#state.privacy_list,
{From, FJID, Packet},
out) of
@ -1261,6 +1305,7 @@ presence_broadcast_to_trusted(StateData, From, T, A, Packet) ->
%-ifdef(PRIVACY_SUPPORT).
case catch mod_privacy:check_packet(
StateData#state.user,
StateData#state.server,
StateData#state.privacy_list,
{From, FJID, Packet},
out) of
@ -1300,6 +1345,7 @@ presence_broadcast_first(From, StateData, Packet) ->
%-ifdef(PRIVACY_SUPPORT).
case catch mod_privacy:check_packet(
StateData#state.user,
StateData#state.server,
StateData#state.privacy_list,
{From, FJID, Packet},
out) of
@ -1395,6 +1441,7 @@ update_priority(El, StateData) ->
end
end,
ejabberd_sm:set_presence(StateData#state.user,
StateData#state.server,
StateData#state.resource,
Pri).
@ -1439,15 +1486,17 @@ process_privacy_iq(From, To,
resend_offline_messages(#state{user = User,
server = Server,
privacy_list = PrivList} = StateData) ->
case ejabberd_hooks:run_fold(resend_offline_messages_hook, [],
[User]) of
[User, Server]) of
Rs when list(Rs) ->
lists:foreach(
fun({route,
From, To, {xmlelement, Name, Attrs, Els} = Packet}) ->
Pass = case catch mod_privacy:check_packet(
<