25
1
mirror of https://github.com/processone/ejabberd.git synced 2024-12-22 17:28:25 +01:00

* src/ejabberd_c2s.erl: Implements timeouts during session opening negociation (EJAB-355).

SVN Revision: 933
This commit is contained in:
Mickaël Rémond 2007-09-14 14:17:42 +00:00
parent 7146a52a84
commit f787a3ed71

View File

@ -84,6 +84,10 @@
[SockData, Opts])). [SockData, Opts])).
-endif. -endif.
%% This is the timeout to apply between event when starting a new
%% session:
-define(C2S_OPEN_TIMEOUT, 5000).
-define(STREAM_HEADER, -define(STREAM_HEADER,
"<?xml version='1.0'?>" "<?xml version='1.0'?>"
"<stream:stream xmlns='jabber:client' " "<stream:stream xmlns='jabber:client' "
@ -166,7 +170,7 @@ init([{SockMod, Socket}, Opts]) ->
streamid = new_id(), streamid = new_id(),
access = Access, access = Access,
shaper = Shaper, shaper = Shaper,
ip = IP}}. ip = IP}, ?C2S_OPEN_TIMEOUT}.
%%---------------------------------------------------------------------- %%----------------------------------------------------------------------
@ -265,7 +269,8 @@ wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData) ->
{next_state, wait_for_feature_request, {next_state, wait_for_feature_request,
StateData#state{server = Server, StateData#state{server = Server,
sasl_state = SASLState, sasl_state = SASLState,
lang = Lang}}; lang = Lang},
?C2S_OPEN_TIMEOUT};
_ -> _ ->
case StateData#state.resource of case StateData#state.resource of
"" -> "" ->
@ -278,7 +283,8 @@ wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData) ->
[{"xmlns", ?NS_SESSION}], []}]}), [{"xmlns", ?NS_SESSION}], []}]}),
{next_state, wait_for_bind, {next_state, wait_for_bind,
StateData#state{server = Server, StateData#state{server = Server,
lang = Lang}}; lang = Lang},
?C2S_OPEN_TIMEOUT};
_ -> _ ->
send_element( send_element(
StateData, StateData,
@ -328,6 +334,9 @@ wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData) ->
{stop, normal, StateData} {stop, normal, StateData}
end; end;
wait_for_stream(timeout, StateData) ->
{stop, normal, StateData};
wait_for_stream({xmlstreamelement, _}, StateData) -> wait_for_stream({xmlstreamelement, _}, StateData) ->
send_text(StateData, ?INVALID_XML_ERR ++ ?STREAM_TRAILER), send_text(StateData, ?INVALID_XML_ERR ++ ?STREAM_TRAILER),
{stop, normal, StateData}; {stop, normal, StateData};
@ -376,13 +385,13 @@ wait_for_auth({xmlstreamelement, El}, StateData) ->
]}]} ]}]}
end, end,
send_element(StateData, Res), send_element(StateData, Res),
{next_state, wait_for_auth, StateData}; {next_state, wait_for_auth, StateData, ?C2S_OPEN_TIMEOUT};
{auth, _ID, set, {_U, _P, _D, ""}} -> {auth, _ID, set, {_U, _P, _D, ""}} ->
Err = jlib:make_error_reply( Err = jlib:make_error_reply(
El, El,
?ERR_AUTH_NO_RESOURCE_PROVIDED(StateData#state.lang)), ?ERR_AUTH_NO_RESOURCE_PROVIDED(StateData#state.lang)),
send_element(StateData, Err), send_element(StateData, Err),
{next_state, wait_for_auth, StateData}; {next_state, wait_for_auth, StateData, ?C2S_OPEN_TIMEOUT};
{auth, _ID, set, {U, P, D, R}} -> {auth, _ID, set, {U, P, D, R}} ->
JID = jlib:make_jid(U, StateData#state.server, R), JID = jlib:make_jid(U, StateData#state.server, R),
case (JID /= error) andalso case (JID /= error) andalso
@ -435,7 +444,8 @@ wait_for_auth({xmlstreamelement, El}, StateData) ->
Err = jlib:make_error_reply( Err = jlib:make_error_reply(
El, ?ERR_NOT_AUTHORIZED), El, ?ERR_NOT_AUTHORIZED),
send_element(StateData, Err), send_element(StateData, Err),
{next_state, wait_for_auth, StateData} {next_state, wait_for_auth, StateData,
?C2S_OPEN_TIMEOUT}
end; end;
_ -> _ ->
if if
@ -446,7 +456,8 @@ wait_for_auth({xmlstreamelement, El}, StateData) ->
[StateData#state.socket, U, R]), [StateData#state.socket, U, R]),
Err = jlib:make_error_reply(El, ?ERR_JID_MALFORMED), Err = jlib:make_error_reply(El, ?ERR_JID_MALFORMED),
send_element(StateData, Err), send_element(StateData, Err),
{next_state, wait_for_auth, StateData}; {next_state, wait_for_auth, StateData,
?C2S_OPEN_TIMEOUT};
true -> true ->
?INFO_MSG( ?INFO_MSG(
"(~w) Forbidden legacy authentication for ~s", "(~w) Forbidden legacy authentication for ~s",
@ -454,14 +465,18 @@ wait_for_auth({xmlstreamelement, El}, StateData) ->
jlib:jid_to_string(JID)]), jlib:jid_to_string(JID)]),
Err = jlib:make_error_reply(El, ?ERR_NOT_ALLOWED), Err = jlib:make_error_reply(El, ?ERR_NOT_ALLOWED),
send_element(StateData, Err), send_element(StateData, Err),
{next_state, wait_for_auth, StateData} {next_state, wait_for_auth, StateData,
?C2S_OPEN_TIMEOUT}
end end
end; end;
_ -> _ ->
process_unauthenticated_stanza(StateData, El), process_unauthenticated_stanza(StateData, El),
{next_state, wait_for_auth, StateData} {next_state, wait_for_auth, StateData, ?C2S_OPEN_TIMEOUT}
end; end;
wait_for_auth(timeout, StateData) ->
{stop, normal, StateData};
wait_for_auth({xmlstreamend, _Name}, StateData) -> wait_for_auth({xmlstreamend, _Name}, StateData) ->
send_text(StateData, ?STREAM_TRAILER), send_text(StateData, ?STREAM_TRAILER),
{stop, normal, StateData}; {stop, normal, StateData};
@ -501,7 +516,7 @@ wait_for_feature_request({xmlstreamelement, El}, StateData) ->
StateData#state{streamid = new_id(), StateData#state{streamid = new_id(),
authenticated = true, authenticated = true,
user = U user = U
}}; }, ?C2S_OPEN_TIMEOUT};
{continue, ServerOut, NewSASLState} -> {continue, ServerOut, NewSASLState} ->
send_element(StateData, send_element(StateData,
{xmlelement, "challenge", {xmlelement, "challenge",
@ -509,7 +524,8 @@ wait_for_feature_request({xmlstreamelement, El}, StateData) ->
[{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},
?C2S_OPEN_TIMEOUT};
{error, Error, Username} -> {error, Error, Username} ->
?INFO_MSG( ?INFO_MSG(
"(~w) Failed authentication for ~s@~s", "(~w) Failed authentication for ~s@~s",
@ -519,13 +535,15 @@ wait_for_feature_request({xmlstreamelement, El}, StateData) ->
{xmlelement, "failure", {xmlelement, "failure",
[{"xmlns", ?NS_SASL}], [{"xmlns", ?NS_SASL}],
[{xmlelement, Error, [], []}]}), [{xmlelement, Error, [], []}]}),
{next_state, wait_for_feature_request, StateData}; {next_state, wait_for_feature_request, StateData,
?C2S_OPEN_TIMEOUT};
{error, Error} -> {error, Error} ->
send_element(StateData, send_element(StateData,
{xmlelement, "failure", {xmlelement, "failure",
[{"xmlns", ?NS_SASL}], [{"xmlns", ?NS_SASL}],
[{xmlelement, Error, [], []}]}), [{xmlelement, Error, [], []}]}),
{next_state, wait_for_feature_request, StateData} {next_state, wait_for_feature_request, StateData,
?C2S_OPEN_TIMEOUT}
end; end;
{?NS_TLS, "starttls"} when TLS == true, {?NS_TLS, "starttls"} when TLS == true,
TLSEnabled == false, TLSEnabled == false,
@ -548,7 +566,7 @@ wait_for_feature_request({xmlstreamelement, El}, StateData) ->
StateData#state{socket = TLSSocket, StateData#state{socket = TLSSocket,
streamid = new_id(), streamid = new_id(),
tls_enabled = true tls_enabled = true
}}; }, ?C2S_OPEN_TIMEOUT};
{?NS_COMPRESS, "compress"} when Zlib == true, {?NS_COMPRESS, "compress"} when Zlib == true,
SockMod == gen_tcp -> SockMod == gen_tcp ->
case xml:get_subtag(El, "method") of case xml:get_subtag(El, "method") of
@ -557,7 +575,8 @@ wait_for_feature_request({xmlstreamelement, El}, StateData) ->
{xmlelement, "failure", {xmlelement, "failure",
[{"xmlns", ?NS_COMPRESS}], [{"xmlns", ?NS_COMPRESS}],
[{xmlelement, "setup-failed", [], []}]}), [{xmlelement, "setup-failed", [], []}]}),
{next_state, wait_for_feature_request, StateData}; {next_state, wait_for_feature_request, StateData,
?C2S_OPEN_TIMEOUT};
Method -> Method ->
case xml:get_tag_cdata(Method) of case xml:get_tag_cdata(Method) of
"zlib" -> "zlib" ->
@ -570,14 +589,15 @@ wait_for_feature_request({xmlstreamelement, El}, StateData) ->
{next_state, wait_for_stream, {next_state, wait_for_stream,
StateData#state{socket = ZlibSocket, StateData#state{socket = ZlibSocket,
streamid = new_id() streamid = new_id()
}}; }, ?C2S_OPEN_TIMEOUT};
_ -> _ ->
send_element(StateData, send_element(StateData,
{xmlelement, "failure", {xmlelement, "failure",
[{"xmlns", ?NS_COMPRESS}], [{"xmlns", ?NS_COMPRESS}],
[{xmlelement, "unsupported-method", [{xmlelement, "unsupported-method",
[], []}]}), [], []}]}),
{next_state, wait_for_feature_request, StateData} {next_state, wait_for_feature_request, StateData,
?C2S_OPEN_TIMEOUT}
end end
end; end;
_ -> _ ->
@ -591,10 +611,14 @@ wait_for_feature_request({xmlstreamelement, El}, StateData) ->
{stop, normal, StateData}; {stop, normal, StateData};
true -> true ->
process_unauthenticated_stanza(StateData, El), process_unauthenticated_stanza(StateData, El),
{next_state, wait_for_feature_request, StateData} {next_state, wait_for_feature_request, StateData,
?C2S_OPEN_TIMEOUT}
end end
end; end;
wait_for_feature_request(timeout, StateData) ->
{stop, normal, StateData};
wait_for_feature_request({xmlstreamend, _Name}, StateData) -> wait_for_feature_request({xmlstreamend, _Name}, StateData) ->
send_text(StateData, ?STREAM_TRAILER), send_text(StateData, ?STREAM_TRAILER),
{stop, normal, StateData}; {stop, normal, StateData};
@ -627,7 +651,7 @@ wait_for_sasl_response({xmlstreamelement, El}, StateData) ->
StateData#state{streamid = new_id(), StateData#state{streamid = new_id(),
authenticated = true, authenticated = true,
user = U user = U
}}; }, ?C2S_OPEN_TIMEOUT};
{continue, ServerOut, NewSASLState} -> {continue, ServerOut, NewSASLState} ->
send_element(StateData, send_element(StateData,
{xmlelement, "challenge", {xmlelement, "challenge",
@ -645,19 +669,25 @@ wait_for_sasl_response({xmlstreamelement, El}, StateData) ->
{xmlelement, "failure", {xmlelement, "failure",
[{"xmlns", ?NS_SASL}], [{"xmlns", ?NS_SASL}],
[{xmlelement, Error, [], []}]}), [{xmlelement, Error, [], []}]}),
{next_state, wait_for_feature_request, StateData}; {next_state, wait_for_feature_request, StateData,
?C2S_OPEN_TIMEOUT};
{error, Error} -> {error, Error} ->
send_element(StateData, send_element(StateData,
{xmlelement, "failure", {xmlelement, "failure",
[{"xmlns", ?NS_SASL}], [{"xmlns", ?NS_SASL}],
[{xmlelement, Error, [], []}]}), [{xmlelement, Error, [], []}]}),
{next_state, wait_for_feature_request, StateData} {next_state, wait_for_feature_request, StateData,
?C2S_OPEN_TIMEOUT}
end; end;
_ -> _ ->
process_unauthenticated_stanza(StateData, El), process_unauthenticated_stanza(StateData, El),
{next_state, wait_for_feature_request, StateData} {next_state, wait_for_feature_request, StateData,
?C2S_OPEN_TIMEOUT}
end; end;
wait_for_sasl_response(timeout, StateData) ->
{stop, normal, StateData};
wait_for_sasl_response({xmlstreamend, _Name}, StateData) -> wait_for_sasl_response({xmlstreamend, _Name}, StateData) ->
send_text(StateData, ?STREAM_TRAILER), send_text(StateData, ?STREAM_TRAILER),
{stop, normal, StateData}; {stop, normal, StateData};
@ -687,7 +717,7 @@ wait_for_bind({xmlstreamelement, El}, StateData) ->
error -> error ->
Err = jlib:make_error_reply(El, ?ERR_BAD_REQUEST), Err = jlib:make_error_reply(El, ?ERR_BAD_REQUEST),
send_element(StateData, Err), send_element(StateData, Err),
{next_state, wait_for_bind, StateData}; {next_state, wait_for_bind, StateData, ?C2S_OPEN_TIMEOUT};
_ -> _ ->
JID = jlib:make_jid(U, StateData#state.server, R), JID = jlib:make_jid(U, StateData#state.server, R),
Res = IQ#iq{type = result, Res = IQ#iq{type = result,
@ -698,12 +728,16 @@ wait_for_bind({xmlstreamelement, El}, StateData) ->
jlib:jid_to_string(JID)}]}]}]}, jlib:jid_to_string(JID)}]}]}]},
send_element(StateData, jlib:iq_to_xml(Res)), send_element(StateData, jlib:iq_to_xml(Res)),
{next_state, wait_for_session, {next_state, wait_for_session,
StateData#state{resource = R, jid = JID}} StateData#state{resource = R, jid = JID},
?C2S_OPEN_TIMEOUT}
end; end;
_ -> _ ->
{next_state, wait_for_bind, StateData} {next_state, wait_for_bind, StateData, ?C2S_OPEN_TIMEOUT}
end; end;
wait_for_bind(timeout, StateData) ->
{stop, normal, StateData};
wait_for_bind({xmlstreamend, _Name}, StateData) -> wait_for_bind({xmlstreamend, _Name}, StateData) ->
send_text(StateData, ?STREAM_TRAILER), send_text(StateData, ?STREAM_TRAILER),
{stop, normal, StateData}; {stop, normal, StateData};
@ -760,12 +794,16 @@ wait_for_session({xmlstreamelement, El}, StateData) ->
jlib:jid_to_string(JID)]), jlib:jid_to_string(JID)]),
Err = jlib:make_error_reply(El, ?ERR_NOT_ALLOWED), Err = jlib:make_error_reply(El, ?ERR_NOT_ALLOWED),
send_element(StateData, Err), send_element(StateData, Err),
{next_state, wait_for_session, StateData} {next_state, wait_for_session, StateData,
?C2S_OPEN_TIMEOUT}
end; end;
_ -> _ ->
{next_state, wait_for_session, StateData} {next_state, wait_for_session, StateData, ?C2S_OPEN_TIMEOUT}
end; end;
wait_for_session(timeout, StateData) ->
{stop, normal, StateData};
wait_for_session({xmlstreamend, _Name}, StateData) -> wait_for_session({xmlstreamend, _Name}, StateData) ->
send_text(StateData, ?STREAM_TRAILER), send_text(StateData, ?STREAM_TRAILER),
{stop, normal, StateData}; {stop, normal, StateData};