]> granicus.if.org Git - ejabberd/commitdiff
* src/tls/tls.erl: Added recv_data/2 function
authorAlexey Shchepin <alexey@process-one.net>
Sun, 1 Aug 2004 20:12:20 +0000 (20:12 +0000)
committerAlexey Shchepin <alexey@process-one.net>
Sun, 1 Aug 2004 20:12:20 +0000 (20:12 +0000)
* src/jlib.erl: Added NS_TLS macro

* src/ejabberd_receiver.erl: Support for STARTTLS
* src/ejabberd_c2s.erl: Likewise

SVN Revision: 252

ChangeLog
src/ejabberd_c2s.erl
src/ejabberd_receiver.erl
src/jlib.hrl
src/tls/tls.erl

index 98386a68f776a734f2ed4cd6aa13a64a8a370bcb..9f00cb1068061df69b36b7c6c45dc5a12393f8e3 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2004-08-01  Alexey Shchepin  <alexey@sevcom.net>
+
+       * src/tls/tls.erl: Added recv_data/2 function
+
+       * src/jlib.erl: Added NS_TLS macro
+
+       * src/ejabberd_receiver.erl: Support for STARTTLS
+       * src/ejabberd_c2s.erl: Likewise
+
 2004-07-30  Alexey Shchepin  <alexey@sevcom.net>
 
        * examples/extauth/check_pass_null.pl: A reference "null"
index a920597f4b2e0ee85be2782138fda059061ce9c6..b5b3128dad18d51ca39db0af1aa2588b6dd35bb9 100644 (file)
@@ -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;
 
index 308d1b94cb72149ee5cf720940974e3a608a36c0..8217bb7e845a40934d211aacb485e9d112be04f1 100644 (file)
@@ -13,7 +13,8 @@
 -export([start/3,
         receiver/4,
         change_shaper/2,
-        reset_stream/1]).
+        reset_stream/1,
+        starttls/2]).
 
 -include("ejabberd.hrl").
 
@@ -34,7 +35,30 @@ receiver(Socket, SockMod, Shaper, C2SPid) ->
     receiver(Socket, SockMod, ShaperState, C2SPid, XMLStreamPid, Timeout).
 
 receiver(Socket, SockMod, ShaperState, C2SPid, XMLStreamPid, Timeout) ->
-    case catch SockMod:recv(Socket, 0, Timeout) of
+    Res = (catch SockMod:recv(Socket, 0, Timeout)),
+    case Res of
+        {ok, Data} ->
+           receive
+               {starttls, TLSSocket} ->
+                   exit(XMLStreamPid, closed),
+                   XMLStreamPid1 = xml_stream:start(self(), C2SPid),
+                   TLSRes = tls:recv_data(TLSSocket, Data),
+                   receiver1(TLSSocket, tls,
+                             ShaperState, C2SPid, XMLStreamPid1, Timeout,
+                             TLSRes)
+           after 0 ->
+                   receiver1(Socket, SockMod,
+                             ShaperState, C2SPid, XMLStreamPid, Timeout,
+                             Res)
+           end;
+       _ ->
+           receiver1(Socket, SockMod,
+                     ShaperState, C2SPid, XMLStreamPid, Timeout, Res)
+    end.
+
+
+receiver1(Socket, SockMod, ShaperState, C2SPid, XMLStreamPid, Timeout, Res) ->
+    case Res of
         {ok, Text} ->
            ShaperSt1 = receive
                            {change_shaper, Shaper} ->
@@ -75,4 +99,7 @@ change_shaper(Pid, Shaper) ->
 reset_stream(Pid) ->
     Pid ! reset_stream.
 
+starttls(Pid, TLSSocket) ->
+    Pid ! {starttls, TLSSocket}.
+
 
index 29afc3dc4d9229289857335de01821f23978e11c..c684a7f3bd0c61932364bdb7e55d1a7d1a09ab87 100644 (file)
@@ -40,6 +40,7 @@
 -define(NS_STANZAS,      "urn:ietf:params:xml:ns:xmpp-stanzas").
 -define(NS_STREAMS,      "urn:ietf:params:xml:ns:xmpp-streams").
 
