* src/ejabberd_c2s.erl: SASL support updated to xmpp-core-13
* src/cyrsasl*.erl: Support for authzid SVN Revision: 114
This commit is contained in:
parent
2efb3e7e88
commit
bc73337214
|
@ -1,3 +1,11 @@
|
||||||
|
2003-06-07 Alexey Shchepin <alexey@sevcom.net>
|
||||||
|
|
||||||
|
* src/ejabberd_c2s.erl: SASL support updated to xmpp-core-13
|
||||||
|
|
||||||
|
2003-06-06 Alexey Shchepin <alexey@sevcom.net>
|
||||||
|
|
||||||
|
* src/cyrsasl*.erl: Support for authzid
|
||||||
|
|
||||||
2003-06-03 Alexey Shchepin <alexey@sevcom.net>
|
2003-06-03 Alexey Shchepin <alexey@sevcom.net>
|
||||||
|
|
||||||
* src/msgs/fr.msg: New french translation (thanks to Vincent Ricard)
|
* src/msgs/fr.msg: New french translation (thanks to Vincent Ricard)
|
||||||
|
|
|
@ -40,6 +40,30 @@ register_mechanism(Mechanism, Module) ->
|
||||||
ets:insert(sasl_mechanism, #sasl_mechanism{mechanism = Mechanism,
|
ets:insert(sasl_mechanism, #sasl_mechanism{mechanism = Mechanism,
|
||||||
module = Module}).
|
module = Module}).
|
||||||
|
|
||||||
|
% TODO: use callbacks
|
||||||
|
-include("ejabberd.hrl").
|
||||||
|
-include("jlib.hrl").
|
||||||
|
check_authzid(State, Props) ->
|
||||||
|
AuthzId = xml:get_attr_s(authzid, Props),
|
||||||
|
case jlib:string_to_jid(AuthzId) of
|
||||||
|
error ->
|
||||||
|
{error, "invalid-authzid"};
|
||||||
|
JID ->
|
||||||
|
LUser = xml:get_attr_s(username, Props),
|
||||||
|
{U, S, R} = jlib:jid_tolower(JID),
|
||||||
|
case R of
|
||||||
|
"" ->
|
||||||
|
{error, "invalid-authzid"};
|
||||||
|
_ ->
|
||||||
|
case {LUser, ?MYNAME} of
|
||||||
|
{U, S} ->
|
||||||
|
ok;
|
||||||
|
_ ->
|
||||||
|
{error, "invalid-authzid"}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end.
|
||||||
|
|
||||||
listmech() ->
|
listmech() ->
|
||||||
ets:select(sasl_mechanism,
|
ets:select(sasl_mechanism,
|
||||||
[{#sasl_mechanism{mechanism = '$1', _ = '_'}, [], ['$1']}]).
|
[{#sasl_mechanism{mechanism = '$1', _ = '_'}, [], ['$1']}]).
|
||||||
|
@ -58,7 +82,7 @@ server_start(State, Mech, ClientIn) ->
|
||||||
mech_state = MechState},
|
mech_state = MechState},
|
||||||
ClientIn);
|
ClientIn);
|
||||||
_ ->
|
_ ->
|
||||||
{error, "454"}
|
{error, "no-mechanism"}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
server_step(State, ClientIn) ->
|
server_step(State, ClientIn) ->
|
||||||
|
@ -66,13 +90,16 @@ server_step(State, ClientIn) ->
|
||||||
MechState = State#sasl_state.mech_state,
|
MechState = State#sasl_state.mech_state,
|
||||||
case Module:mech_step(MechState, ClientIn) of
|
case Module:mech_step(MechState, ClientIn) of
|
||||||
{ok, Props} ->
|
{ok, Props} ->
|
||||||
{ok, Props};
|
case check_authzid(State, Props) of
|
||||||
|
ok ->
|
||||||
|
{ok, Props};
|
||||||
|
{error, Error} ->
|
||||||
|
{error, Error}
|
||||||
|
end;
|
||||||
{continue, ServerOut, NewMechState} ->
|
{continue, ServerOut, NewMechState} ->
|
||||||
{continue, ServerOut,
|
{continue, ServerOut,
|
||||||
State#sasl_state{mech_state = NewMechState}};
|
State#sasl_state{mech_state = NewMechState}};
|
||||||
{error, Code} ->
|
{error, Error} ->
|
||||||
{error, Code}
|
{error, Error}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
-behaviour(cyrsasl).
|
-behaviour(cyrsasl).
|
||||||
%-behaviour(gen_mod).
|
%-behaviour(gen_mod).
|
||||||
|
|
||||||
-record(state, {step, nonce, username}).
|
-record(state, {step, nonce, username, authzid}).
|
||||||
|
|
||||||
start(Opts) ->
|
start(Opts) ->
|
||||||
cyrsasl:register_mechanism("DIGEST-MD5", ?MODULE),
|
cyrsasl:register_mechanism("DIGEST-MD5", ?MODULE),
|
||||||
|
@ -39,31 +39,38 @@ mech_step(#state{step = 1, nonce = Nonce} = State, "") ->
|
||||||
mech_step(#state{step = 3, nonce = Nonce} = State, ClientIn) ->
|
mech_step(#state{step = 3, nonce = Nonce} = State, ClientIn) ->
|
||||||
case parse(ClientIn) of
|
case parse(ClientIn) of
|
||||||
bad ->
|
bad ->
|
||||||
{error, "454"};
|
{error, "bad-protocol"};
|
||||||
KeyVals ->
|
KeyVals ->
|
||||||
UserName = xml:get_attr_s("username", KeyVals),
|
UserName = xml:get_attr_s("username", KeyVals),
|
||||||
|
AuthzId = xml:get_attr_s("authzid", KeyVals),
|
||||||
case ejabberd_auth:get_password(UserName) of
|
case ejabberd_auth:get_password(UserName) of
|
||||||
false ->
|
false ->
|
||||||
{error, "454"};
|
{error, "no-user"};
|
||||||
Passwd ->
|
Passwd ->
|
||||||
Response = response(KeyVals, UserName, Passwd,
|
Response = response(KeyVals, UserName, Passwd, AuthzId,
|
||||||
"AUTHENTICATE"),
|
"AUTHENTICATE"),
|
||||||
case xml:get_attr_s("response", KeyVals) of
|
case xml:get_attr_s("response", KeyVals) of
|
||||||
Response ->
|
Response ->
|
||||||
RspAuth = response(KeyVals, UserName, Passwd, ""),
|
RspAuth = response(KeyVals,
|
||||||
|
UserName, Passwd,
|
||||||
|
AuthzId, ""),
|
||||||
{continue,
|
{continue,
|
||||||
"rspauth=" ++ RspAuth,
|
"rspauth=" ++ RspAuth,
|
||||||
State#state{step = 5, username = UserName}};
|
State#state{step = 5,
|
||||||
|
username = UserName,
|
||||||
|
authzid = AuthzId}};
|
||||||
_ ->
|
_ ->
|
||||||
{error, "454"}
|
{error, "bad-auth"}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end;
|
end;
|
||||||
mech_step(#state{step = 5, username = UserName} = State, "") ->
|
mech_step(#state{step = 5,
|
||||||
{ok, [{username, UserName}]};
|
username = UserName,
|
||||||
|
authzid = AuthzId} = State, "") ->
|
||||||
|
{ok, [{username, UserName}, {authzid, AuthzId}]};
|
||||||
mech_step(A, B) ->
|
mech_step(A, B) ->
|
||||||
io:format("SASL DIGEST: A ~p B ~p", [A,B]),
|
io:format("SASL DIGEST: A ~p B ~p", [A,B]),
|
||||||
{error, "454"}.
|
{error, "bad-protocol"}.
|
||||||
|
|
||||||
|
|
||||||
parse(S) ->
|
parse(S) ->
|
||||||
|
@ -119,15 +126,23 @@ hex([N | Ns], Res) ->
|
||||||
digit_to_xchar(N div 16) | Res]).
|
digit_to_xchar(N div 16) | Res]).
|
||||||
|
|
||||||
|
|
||||||
response(KeyVals, User, Passwd, A2Prefix) ->
|
response(KeyVals, User, Passwd, AuthzId, A2Prefix) ->
|
||||||
Realm = xml:get_attr_s("realm", KeyVals),
|
Realm = xml:get_attr_s("realm", KeyVals),
|
||||||
Nonce = xml:get_attr_s("nonce", KeyVals),
|
Nonce = xml:get_attr_s("nonce", KeyVals),
|
||||||
CNonce = xml:get_attr_s("cnonce", KeyVals),
|
CNonce = xml:get_attr_s("cnonce", KeyVals),
|
||||||
DigestURI = xml:get_attr_s("digest-uri", KeyVals),
|
DigestURI = xml:get_attr_s("digest-uri", KeyVals),
|
||||||
NC = xml:get_attr_s("nc", KeyVals),
|
NC = xml:get_attr_s("nc", KeyVals),
|
||||||
QOP = xml:get_attr_s("qop", KeyVals),
|
QOP = xml:get_attr_s("qop", KeyVals),
|
||||||
A1 = binary_to_list(crypto:md5(User ++ ":" ++ Realm ++ ":" ++ Passwd)) ++
|
A1 = case AuthzId of
|
||||||
":" ++ Nonce ++ ":" ++ CNonce,
|
"" ->
|
||||||
|
binary_to_list(
|
||||||
|
crypto:md5(User ++ ":" ++ Realm ++ ":" ++ Passwd)) ++
|
||||||
|
":" ++ Nonce ++ ":" ++ CNonce;
|
||||||
|
_ ->
|
||||||
|
binary_to_list(
|
||||||
|
crypto:md5(User ++ ":" ++ Realm ++ ":" ++ Passwd)) ++
|
||||||
|
":" ++ Nonce ++ ":" ++ CNonce ++ ":" ++ AuthzId
|
||||||
|
end,
|
||||||
case QOP of
|
case QOP of
|
||||||
"auth" ->
|
"auth" ->
|
||||||
A2 = A2Prefix ++ ":" ++ DigestURI;
|
A2 = A2Prefix ++ ":" ++ DigestURI;
|
||||||
|
|
|
@ -27,15 +27,15 @@ mech_new() ->
|
||||||
|
|
||||||
mech_step(State, ClientIn) ->
|
mech_step(State, ClientIn) ->
|
||||||
case parse(ClientIn) of
|
case parse(ClientIn) of
|
||||||
[_, User, Password] ->
|
[AuthzId, User, Password] ->
|
||||||
case ejabberd_auth:check_password(User, Password) of
|
case ejabberd_auth:check_password(User, Password) of
|
||||||
true ->
|
true ->
|
||||||
{ok, [{username, User}]};
|
{ok, [{username, User}, {authzid, AuthzId}]};
|
||||||
_ ->
|
_ ->
|
||||||
{error, "454"}
|
{error, "bad-auth"}
|
||||||
end;
|
end;
|
||||||
_ ->
|
_ ->
|
||||||
{error, "454"}
|
{error, "bad-protocol"}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
wait_for_stream/2,
|
wait_for_stream/2,
|
||||||
wait_for_auth/2,
|
wait_for_auth/2,
|
||||||
wait_for_sasl_auth/2,
|
wait_for_sasl_auth/2,
|
||||||
wait_for_resource_auth/2,
|
wait_for_session/2,
|
||||||
wait_for_sasl_response/2,
|
wait_for_sasl_response/2,
|
||||||
session_established/2,
|
session_established/2,
|
||||||
handle_event/3,
|
handle_event/3,
|
||||||
|
@ -40,6 +40,7 @@
|
||||||
sasl_state,
|
sasl_state,
|
||||||
access,
|
access,
|
||||||
shaper,
|
shaper,
|
||||||
|
authentificated = false,
|
||||||
user = "", server = ?MYNAME, resource = "",
|
user = "", server = ?MYNAME, resource = "",
|
||||||
pres_t = ?SETS:new(),
|
pres_t = ?SETS:new(),
|
||||||
pres_f = ?SETS:new(),
|
pres_f = ?SETS:new(),
|
||||||
|
@ -129,13 +130,18 @@ wait_for_stream({xmlstreamstart, Name, Attrs}, StateData) ->
|
||||||
{xmlelement, "mechanism", [],
|
{xmlelement, "mechanism", [],
|
||||||
[{xmlcdata, S}]}
|
[{xmlcdata, S}]}
|
||||||
end, cyrsasl:listmech()),
|
end, cyrsasl:listmech()),
|
||||||
send_element(StateData,
|
case StateData#state.authentificated of
|
||||||
{xmlelement, "stream:features", [],
|
false ->
|
||||||
[{xmlelement, "mechanisms",
|
send_element(StateData,
|
||||||
[{"xmlns", ?NS_SASL_MECHANISMS}],
|
{xmlelement, "stream:features", [],
|
||||||
Mechs}]}),
|
[{xmlelement, "mechanisms",
|
||||||
{next_state, wait_for_sasl_auth,
|
[{"xmlns", ?NS_SASL}],
|
||||||
StateData#state{sasl_state = SASLState}};
|
Mechs}]}),
|
||||||
|
{next_state, wait_for_sasl_auth,
|
||||||
|
StateData#state{sasl_state = SASLState}};
|
||||||
|
_ ->
|
||||||
|
{next_state, wait_for_session, StateData}
|
||||||
|
end;
|
||||||
_ ->
|
_ ->
|
||||||
Header = io_lib:format(
|
Header = io_lib:format(
|
||||||
?STREAM_HEADER,
|
?STREAM_HEADER,
|
||||||
|
@ -245,32 +251,37 @@ wait_for_auth(closed, StateData) ->
|
||||||
wait_for_sasl_auth({xmlstreamelement, El}, StateData) ->
|
wait_for_sasl_auth({xmlstreamelement, El}, StateData) ->
|
||||||
{xmlelement, Name, Attrs, Els} = El,
|
{xmlelement, Name, Attrs, Els} = El,
|
||||||
case {xml:get_attr_s("xmlns", Attrs), Name} of
|
case {xml:get_attr_s("xmlns", Attrs), Name} of
|
||||||
{?NS_SASL_MECHANISMS, "auth"} ->
|
{?NS_SASL, "auth"} ->
|
||||||
Mech = xml:get_attr_s("mechanism", Attrs),
|
Mech = xml:get_attr_s("mechanism", Attrs),
|
||||||
ClientIn = jlib:decode_base64(xml:get_cdata(Els)),
|
ClientIn = jlib:decode_base64(xml:get_cdata(Els)),
|
||||||
case cyrsasl:server_start(StateData#state.sasl_state,
|
case cyrsasl:server_start(StateData#state.sasl_state,
|
||||||
Mech,
|
Mech,
|
||||||
ClientIn) of
|
ClientIn) of
|
||||||
{ok, Props} ->
|
{ok, Props} ->
|
||||||
|
StateData#state.receiver ! reset_stream,
|
||||||
send_element(StateData,
|
send_element(StateData,
|
||||||
{xmlelement, "success",
|
{xmlelement, "success",
|
||||||
[{"xmlns", ?NS_SASL_MECHANISMS}], []}),
|
[{"xmlns", ?NS_SASL}], []}),
|
||||||
{next_state, wait_for_resource_auth,
|
{U, _, R} = jlib:string_to_jid(
|
||||||
StateData#state{user = xml:get_attr_s(username, Props)}};
|
xml:get_attr_s(authzid, Props)),
|
||||||
|
{next_state, wait_for_stream,
|
||||||
|
StateData#state{authentificated = true,
|
||||||
|
user = U,
|
||||||
|
resource = R
|
||||||
|
}};
|
||||||
{continue, ServerOut, NewSASLState} ->
|
{continue, ServerOut, NewSASLState} ->
|
||||||
send_element(StateData,
|
send_element(StateData,
|
||||||
{xmlelement, "challenge",
|
{xmlelement, "challenge",
|
||||||
[{"xmlns", ?NS_SASL_MECHANISMS}],
|
[{"xmlns", ?NS_SASL}],
|
||||||
[{xmlcdata,
|
[{xmlcdata,
|
||||||
jlib:encode_base64(ServerOut)}]}),
|
jlib:encode_base64(ServerOut)}]}),
|
||||||
{next_state, wait_for_sasl_response,
|
{next_state, wait_for_sasl_response,
|
||||||
StateData#state{sasl_state = NewSASLState}};
|
StateData#state{sasl_state = NewSASLState}};
|
||||||
{error, Code} ->
|
{error, Error} ->
|
||||||
send_element(StateData,
|
send_element(StateData,
|
||||||
{xmlelement, "failure",
|
{xmlelement, "failure",
|
||||||
[{"xmlns", ?NS_SASL_MECHANISMS},
|
[{"xmlns", ?NS_SASL}],
|
||||||
{"code", Code}],
|
[{xmlelement, Error, [], []}]}),
|
||||||
[]}),
|
|
||||||
{next_state, wait_for_sasl_auth, StateData}
|
{next_state, wait_for_sasl_auth, StateData}
|
||||||
end;
|
end;
|
||||||
_ ->
|
_ ->
|
||||||
|
@ -302,110 +313,38 @@ wait_for_sasl_auth(closed, StateData) ->
|
||||||
{stop, normal, StateData}.
|
{stop, normal, StateData}.
|
||||||
|
|
||||||
|
|
||||||
wait_for_resource_auth({xmlstreamelement, El}, StateData) ->
|
|
||||||
case is_auth_packet(El) of
|
|
||||||
{auth, ID, get, {"", _, _, _}} ->
|
|
||||||
Err = jlib:make_error_reply(El, ?ERR_BAD_REQUEST),
|
|
||||||
send_element(StateData, Err),
|
|
||||||
{next_state, wait_for_resource_auth, StateData};
|
|
||||||
{auth, ID, get, {U, _, _, _}} ->
|
|
||||||
{xmlelement, Name, Attrs, Els} = jlib:make_result_iq_reply(El),
|
|
||||||
Res = {xmlelement, Name, Attrs,
|
|
||||||
[{xmlelement, "query", [{"xmlns", ?NS_AUTH}],
|
|
||||||
[{xmlelement, "username", [],
|
|
||||||
[{xmlcdata, StateData#state.user}]},
|
|
||||||
{xmlelement, "resource", [], []}
|
|
||||||
]}]},
|
|
||||||
send_element(StateData, Res),
|
|
||||||
{next_state, wait_for_resource_auth, StateData};
|
|
||||||
{auth, ID, set, {U, _, _, ""}} ->
|
|
||||||
Err = jlib:make_error_reply(El, ?ERR_AUTH_NO_RESOURCE_PROVIDED),
|
|
||||||
send_element(StateData, Err),
|
|
||||||
{next_state, wait_for_resource_auth, StateData};
|
|
||||||
{auth, ID, set, {U, _, _, R}} ->
|
|
||||||
case StateData#state.user of
|
|
||||||
U ->
|
|
||||||
io:format("SASLAUTH: ~p~n", [{U, R}]),
|
|
||||||
JID = {U, ?MYNAME, R},
|
|
||||||
case acl:match_rule(StateData#state.access, JID) of
|
|
||||||
allow ->
|
|
||||||
ejabberd_sm:open_session(U, R),
|
|
||||||
Res = jlib:make_result_iq_reply(El),
|
|
||||||
send_element(StateData, Res),
|
|
||||||
change_shaper(StateData, JID),
|
|
||||||
{Fs, Ts} = mod_roster:get_subscription_lists(U),
|
|
||||||
{next_state, session_established,
|
|
||||||
StateData#state{user = U,
|
|
||||||
resource = R,
|
|
||||||
pres_f = ?SETS:from_list(Fs),
|
|
||||||
pres_t = ?SETS:from_list(Ts)}};
|
|
||||||
_ ->
|
|
||||||
Err = jlib:make_error_reply(El, ?ERR_NOT_ALLOWED),
|
|
||||||
send_element(StateData, Err),
|
|
||||||
{next_state, wait_for_resource_auth, StateData}
|
|
||||||
end;
|
|
||||||
_ ->
|
|
||||||
Err = jlib:make_error_reply(El, ?ERR_BAD_REQUEST),
|
|
||||||
send_element(StateData, Err),
|
|
||||||
{next_state, wait_for_resource_auth, StateData}
|
|
||||||
end;
|
|
||||||
_ ->
|
|
||||||
case jlib:iq_query_info(El) of
|
|
||||||
{iq, ID, Type, ?NS_REGISTER, SubEl} ->
|
|
||||||
ResIQ = mod_register:process_iq(
|
|
||||||
{"", "", ""}, {"", ?MYNAME, ""},
|
|
||||||
{iq, ID, Type, ?NS_REGISTER, SubEl}),
|
|
||||||
Res1 = jlib:replace_from_to({"", ?MYNAME, ""},
|
|
||||||
{"", "", ""},
|
|
||||||
jlib:iq_to_xml(ResIQ)),
|
|
||||||
Res = jlib:remove_attr("to", Res1),
|
|
||||||
send_element(StateData, Res),
|
|
||||||
{next_state, wait_for_resource_auth, StateData};
|
|
||||||
_ ->
|
|
||||||
{next_state, wait_for_resource_auth, StateData}
|
|
||||||
end
|
|
||||||
end;
|
|
||||||
|
|
||||||
wait_for_resource_auth({xmlstreamend, Name}, StateData) ->
|
|
||||||
send_text(StateData, ?STREAM_TRAILER),
|
|
||||||
{stop, normal, StateData};
|
|
||||||
|
|
||||||
wait_for_resource_auth({xmlstreamerror, _}, StateData) ->
|
|
||||||
send_text(StateData, ?INVALID_XML_ERR ++ ?STREAM_TRAILER),
|
|
||||||
{stop, normal, StateData};
|
|
||||||
|
|
||||||
wait_for_resource_auth(closed, StateData) ->
|
|
||||||
{stop, normal, StateData}.
|
|
||||||
|
|
||||||
|
|
||||||
% TODO: wait_for_sasl_response
|
|
||||||
wait_for_sasl_response({xmlstreamelement, El}, StateData) ->
|
wait_for_sasl_response({xmlstreamelement, El}, StateData) ->
|
||||||
{xmlelement, Name, Attrs, Els} = El,
|
{xmlelement, Name, Attrs, Els} = El,
|
||||||
case {xml:get_attr_s("xmlns", Attrs), Name} of
|
case {xml:get_attr_s("xmlns", Attrs), Name} of
|
||||||
{?NS_SASL_MECHANISMS, "response"} ->
|
{?NS_SASL, "response"} ->
|
||||||
ClientIn = jlib:decode_base64(xml:get_cdata(Els)),
|
ClientIn = jlib:decode_base64(xml:get_cdata(Els)),
|
||||||
case cyrsasl:server_step(StateData#state.sasl_state,
|
case cyrsasl:server_step(StateData#state.sasl_state,
|
||||||
ClientIn) of
|
ClientIn) of
|
||||||
{ok, Props} ->
|
{ok, Props} ->
|
||||||
|
StateData#state.receiver ! reset_stream,
|
||||||
send_element(StateData,
|
send_element(StateData,
|
||||||
{xmlelement, "success",
|
{xmlelement, "success",
|
||||||
[{"xmlns", ?NS_SASL_MECHANISMS}], []}),
|
[{"xmlns", ?NS_SASL}], []}),
|
||||||
{next_state, wait_for_resource_auth,
|
{U, _, R} = jlib:string_to_jid(
|
||||||
StateData#state{user = xml:get_attr_s(username, Props)}};
|
xml:get_attr_s(authzid, Props)),
|
||||||
|
{next_state, wait_for_stream,
|
||||||
|
StateData#state{authentificated = true,
|
||||||
|
user = U,
|
||||||
|
resource = R
|
||||||
|
}};
|
||||||
{continue, ServerOut, NewSASLState} ->
|
{continue, ServerOut, NewSASLState} ->
|
||||||
send_element(StateData,
|
send_element(StateData,
|
||||||
{xmlelement, "challenge",
|
{xmlelement, "challenge",
|
||||||
[{"xmlns", ?NS_SASL_MECHANISMS}],
|
[{"xmlns", ?NS_SASL}],
|
||||||
[{xmlcdata,
|
[{xmlcdata,
|
||||||
jlib:encode_base64(ServerOut)}]}),
|
jlib:encode_base64(ServerOut)}]}),
|
||||||
{next_state, wait_for_sasl_response,
|
{next_state, wait_for_sasl_response,
|
||||||
StateData#state{sasl_state = NewSASLState}};
|
StateData#state{sasl_state = NewSASLState}};
|
||||||
{error, Code} ->
|
{error, Error} ->
|
||||||
send_element(StateData,
|
send_element(StateData,
|
||||||
{xmlelement, "failure",
|
{xmlelement, "failure",
|
||||||
[{"xmlns", ?NS_SASL_MECHANISMS},
|
[{"xmlns", ?NS_SASL}],
|
||||||
{"code", Code}],
|
[{xmlelement, Error, [], []}]}),
|
||||||
[]}),
|
|
||||||
{next_state, wait_for_sasl_auth, StateData}
|
{next_state, wait_for_sasl_auth, StateData}
|
||||||
end;
|
end;
|
||||||
_ ->
|
_ ->
|
||||||
|
@ -438,6 +377,56 @@ wait_for_sasl_response(closed, StateData) ->
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
wait_for_session({xmlstreamelement, El}, StateData) ->
|
||||||
|
case jlib:iq_query_info(El) of
|
||||||
|
{iq, ID, set, ?NS_SESSION, SubEl} ->
|
||||||
|
U = StateData#state.user,
|
||||||
|
R = StateData#state.resource,
|
||||||
|
io:format("SASLAUTH: ~p~n", [{U, R}]),
|
||||||
|
JID = {U, ?MYNAME, R},
|
||||||
|
case acl:match_rule(StateData#state.access, JID) of
|
||||||
|
allow ->
|
||||||
|
ejabberd_sm:open_session(U, R),
|
||||||
|
Res = jlib:make_result_iq_reply(El),
|
||||||
|
send_element(StateData, Res),
|
||||||
|
change_shaper(StateData, JID),
|
||||||
|
{Fs, Ts} = mod_roster:get_subscription_lists(U),
|
||||||
|
{next_state, session_established,
|
||||||
|
StateData#state{pres_f = ?SETS:from_list(Fs),
|
||||||
|
pres_t = ?SETS:from_list(Ts)}};
|
||||||
|
_ ->
|
||||||
|
Err = jlib:make_error_reply(El, ?ERR_NOT_ALLOWED),
|
||||||
|
send_element(StateData, Err),
|
||||||
|
{next_state, wait_for_session, StateData}
|
||||||
|
end;
|
||||||
|
% TODO: is this needed?
|
||||||
|
{iq, ID, Type, ?NS_REGISTER, SubEl} ->
|
||||||
|
ResIQ = mod_register:process_iq(
|
||||||
|
{"", "", ""}, {"", ?MYNAME, ""},
|
||||||
|
{iq, ID, Type, ?NS_REGISTER, SubEl}),
|
||||||
|
Res1 = jlib:replace_from_to({"", ?MYNAME, ""},
|
||||||
|
{"", "", ""},
|
||||||
|
jlib:iq_to_xml(ResIQ)),
|
||||||
|
Res = jlib:remove_attr("to", Res1),
|
||||||
|
send_element(StateData, Res),
|
||||||
|
{next_state, wait_for_session, StateData};
|
||||||
|
_ ->
|
||||||
|
{next_state, wait_for_session, StateData}
|
||||||
|
end;
|
||||||
|
|
||||||
|
wait_for_session({xmlstreamend, Name}, StateData) ->
|
||||||
|
send_text(StateData, ?STREAM_TRAILER),
|
||||||
|
{stop, normal, StateData};
|
||||||
|
|
||||||
|
wait_for_session({xmlstreamerror, _}, StateData) ->
|
||||||
|
send_text(StateData, ?INVALID_XML_ERR ++ ?STREAM_TRAILER),
|
||||||
|
{stop, normal, StateData};
|
||||||
|
|
||||||
|
wait_for_session(closed, StateData) ->
|
||||||
|
{stop, normal, StateData}.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
session_established({xmlstreamelement, El}, StateData) ->
|
session_established({xmlstreamelement, El}, StateData) ->
|
||||||
{xmlelement, Name, Attrs, Els} = El,
|
{xmlelement, Name, Attrs, Els} = El,
|
||||||
|
@ -659,8 +648,15 @@ receiver(Socket, SockMod, ShaperState, C2SPid, XMLStreamPid, Timeout) ->
|
||||||
ShaperState
|
ShaperState
|
||||||
end,
|
end,
|
||||||
NewShaperState = shaper:update(ShaperSt1, size(Text)),
|
NewShaperState = shaper:update(ShaperSt1, size(Text)),
|
||||||
xml_stream:send_text(XMLStreamPid, Text),
|
XMLStreamPid1 = receive
|
||||||
receiver(Socket, SockMod, NewShaperState, C2SPid, XMLStreamPid,
|
reset_stream ->
|
||||||
|
exit(XMLStreamPid, closed),
|
||||||
|
xml_stream:start(C2SPid)
|
||||||
|
after 0 ->
|
||||||
|
XMLStreamPid
|
||||||
|
end,
|
||||||
|
xml_stream:send_text(XMLStreamPid1, Text),
|
||||||
|
receiver(Socket, SockMod, NewShaperState, C2SPid, XMLStreamPid1,
|
||||||
Timeout);
|
Timeout);
|
||||||
{error, timeout} ->
|
{error, timeout} ->
|
||||||
receiver(Socket, SockMod, ShaperState, C2SPid, XMLStreamPid,
|
receiver(Socket, SockMod, ShaperState, C2SPid, XMLStreamPid,
|
||||||
|
|
|
@ -32,7 +32,8 @@
|
||||||
-define(NS_STANZAS, "urn:ietf:params:xml:ns:xmpp-stanzas").
|
-define(NS_STANZAS, "urn:ietf:params:xml:ns:xmpp-stanzas").
|
||||||
-define(NS_STREAMS, "urn:ietf:params:xml:ns:xmpp-streams").
|
-define(NS_STREAMS, "urn:ietf:params:xml:ns:xmpp-streams").
|
||||||
|
|
||||||
-define(NS_SASL_MECHANISMS, "urn:ietf:params:xml:ns:xmpp-sasl").
|
-define(NS_SASL, "urn:ietf:params:xml:ns:xmpp-sasl").
|
||||||
|
-define(NS_SESSION, "urn:ietf:params:xml:ns:xmpp-session").
|
||||||
|
|
||||||
% TODO: remove "code" attribute (currently it used for backward-compatibility)
|
% TODO: remove "code" attribute (currently it used for backward-compatibility)
|
||||||
-define(STANZA_ERROR(Code, Class, Condition),
|
-define(STANZA_ERROR(Code, Class, Condition),
|
||||||
|
|
Loading…
Reference in New Issue