]> granicus.if.org Git - ejabberd/commitdiff
* src/ejabberd_c2s.erl: Enforce client stanza from attribute (EJAB-812).
authorMickaël Rémond <mickael.remond@process-one.net>
Mon, 8 Dec 2008 09:21:36 +0000 (09:21 +0000)
committerMickaël Rémond <mickael.remond@process-one.net>
Mon, 8 Dec 2008 09:21:36 +0000 (09:21 +0000)
* src/jlib.erl: Likewise.

SVN Revision: 1706

ChangeLog
src/ejabberd_c2s.erl
src/jlib.erl

index 2aea5671841d603135833318d74e78052923c3f4..823b6bc7bfaa88a23bd5ee3358f40c900ac6dc94 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2008-12-08  Mickael Remond  <mremond@process-one.net>
+
+       * src/ejabberd_c2s.erl: Enforce client stanza from attribute
+       (EJAB-812).
+       * src/jlib.erl: Likewise.
+
 2008-12-02  Badlop  <badlop@process-one.net>
 
        * src/mod_muc/mod_muc_room.erl: Move definitions to header file
index 5b08d1e3547269e84fc58ce66a52d3d127b2f1b3..fb93d8ddeda46769f68590581f58cd8d66b571f6 100644 (file)
        xml:element_to_string(?SERR_HOST_UNKNOWN)).
 -define(POLICY_VIOLATION_ERR(Lang, Text),
        xml:element_to_string(?SERRT_POLICY_VIOLATION(Lang, Text))).
+-define(INVALID_FROM,
+       xml:element_to_string(?SERR_INVALID_FROM)).
+
 
 %%%----------------------------------------------------------------------
 %%% API
@@ -868,10 +871,41 @@ wait_for_session(closed, StateData) ->
 
 
 session_established({xmlstreamelement, El}, StateData) ->
+    FromJID = StateData#state.jid,
+    % Check 'from' attribute in stanza RFC 3920 Section 9.1.2
+    case check_from(El, FromJID) of
+       'invalid-from' ->
+           send_text(StateData, ?INVALID_FROM ++ ?STREAM_TRAILER),
+           {stop, normal, StateData};
+       _NewEl ->
+           session_established2(El, StateData)
+    end;
+
+%% We hibernate the process to reduce memory consumption after a
+%% configurable activity timeout
+session_established(timeout, StateData) ->
+    %% TODO: Options must be stored in state:
+    Options = [],
+    proc_lib:hibernate(gen_fsm, enter_loop,
+                      [?MODULE, Options, session_established, StateData]),
+    fsm_next_state(session_established, StateData);
+
+session_established({xmlstreamend, _Name}, StateData) ->
+    send_text(StateData, ?STREAM_TRAILER),
+    {stop, normal, StateData};
+
+session_established({xmlstreamerror, _}, StateData) ->
+    send_text(StateData, ?INVALID_XML_ERR ++ ?STREAM_TRAILER),
+    {stop, normal, StateData};
+
+session_established(closed, StateData) ->
+    {stop, normal, StateData}.
+
+
+session_established2(El, StateData) ->
     {xmlelement, Name, Attrs, _Els} = El,
     User = StateData#state.user,
     Server = StateData#state.server,
-    % TODO: check 'from' attribute in stanza
     FromJID = StateData#state.jid,
     To = xml:get_attr_s("to", Attrs),
     ToJID = case To of
@@ -951,27 +985,7 @@ session_established({xmlstreamelement, El}, StateData) ->
                end
        end,
     ejabberd_hooks:run(c2s_loop_debug, [{xmlstreamelement, El}]),
-    fsm_next_state(session_established, NewState);
-
-%% We hibernate the process to reduce memory consumption after a
-%% configurable activity timeout
-session_established(timeout, StateData) ->
-    %% TODO: Options must be stored in state:
-    Options = [],
-    proc_lib:hibernate(gen_fsm, enter_loop,
-                      [?MODULE, Options, session_established, StateData]),
-    fsm_next_state(session_established, StateData);
-
-session_established({xmlstreamend, _Name}, StateData) ->
-    send_text(StateData, ?STREAM_TRAILER),
-    {stop, normal, StateData};
-
-session_established({xmlstreamerror, _}, StateData) ->
-    send_text(StateData, ?INVALID_XML_ERR ++ ?STREAM_TRAILER),
-    {stop, normal, StateData};
-
-session_established(closed, StateData) ->
-    {stop, normal, StateData}.
+    fsm_next_state(session_established, NewState).
 
 
 
@@ -1994,3 +2008,32 @@ fsm_reply(Reply, StateName, StateData) ->
 %% Used by c2s blacklist plugins
 is_ip_blacklisted({IP,_Port}) ->
     ejabberd_hooks:run_fold(check_bl_c2s, false, [IP]).        
+
+%% Check from attributes
+%% returns invalid-from|NewElement
+check_from(El, FromJID) ->
+    case xml:get_tag_attr("from", El) of
+       false ->
+           jlib:replace_from(FromJID, El);
+       {value, JIDElString} ->
+           JIDEl = jlib:string_to_jid(JIDElString),
+           case JIDEl#jid.lresource of 
+               "" ->
+                   %% Matching JID: The stanza is ok
+                   if JIDEl#jid.luser == FromJID#jid.luser andalso
+                      JIDEl#jid.lserver == FromJID#jid.lserver ->
+                           El;
+                      true ->
+                           'invalid-from'
+                   end;
+               _ ->
+                   %% Matching JID: The stanza is ok
+                   if JIDEl#jid.luser == FromJID#jid.luser andalso
+                      JIDEl#jid.lserver == FromJID#jid.lserver andalso 
+                      JIDEl#jid.lresource == FromJID#jid.lresource ->
+                           El;
+                      true ->
+                          'invalid-from'
+                   end
+           end
+    end.
index 70f190a93f31c831d58c1428ed01313e4a1e75b8..765457a5bc34af1885f7cf2d9510bfa77e19c1a7 100644 (file)
@@ -34,6 +34,8 @@
         make_correct_from_to_attrs/3,
         replace_from_to_attrs/3,
         replace_from_to/3,
+        replace_from_attrs/2,
+        replace_from/2,
         remove_attr/2,
         make_jid/3,
         make_jid/1,
@@ -153,6 +155,13 @@ replace_from_to(From, To, {xmlelement, Name, Attrs, Els}) ->
                                     Attrs),
     {xmlelement, Name, NewAttrs, Els}.
 
+replace_from_attrs(From, Attrs) ->
+    Attrs1 = lists:keydelete("from", 1, Attrs),
+    [{"from", From} | Attrs1].
+
+replace_from(From, {xmlelement, Name, Attrs, Els}) ->
+    NewAttrs = replace_from_attrs(jlib:jid_to_string(From), Attrs),
+    {xmlelement, Name, NewAttrs, Els}.
 
 remove_attr(Attr, {xmlelement, Name, Attrs, Els}) ->
     NewAttrs = lists:keydelete(Attr, 1, Attrs),