+-define(NS_TLS,          "urn:ietf:params:xml:ns:xmpp-tls").
 -define(NS_SASL,         "urn:ietf:params:xml:ns:xmpp-sasl").
 -define(NS_SESSION,      "urn:ietf:params:xml:ns:xmpp-session").
 -define(NS_BIND,         "urn:ietf:params:xml:ns:xmpp-bind").
index edf94a1692f2c00e7115d0fda778d95de6c7ddf3..361c92fcfb9731b498bcf5720d60895f3a3a4db9 100644 (file)
@@ -15,7 +15,7 @@
 -export([start/0, start_link/0,
         tcp_to_tls/2, tls_to_tcp/1,
         send/2,
-        recv/2, recv/3,
+        recv/2, recv/3, recv_data/2,
         close/1,
         test/0]).
 
@@ -86,7 +86,6 @@ tcp_to_tls(TCPSocket, Options) ->
        {value, {certfile, CertFile}} ->
            ok = erl_ddll:load_driver(ejabberd:get_so_path(), tls_drv),
            Port = open_port({spawn, tls_drv}, [binary]),
-           io:format("open_port: ~p~n", [Port]),
            case port_control(Port, ?SET_CERTIFICATE_FILE,
                              CertFile ++ [0]) of
                <<0>> ->
@@ -104,23 +103,27 @@ tls_to_tcp(#tlssock{tcpsock = TCPSocket, tlsport = Port}) ->
 
 recv(Socket, Length) ->
     recv(Socket, Length, infinity).
-recv(#tlssock{tcpsock = TCPSocket, tlsport = Port}, Length, Timeout) ->
+recv(#tlssock{tcpsock = TCPSocket, tlsport = Port} = TLSSock,
+     Length, Timeout) ->
     case gen_tcp:recv(TCPSocket, Length, Timeout) of
        {ok, Packet} ->
-           case port_control(Port, ?SET_ENCRYPTED_INPUT, Packet) of
-               <<0>> ->
-                   case port_control(Port, ?GET_DECRYPTED_INPUT, []) of
-                       <<0, In/binary>> ->
-                           case port_control(Port, ?GET_ENCRYPTED_OUTPUT, []) of
-                               <<0, Out/binary>> ->
-                                   case gen_tcp:send(TCPSocket, Out) of
-                                       ok ->
-                                           {ok, In};
-                                       Error ->
-                                           Error
-                                   end;
-                               <<1, Error/binary>> ->
-                                   {error, binary_to_list(Error)}
+           recv_data(TLSSock, Packet);
+       {error, _Reason} = Error ->
+           Error
+    end.
+
+recv_data(#tlssock{tcpsock = TCPSocket, tlsport = Port}, Packet) ->
+    case port_control(Port, ?SET_ENCRYPTED_INPUT, Packet) of
+       <<0>> ->
+           case port_control(Port, ?GET_DECRYPTED_INPUT, []) of
+               <<0, In/binary>> ->
+                   case port_control(Port, ?GET_ENCRYPTED_OUTPUT, []) of
+                       <<0, Out/binary>> ->
+                           case gen_tcp:send(TCPSocket, Out) of
+                               ok ->
+                                   {ok, In};
+                               Error ->
+                                   Error
                            end;
                        <<1, Error/binary>> ->
                            {error, binary_to_list(Error)}
@@ -128,8 +131,8 @@ recv(#tlssock{tcpsock = TCPSocket, tlsport = Port}, Length, Timeout) ->
                <<1, Error/binary>> ->
                    {error, binary_to_list(Error)}
            end;
-       {error, _Reason} = Error ->
-           Error
+       <<1, Error/binary>> ->
+           {error, binary_to_list(Error)}
     end.
 
 send(#tlssock{tcpsock = TCPSocket, tlsport = Port}, Packet) ->