From a4ec06445593728af35149a2a111527f8515e43c Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Tue, 20 Sep 2016 14:04:07 +0300 Subject: [PATCH] Add more tests for C2S --- src/ejabberd_c2s.erl | 26 ++--- test/ejabberd_SUITE.erl | 228 ++++++++++++++++++++++++++++++++++------ test/suite.erl | 150 ++++++++++++++++++++------ test/suite.hrl | 6 -- 4 files changed, 326 insertions(+), 84 deletions(-) diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index 186f7e9a5..e98a9eb8f 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -323,24 +323,25 @@ get_subscribed(FsmRef) -> wait_for_stream({xmlstreamstart, Name, Attrs}, StateData) -> try xmpp:decode(#xmlel{name = Name, attrs = Attrs}) of - #stream_start{xmlns = NS_CLIENT, stream_xmlns = NS_STREAM, lang = Lang} + #stream_start{xmlns = NS_CLIENT, stream_xmlns = NS_STREAM, + version = Version, lang = Lang} when NS_CLIENT /= ?NS_CLIENT; NS_STREAM /= ?NS_STREAM -> - send_header(StateData, ?MYNAME, <<"">>, Lang), + send_header(StateData, ?MYNAME, Version, Lang), send_element(StateData, xmpp:serr_invalid_namespace()), {stop, normal, StateData}; - #stream_start{lang = Lang} when byte_size(Lang) > 35 -> + #stream_start{lang = Lang, version = Version} when byte_size(Lang) > 35 -> %% As stated in BCP47, 4.4.1: %% Protocols or specifications that specify limited buffer sizes for %% language tags MUST allow for language tags of at least 35 characters. %% Do not store long language tag to avoid possible DoS/flood attacks - send_header(StateData, ?MYNAME, <<"">>, ?MYLANG), + send_header(StateData, ?MYNAME, Version, ?MYLANG), Txt = <<"Too long value of 'xml:lang' attribute">>, send_element(StateData, xmpp:serr_policy_violation(Txt, ?MYLANG)), {stop, normal, StateData}; - #stream_start{to = undefined, lang = Lang} -> + #stream_start{to = undefined, lang = Lang, version = Version} -> Txt = <<"Missing 'to' attribute">>, - send_header(StateData, ?MYNAME, <<"">>, Lang), + send_header(StateData, ?MYNAME, Version, Lang), send_element(StateData, xmpp:serr_improper_addressing(Txt, Lang)), {stop, normal, StateData}; @@ -463,7 +464,7 @@ wait_for_stream({xmlstreamstart, Name, Attrs}, StateData) -> end end; _ -> - send_header(StateData, Server, <<"">>, ?MYLANG), + send_header(StateData, Server, StreamVersion, ?MYLANG), if not StateData#state.tls_enabled and StateData#state.tls_required -> send_element( @@ -492,7 +493,7 @@ wait_for_stream({xmlstreamstart, Name, Attrs}, StateData) -> end catch _:{xmpp_codec, Why} -> Txt = xmpp:format_error(Why), - send_header(StateData, ?MYNAME, <<"">>, ?MYLANG), + send_header(StateData, ?MYNAME, <<"1.0">>, ?MYLANG), send_element(StateData, xmpp:serr_not_well_formed(Txt, ?MYLANG)), {stop, normal, StateData} end; @@ -517,13 +518,8 @@ wait_for_auth({xmlstreamelement, #xmlel{} = El}, StateData) -> decode_element(El, wait_for_auth, StateData); wait_for_auth(Pkt, StateData) when ?IS_STREAM_MGMT_PACKET(Pkt) -> fsm_next_state(wait_for_auth, dispatch_stream_mgmt(Pkt, StateData)); -wait_for_auth(#iq{type = get, - sub_els = [#legacy_auth{username = U}]} = IQ, StateData) -> - Username = case U of - undefined -> <<"">>; - _ -> U - end, - Auth = #legacy_auth{username = Username, password = <<>>, resource = <<>>}, +wait_for_auth(#iq{type = get, sub_els = [#legacy_auth{}]} = IQ, StateData) -> + Auth = #legacy_auth{username = <<>>, password = <<>>, resource = <<>>}, Res = case ejabberd_auth:plain_password_required(StateData#state.server) of false -> xmpp:make_iq_result(IQ, Auth#legacy_auth{digest = <<>>}); diff --git a/test/ejabberd_SUITE.erl b/test/ejabberd_SUITE.erl index fbaee781f..0af81dd33 100644 --- a/test/ejabberd_SUITE.erl +++ b/test/ejabberd_SUITE.erl @@ -19,8 +19,9 @@ wait_for_master/1, wait_for_slave/1, make_iq_result/1, start_event_relay/0, stop_event_relay/1, put_event/2, get_event/1, - bind/1, auth/1, open_session/1, zlib/1, starttls/1, - close_socket/1]). + bind/1, auth/1, auth/2, open_session/1, open_session/2, + zlib/1, starttls/1, close_socket/1, init_stream/1, + auth_legacy/2, auth_legacy/3]). -include("suite.hrl"). @@ -154,15 +155,26 @@ init_per_testcase(stop_ejabberd, Config) -> open_session(bind(auth(connect(Config)))); init_per_testcase(TestCase, OrigConfig) -> subscribe_to_events(OrigConfig), + TestGroup = proplists:get_value( + name, ?config(tc_group_properties, OrigConfig)), Server = ?config(server, OrigConfig), - Resource = ?config(resource, OrigConfig), + Resource = case TestGroup of + generic -> + randoms:get_string(); + legacy_auth -> + randoms:get_string(); + _ -> + ?config(resource, OrigConfig) + end, MasterResource = ?config(master_resource, OrigConfig), SlaveResource = ?config(slave_resource, OrigConfig), Test = atom_to_list(TestCase), IsMaster = lists:suffix("_master", Test), IsSlave = lists:suffix("_slave", Test), IsCarbons = lists:prefix("carbons_", Test), - User = if IsMaster or IsCarbons -> <<"test_master!#$%^*()`~+-;_=[]{}|\\">>; + IsReplaced = lists:prefix("replaced_", Test), + User = if IsReplaced -> <<"test_single!#$%^*()`~+-;_=[]{}|\\">>; + IsMaster or IsCarbons -> <<"test_master!#$%^*()`~+-;_=[]{}|\\">>; IsSlave -> <<"test_slave!#$%^*()`~+-;_=[]{}|\\">>; true -> <<"test_single!#$%^*()`~+-;_=[]{}|\\">> end, @@ -172,11 +184,15 @@ init_per_testcase(TestCase, OrigConfig) -> end, Slave = if IsCarbons -> jid:make(<<"test_master!#$%^*()`~+-;_=[]{}|\\">>, Server, SlaveResource); + IsReplaced -> + jid:make(User, Server, Resource); true -> jid:make(<<"test_slave!#$%^*()`~+-;_=[]{}|\\">>, Server, Resource) end, Master = if IsCarbons -> jid:make(<<"test_master!#$%^*()`~+-;_=[]{}|\\">>, Server, MasterResource); + IsReplaced -> + jid:make(User, Server, Resource); true -> jid:make(<<"test_master!#$%^*()`~+-;_=[]{}|\\">>, Server, Resource) end, @@ -184,29 +200,35 @@ init_per_testcase(TestCase, OrigConfig) -> set_opt(slave, Slave, set_opt(master, Master, set_opt(resource, MyResource, OrigConfig)))), - case TestCase of - test_connect -> + case Test of + "test_connect" ++ _ -> Config; - test_auth -> + "test_legacy_auth" ++ _ -> + init_stream(set_opt(stream_version, <<"">>, Config)); + "test_auth" ++ _ -> connect(Config); - test_starttls -> + "test_starttls" ++ _ -> connect(Config); - test_zlib -> + "test_zlib" -> connect(Config); - test_register -> + "test_register" -> connect(Config); - auth_md5 -> + "auth_md5" -> connect(Config); - auth_plain -> + "auth_plain" -> connect(Config); - test_bind -> + "unauthenticated_" ++ _ -> + connect(Config); + "test_bind" -> auth(connect(Config)); - sm_resume -> + "sm_resume" -> auth(connect(Config)); - sm_resume_failed -> + "sm_resume_failed" -> auth(connect(Config)); - test_open_session -> + "test_open_session" -> bind(auth(connect(Config))); + "replaced" ++ _ -> + auth(connect(Config)); _ when IsMaster or IsSlave -> Password = ?config(password, Config), ejabberd_auth:try_register(User, Server, Password), @@ -218,30 +240,56 @@ init_per_testcase(TestCase, OrigConfig) -> end_per_testcase(_TestCase, _Config) -> ok. +legacy_auth_tests() -> + {legacy_auth, [parallel], + [test_legacy_auth, + test_legacy_auth_digest, + test_legacy_auth_no_resource, + test_legacy_auth_bad_jid, + test_legacy_auth_fail]}. + no_db_tests() -> - [{generic, [sequence], - [test_connect, + [{generic, [parallel], + [test_connect_bad_xml, + test_connect_unknown_ns, + test_connect_bad_ns_client, + test_connect_bad_ns_stream, + test_connect_bad_lang, + test_connect_bad_to, + test_connect_missing_to, + test_connect, + unauthenticated_iq, + unauthenticated_stanza, test_starttls, test_zlib, test_auth, + test_auth_fail, test_bind, test_open_session, - presence, + codec_failure, + unsupported_query, + bad_nonza, + invalid_from, ping, version, time, stats, - sm, - sm_resume, - sm_resume_failed, disco]}, + {presence, [sequence], [presence]}, + {sm, [sequence], + [sm, + sm_resume, + sm_resume_failed]}, {test_proxy65, [parallel], - [proxy65_master, proxy65_slave]}]. + [proxy65_master, proxy65_slave]}, + {replaced, [parallel], + [replaced_master, replaced_slave]}]. db_tests(riak) -> %% No support for mod_pubsub [{single_user, [sequence], [test_register, + legacy_auth_tests(), auth_plain, auth_md5, presence_broadcast, @@ -273,6 +321,7 @@ db_tests(riak) -> db_tests(DB) when DB == mnesia; DB == redis -> [{single_user, [sequence], [test_register, + legacy_auth_tests(), auth_plain, auth_md5, presence_broadcast, @@ -319,6 +368,7 @@ db_tests(_) -> %% No support for carboncopy [{single_user, [sequence], [test_register, + legacy_auth_tests(), auth_plain, auth_md5, presence_broadcast, @@ -361,12 +411,14 @@ db_tests(_) -> ldap_tests() -> [{ldap_tests, [sequence], [test_auth, + test_auth_fail, vcard_get, ldap_shared_roster_get]}]. extauth_tests() -> [{extauth_tests, [sequence], [test_auth, + test_auth_fail, test_unregister]}]. groups() -> @@ -381,15 +433,15 @@ groups() -> {riak, [sequence], db_tests(riak)}]. all() -> - [{group, ldap}, + [%%{group, ldap}, {group, no_db}, {group, mnesia}, - {group, redis}, - {group, mysql}, - {group, pgsql}, - {group, sqlite}, - {group, extauth}, - {group, riak}, + %%{group, redis}, + %%{group, mysql}, + %%{group, pgsql}, + %%{group, sqlite}, + %%{group, extauth}, + %%{group, riak}, stop_ejabberd]. stop_ejabberd(Config) -> @@ -398,6 +450,48 @@ stop_ejabberd(Config) -> ?recv1({xmlstreamend, <<"stream:stream">>}), Config. +test_connect_bad_xml(Config) -> + Config0 = init_stream(set_opt(ns_client, <<"'">>, Config)), + ?recv1(#stream_error{reason = 'not-well-formed'}), + ?recv1({xmlstreamend, <<"stream:stream">>}), + close_socket(Config0). + +test_connect_unknown_ns(Config) -> + Config0 = init_stream(set_opt(ns_client, <<"wrong">>, Config)), + ?recv1(#stream_error{reason = 'not-well-formed'}), + ?recv1({xmlstreamend, <<"stream:stream">>}), + close_socket(Config0). + +test_connect_bad_ns_client(Config) -> + Config0 = init_stream(set_opt(ns_client, ?NS_SERVER, Config)), + ?recv1(#stream_error{reason = 'invalid-namespace'}), + ?recv1({xmlstreamend, <<"stream:stream">>}), + close_socket(Config0). + +test_connect_bad_ns_stream(Config) -> + Config0 = init_stream(set_opt(ns_stream, <<"wrong">>, Config)), + ?recv1(#stream_error{reason = 'invalid-namespace'}), + ?recv1({xmlstreamend, <<"stream:stream">>}), + close_socket(Config0). + +test_connect_bad_lang(Config) -> + Config0 = init_stream(set_opt(lang, lists:duplicate(36, $x), Config)), + ?recv1(#stream_error{reason = 'policy-violation'}), + ?recv1({xmlstreamend, <<"stream:stream">>}), + close_socket(Config0). + +test_connect_bad_to(Config) -> + Config0 = init_stream(set_opt(server, <<"wrong.com">>, Config)), + ?recv1(#stream_error{reason = 'host-unknown'}), + ?recv1({xmlstreamend, <<"stream:stream">>}), + close_socket(Config0). + +test_connect_missing_to(Config) -> + Config0 = init_stream(set_opt(server, <<"">>, Config)), + ?recv1(#stream_error{reason = 'improper-addressing'}), + ?recv1({xmlstreamend, <<"stream:stream">>}), + close_socket(Config0). + test_connect(Config) -> disconnect(connect(Config)). @@ -462,6 +556,28 @@ try_unregister(Config) -> ?recv1(#stream_error{reason = conflict}), Config. +unauthenticated_stanza(Config) -> + %% Unauthenticated stanza should be silently dropped. + send(Config, #message{to = server_jid(Config)}), + disconnect(Config). + +unauthenticated_iq(Config) -> + #iq{type = error} = + send_recv(Config, #iq{type = get, sub_els = [#disco_info{}]}), + disconnect(Config). + +bad_nonza(Config) -> + %% Unsupported and invalid nonza should be silently dropped. + send(Config, #caps{}), + send(Config, #stanza_error{type = wrong}), + disconnect(Config). + +invalid_from(Config) -> + send(Config, #message{from = jid:make(randoms:get_string())}), + ?recv1(#stream_error{reason = 'invalid-from'}), + ?recv1({xmlstreamend, <<"stream:stream">>}), + close_socket(Config). + auth_md5(Config) -> Mechs = ?config(mechs, Config), case lists:member(<<"DIGEST-MD5">>, Mechs) of @@ -482,14 +598,37 @@ auth_plain(Config) -> {skipped, 'PLAIN_not_available'} end. +test_legacy_auth(Config) -> + disconnect(auth_legacy(Config, _Digest = false)). + +test_legacy_auth_digest(Config) -> + ServerJID = server_jid(Config), + disconnect(auth_legacy(Config, _Digest = true)). + +test_legacy_auth_no_resource(Config0) -> + Config = set_opt(resource, <<"">>, Config0), + disconnect(auth_legacy(Config, _Digest = false, _ShouldFail = true)). + +test_legacy_auth_bad_jid(Config0) -> + Config = set_opt(user, <<"@">>, Config0), + disconnect(auth_legacy(Config, _Digest = false, _ShouldFail = true)). + +test_legacy_auth_fail(Config0) -> + Config = set_opt(user, <<"wrong">>, Config0), + disconnect(auth_legacy(Config, _Digest = false, _ShouldFail = true)). + test_auth(Config) -> disconnect(auth(Config)). +test_auth_fail(Config0) -> + Config = set_opt(user, <<"wrong">>, Config0), + disconnect(auth(Config, _ShouldFail = true)). + test_bind(Config) -> disconnect(bind(Config)). test_open_session(Config) -> - disconnect(open_session(Config)). + disconnect(open_session(Config, true)). roster_get(Config) -> #iq{type = result, sub_els = [#roster_query{items = []}]} = @@ -519,6 +658,21 @@ roster_ver(Config) -> sub_els = [#roster_query{ver = Ver2}]}), disconnect(Config). +codec_failure(Config) -> + #iq{type = error} = send_recv(Config, #iq{type = wrong}), + disconnect(Config). + +unsupported_query(Config) -> + ServerJID = server_jid(Config), + #iq{type = error} = send_recv(Config, #iq{type = get, to = ServerJID}), + #iq{type = error} = send_recv(Config, #iq{type = get, to = ServerJID, + sub_els = [#caps{}]}), + #iq{type = error} = send_recv(Config, #iq{type = get, to = ServerJID, + sub_els = [#roster_query{}, + #disco_info{}, + #privacy_query{}]}), + disconnect(Config). + presence(Config) -> send(Config, #presence{}), JID = my_jid(Config), @@ -604,6 +758,18 @@ disco(Config) -> end, Items), disconnect(Config). +replaced_master(Config0) -> + Config = bind(Config0), + wait_for_slave(Config), + ?recv1(#stream_error{reason = conflict}), + ?recv1({xmlstreamend, <<"stream:stream">>}), + close_socket(Config). + +replaced_slave(Config0) -> + wait_for_master(Config0), + Config = bind(Config0), + disconnect(Config). + sm(Config) -> Server = ?config(server, Config), ServerJID = jid:make(<<"">>, Server, <<"">>), diff --git a/test/suite.erl b/test/suite.erl index d89a49ef8..93141d846 100644 --- a/test/suite.erl +++ b/test/suite.erl @@ -32,7 +32,7 @@ init_config(Config) -> {ok, CfgContentTpl} = file:read_file(ConfigPathTpl), CfgContent = process_config_tpl(CfgContentTpl, [ {c2s_port, 5222}, - {loglevel, 4}, + {loglevel, 5}, {s2s_port, 5269}, {web_port, 5280}, {mysql_server, <<"localhost">>}, @@ -64,6 +64,12 @@ init_config(Config) -> {slave_nick, <<"slave_nick!@#$%^&*()'\"`~<>+-/;:_=[]{}|\\">>}, {room_subject, <<"hello, world!@#$%^&*()'\"`~<>+-/;:_=[]{}|\\">>}, {certfile, CertFile}, + {ns_client, ?NS_CLIENT}, + {ns_stream, ?NS_STREAM}, + {stream_version, <<"1.0">>}, + {stream_id, <<"">>}, + {mechs, []}, + {lang, <<"en">>}, {base_dir, BaseDir}, {resource, <<"resource!@#$%^&*()'\"`~<>+-/;:_=[]{}|\\">>}, {master_resource, <<"master_resource!@#$%^&*()'\"`~<>+-/;:_=[]{}|\\">>}, @@ -118,20 +124,36 @@ process_config_tpl(Content, [{Name, DefaultValue} | Rest]) -> NewContent = binary:replace(Content, <<"@@",(atom_to_binary(Name, latin1))/binary, "@@">>, Val), process_config_tpl(NewContent, Rest). +stream_header(Config) -> + NSStream = ?config(ns_stream, Config), + NSClient = ?config(ns_client, Config), + Lang = ?config(lang, Config), + To = case ?config(server, Config) of + <<"">> -> <<"">>; + Server -> <<"to='", Server/binary, "'">> + end, + Version = ?config(stream_version, Config), + io_lib:format("", + [NSStream, NSClient, To, Version, Lang]). connect(Config) -> + process_stream_features(init_stream(Config)). + +init_stream(Config) -> + Version = ?config(stream_version, Config), {ok, Sock} = ejabberd_socket:connect( ?config(server_host, Config), ?config(server_port, Config), [binary, {packet, 0}, {active, false}]), - init_stream(set_opt(socket, Sock, Config)). + NewConfig = set_opt(socket, Sock, Config), + ok = send_text(NewConfig, stream_header(NewConfig)), + #stream_start{id = ID, xmlns = ?NS_CLIENT, + version = Version} = recv(), + set_opt(stream_id, ID, NewConfig). -init_stream(Config) -> - ok = send_text(Config, io_lib:format(?STREAM_HEADER, - [?config(server, Config)])), - {xmlstreamstart, <<"stream:stream">>, Attrs} = recv(), - <<"jabber:client">> = fxml:get_attr_s(<<"xmlns">>, Attrs), - <<"1.0">> = fxml:get_attr_s(<<"version">>, Attrs), +process_stream_features(Config) -> #stream_features{sub_els = Fs} = recv(), Mechs = lists:flatmap( fun(#sasl_mechanisms{list = Ms}) -> @@ -169,24 +191,27 @@ starttls(Config) -> ?config(socket, Config), [{certfile, ?config(certfile, Config)}, connect]), - init_stream(set_opt(socket, TLSSocket, Config)). + process_stream_features(init_stream(set_opt(socket, TLSSocket, Config))). zlib(Config) -> send(Config, #compress{methods = [<<"zlib">>]}), #compressed{} = recv(), ZlibSocket = ejabberd_socket:compress(?config(socket, Config)), - init_stream(set_opt(socket, ZlibSocket, Config)). + process_stream_features(init_stream(set_opt(socket, ZlibSocket, Config))). auth(Config) -> + auth(Config, false). + +auth(Config, ShouldFail) -> Mechs = ?config(mechs, Config), HaveMD5 = lists:member(<<"DIGEST-MD5">>, Mechs), HavePLAIN = lists:member(<<"PLAIN">>, Mechs), if HavePLAIN -> - auth_SASL(<<"PLAIN">>, Config); + auth_SASL(<<"PLAIN">>, Config, ShouldFail); HaveMD5 -> - auth_SASL(<<"DIGEST-MD5">>, Config); + auth_SASL(<<"DIGEST-MD5">>, Config, ShouldFail); true -> - ct:fail(no_sasl_mechanisms_available) + auth_legacy(Config, false, ShouldFail) end. bind(Config) -> @@ -198,29 +223,83 @@ bind(Config) -> Config. open_session(Config) -> - #iq{type = result, sub_els = []} = - send_recv(Config, #iq{type = set, sub_els = [#xmpp_session{}]}), + open_session(Config, false). + +open_session(Config, Force) -> + if Force -> + #iq{type = result, sub_els = []} = + send_recv(Config, #iq{type = set, sub_els = [#xmpp_session{}]}); + true -> + ok + end, Config. +auth_legacy(Config, IsDigest) -> + auth_legacy(Config, IsDigest, false). + +auth_legacy(Config, IsDigest, ShouldFail) -> + ServerJID = server_jid(Config), + U = ?config(user, Config), + R = ?config(resource, Config), + P = ?config(password, Config), + #iq{type = result, + from = ServerJID, + sub_els = [#legacy_auth{username = <<"">>, + password = <<"">>, + resource = <<"">>} = Auth]} = + send_recv(Config, + #iq{to = ServerJID, type = get, + sub_els = [#legacy_auth{}]}), + Res = case Auth#legacy_auth.digest of + <<"">> when IsDigest -> + StreamID = ?config(stream_id, Config), + D = p1_sha:sha(<>), + send_recv(Config, #iq{to = ServerJID, type = set, + sub_els = [#legacy_auth{username = U, + resource = R, + digest = D}]}); + _ when not IsDigest -> + send_recv(Config, #iq{to = ServerJID, type = set, + sub_els = [#legacy_auth{username = U, + resource = R, + password = P}]}) + end, + case Res of + #iq{from = ServerJID, type = result, sub_els = []} -> + if ShouldFail -> + ct:fail(legacy_auth_should_have_failed); + true -> + Config + end; + #iq{from = ServerJID, type = error} -> + if ShouldFail -> + Config; + true -> + ct:fail(legacy_auth_failed) + end + end. + auth_SASL(Mech, Config) -> + auth_SASL(Mech, Config, false). + +auth_SASL(Mech, Config, ShouldFail) -> {Response, SASL} = sasl_new(Mech, ?config(user, Config), ?config(server, Config), ?config(password, Config)), send(Config, #sasl_auth{mechanism = Mech, text = Response}), - wait_auth_SASL_result(set_opt(sasl, SASL, Config)). + wait_auth_SASL_result(set_opt(sasl, SASL, Config), ShouldFail). -wait_auth_SASL_result(Config) -> +wait_auth_SASL_result(Config, ShouldFail) -> case recv() of + #sasl_success{} when ShouldFail -> + ct:fail(sasl_auth_should_have_failed); #sasl_success{} -> ejabberd_socket:reset_stream(?config(socket, Config)), - send_text(Config, - io_lib:format(?STREAM_HEADER, - [?config(server, Config)])), - {xmlstreamstart, <<"stream:stream">>, Attrs} = recv(), - <<"jabber:client">> = fxml:get_attr_s(<<"xmlns">>, Attrs), - <<"1.0">> = fxml:get_attr_s(<<"version">>, Attrs), + send_text(Config, stream_header(Config)), + #stream_start{xmlns = ?NS_CLIENT, version = <<"1.0">>} = recv(), #stream_features{sub_els = Fs} = recv(), + #xmpp_session{optional = true} = lists:keyfind(xmpp_session, 1, Fs), lists:foldl( fun(#feature_sm{}, ConfigAcc) -> set_opt(sm, true, ConfigAcc); @@ -232,7 +311,9 @@ wait_auth_SASL_result(Config) -> #sasl_challenge{text = ClientIn} -> {Response, SASL} = (?config(sasl, Config))(ClientIn), send(Config, #sasl_response{text = Response}), - wait_auth_SASL_result(set_opt(sasl, SASL, Config)); + wait_auth_SASL_result(set_opt(sasl, SASL, Config), ShouldFail); + #sasl_failure{} when ShouldFail -> + Config; #sasl_failure{} -> ct:fail(sasl_auth_failed) end. @@ -252,18 +333,23 @@ match_failure(Received, Matches) -> recv() -> receive {'$gen_event', {xmlstreamelement, El}} -> - try - Pkt = xmpp:decode(El), - ct:pal("recv: ~p ->~n~s", [El, xmpp_codec:pp(Pkt)]), - Pkt - catch _:{xmpp_codec, Why} -> - ct:fail("recv failed: ~p->~n~s", - [El, xmpp:format_error(Why)]) - end; + decode(El); + {'$gen_event', {xmlstreamstart, Name, Attrs}} -> + decode(#xmlel{name = Name, attrs = Attrs}); {'$gen_event', Event} -> Event end. +decode(El) -> + try + Pkt = xmpp:decode(El), + ct:pal("recv: ~p ->~n~s", [El, xmpp_codec:pp(Pkt)]), + Pkt + catch _:{xmpp_codec, Why} -> + ct:fail("recv failed: ~p->~n~s", + [El, xmpp:format_error(Why)]) + end. + fix_ns(#xmlel{name = Tag, attrs = Attrs} = El) when Tag == <<"stream:features">>; Tag == <<"stream:error">> -> NewAttrs = [{<<"xmlns">>, <<"http://etherx.jabber.org/streams">>} diff --git a/test/suite.hrl b/test/suite.hrl index fb6b4f3ac..3095e1bb5 100644 --- a/test/suite.hrl +++ b/test/suite.hrl @@ -5,12 +5,6 @@ -include("mod_proxy65.hrl"). -include("xmpp_codec.hrl"). --define(STREAM_HEADER, - <<"">>). - -define(STREAM_TRAILER, <<"">>). -define(PUBSUB(Node), <<(?NS_PUBSUB)/binary, "#", Node>>).