From: Mickaël Rémond Date: Mon, 8 Dec 2008 09:21:36 +0000 (+0000) Subject: * src/ejabberd_c2s.erl: Enforce client stanza from attribute (EJAB-812). X-Git-Tag: v2.1.0~18^2~525 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4618ec1fefb73a8ba85441de19bb17fd451961ec;p=ejabberd * src/ejabberd_c2s.erl: Enforce client stanza from attribute (EJAB-812). * src/jlib.erl: Likewise. SVN Revision: 1706 --- diff --git a/ChangeLog b/ChangeLog index 2aea56718..823b6bc7b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2008-12-08 Mickael Remond + + * src/ejabberd_c2s.erl: Enforce client stanza from attribute + (EJAB-812). + * src/jlib.erl: Likewise. + 2008-12-02 Badlop * src/mod_muc/mod_muc_room.erl: Move definitions to header file diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index 5b08d1e35..fb93d8dde 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -133,6 +133,9 @@ 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. diff --git a/src/jlib.erl b/src/jlib.erl index 70f190a93..765457a5b 100644 --- a/src/jlib.erl +++ b/src/jlib.erl @@ -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),