summaryrefslogtreecommitdiff
path: root/src/ejabberd_c2s.erl
diff options
context:
space:
mode:
Diffstat (limited to 'src/ejabberd_c2s.erl')
-rw-r--r--src/ejabberd_c2s.erl55
1 files changed, 43 insertions, 12 deletions
diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl
index a920597f..b5b3128d 100644
--- a/src/ejabberd_c2s.erl
+++ b/src/ejabberd_c2s.erl
@@ -23,7 +23,7 @@
-export([init/1,
wait_for_stream/2,
wait_for_auth/2,
- wait_for_sasl_auth/2,
+ wait_for_feature_request/2,
wait_for_bind/2,
wait_for_session/2,
wait_for_sasl_response/2,
@@ -178,12 +178,26 @@ wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData) ->
{xmlelement, "mechanism", [],
[{xmlcdata, S}]}
end, cyrsasl:listmech()),
+ TLS = StateData#state.tls,
+ TLSEnabled = StateData#state.tls_enabled,
+ SockMod = StateData#state.sockmod,
+ TLSFeature =
+ case (TLS == true) andalso
+ (TLSEnabled == false) andalso
+ (SockMod == gen_tcp) of
+ true ->
+ [{xmlelement, "starttls",
+ [{"xmlns", ?NS_TLS}], []}];
+ false ->
+ []
+ end,
send_element(StateData,
{xmlelement, "stream:features", [],
+ TLSFeature ++
[{xmlelement, "mechanisms",
[{"xmlns", ?NS_SASL}],
Mechs}]}),
- {next_state, wait_for_sasl_auth,
+ {next_state, wait_for_feature_request,
StateData#state{sasl_state = SASLState,
lang = Lang}};
_ ->
@@ -357,8 +371,11 @@ wait_for_auth(closed, StateData) ->
{stop, normal, StateData}.
-wait_for_sasl_auth({xmlstreamelement, El}, StateData) ->
+wait_for_feature_request({xmlstreamelement, El}, StateData) ->
{xmlelement, Name, Attrs, Els} = El,
+ TLS = StateData#state.tls,
+ TLSEnabled = StateData#state.tls_enabled,
+ SockMod = StateData#state.sockmod,
case {xml:get_attr_s("xmlns", Attrs), Name} of
{?NS_SASL, "auth"} ->
Mech = xml:get_attr_s("mechanism", Attrs),
@@ -391,8 +408,22 @@ wait_for_sasl_auth({xmlstreamelement, El}, StateData) ->
{xmlelement, "failure",
[{"xmlns", ?NS_SASL}],
[{xmlelement, Error, [], []}]}),
- {next_state, wait_for_sasl_auth, StateData}
+ {next_state, wait_for_feature_request, StateData}
end;
+ {?NS_TLS, "starttls"} when TLS == true,
+ TLSEnabled == false,
+ SockMod == gen_tcp ->
+ Socket = StateData#state.socket,
+ TLSOpts = StateData#state.tls_options,
+ {ok, TLSSocket} = tls:tcp_to_tls(Socket, TLSOpts),
+ ejabberd_receiver:starttls(StateData#state.receiver, TLSSocket),
+ send_element(StateData,
+ {xmlelement, "proceed", [{"xmlns", ?NS_TLS}], []}),
+ {next_state, wait_for_stream,
+ StateData#state{sockmod = tls,
+ socket = TLSSocket,
+ tls_enabled = true
+ }};
_ ->
case jlib:iq_query_info(El) of
#iq{xmlns = ?NS_REGISTER} = IQ ->
@@ -403,21 +434,21 @@ wait_for_sasl_auth({xmlstreamelement, El}, StateData) ->
jlib:iq_to_xml(ResIQ)),
Res = jlib:remove_attr("to", Res1),
send_element(StateData, Res),
- {next_state, wait_for_sasl_auth, StateData};
+ {next_state, wait_for_feature_request, StateData};
_ ->
- {next_state, wait_for_sasl_auth, StateData}
+ {next_state, wait_for_feature_request, StateData}
end
end;
-wait_for_sasl_auth({xmlstreamend, _Name}, StateData) ->
+wait_for_feature_request({xmlstreamend, _Name}, StateData) ->
send_text(StateData, ?STREAM_TRAILER),
{stop, normal, StateData};
-wait_for_sasl_auth({xmlstreamerror, _}, StateData) ->
+wait_for_feature_request({xmlstreamerror, _}, StateData) ->
send_text(StateData, ?INVALID_XML_ERR ++ ?STREAM_TRAILER),
{stop, normal, StateData};
-wait_for_sasl_auth(closed, StateData) ->
+wait_for_feature_request(closed, StateData) ->
{stop, normal, StateData}.
@@ -453,7 +484,7 @@ wait_for_sasl_response({xmlstreamelement, El}, StateData) ->
{xmlelement, "failure",
[{"xmlns", ?NS_SASL}],
[{xmlelement, Error, [], []}]}),
- {next_state, wait_for_sasl_auth, StateData}
+ {next_state, wait_for_feature_request, StateData}
end;
_ ->
case jlib:iq_query_info(El) of
@@ -465,9 +496,9 @@ wait_for_sasl_response({xmlstreamelement, El}, StateData) ->
jlib:iq_to_xml(ResIQ)),
Res = jlib:remove_attr("to", Res1),
send_element(StateData, Res),
- {next_state, wait_for_sasl_auth, StateData};
+ {next_state, wait_for_feature_request, StateData};
_ ->
- {next_state, wait_for_sasl_auth, StateData}
+ {next_state, wait_for_feature_request, StateData}
end
end;