diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/acl_test.exs | 271 | ||||
-rw-r--r-- | test/ejabberd_SUITE.erl | 97 | ||||
-rw-r--r-- | test/ejabberd_SUITE_data/cert.pem | 95 | ||||
-rw-r--r-- | test/ejabberd_SUITE_data/ejabberd.ldif | 22 | ||||
-rw-r--r-- | test/ejabberd_SUITE_data/ejabberd.yml | 7 | ||||
-rw-r--r-- | test/ejabberd_commands_mock_test.exs | 18 | ||||
-rw-r--r-- | test/elixir_SUITE.erl | 1 | ||||
-rw-r--r-- | test/mod_admin_extra_test.exs | 1 | ||||
-rw-r--r-- | test/mod_http_api_mock_test.exs | 4 | ||||
-rw-r--r-- | test/mod_http_api_test.exs | 30 | ||||
-rw-r--r-- | test/mod_roster_mock.exs | 67 | ||||
-rw-r--r-- | test/suite.erl | 44 |
12 files changed, 527 insertions, 130 deletions
diff --git a/test/acl_test.exs b/test/acl_test.exs index db6584308..38f0372e6 100644 --- a/test/acl_test.exs +++ b/test/acl_test.exs @@ -36,7 +36,7 @@ defmodule ACLTest do test "access rule match with user part ACL" do :acl.add(:global, :basic_acl_1, {:user, "test1"}) - :acl.add_access(:global, :basic_rule_1, [{:basic_acl_1, :allow}]) + :acl.add_access(:global, :basic_rule_1, [{:allow, [{:acl, :basic_acl_1}]}]) # JID can only be passes as jid record. # => TODO: Support passing JID as binary. assert :acl.match_rule(:global, :basic_rule_1, :jid.from_string("test1@domain1")) == :allow @@ -46,7 +46,7 @@ defmodule ACLTest do assert :acl.match_rule(:global, :basic_rule_1, :jid.from_string("test11@domain1")) == :deny :acl.add(:global, :basic_acl_2, {:user, {"test2", "domain1"}}) - :acl.add_access(:global, :basic_rule_2, [{:basic_acl_2, :allow}]) + :acl.add_access(:global, :basic_rule_2, [{:allow, [{:acl, :basic_acl_2}]}]) assert :acl.match_rule(:global, :basic_rule_2, :jid.from_string("test2@domain1")) == :allow assert :acl.match_rule(:global, :basic_rule_2, :jid.from_string("test2@domain2")) == :deny assert :acl.match_rule(:global, :basic_rule_2, :jid.from_string("test2@otherdomain")) == :deny @@ -55,7 +55,7 @@ defmodule ACLTest do test "IP based ACL" do :acl.add(:global, :ip_acl_1, {:ip, "127.0.0.0/24"}) - :acl.add_access(:global, :ip_rule_1, [{:ip_acl_1, :allow}]) + :acl.add_access(:global, :ip_rule_1, [{:allow, [{:acl, :ip_acl_1}]}]) # IP must be expressed as a tuple when calling match rule assert :acl.match_rule(:global, :ip_rule_1, {127,0,0,1}) == :allow assert :acl.match_rule(:global, :ip_rule_1, {127,0,1,1}) == :deny @@ -65,7 +65,7 @@ defmodule ACLTest do test "Access rule are evaluated sequentially" do :acl.add(:global, :user_acl_1, {:user, {"test1", "domain2"}}) :acl.add(:global, :user_acl_2, {:user, "test1"}) - :acl.add_access(:global, :user_rule_1, [{:user_acl_1, :deny}, {:user_acl_2, :allow}]) + :acl.add_access(:global, :user_rule_1, [{:deny, [{:acl, :user_acl_1}]}, {:allow, [{:acl, :user_acl_2}]}]) assert :acl.match_rule(:global, :user_rule_1, :jid.from_string("test1@domain1")) == :allow assert :acl.match_rule(:global, :user_rule_1, :jid.from_string("test1@domain2")) == :deny end @@ -74,7 +74,7 @@ defmodule ACLTest do test "Access rules providing values" do :acl.add(:global, :user_acl, {:user_regexp, ""}) :acl.add(:global, :admin_acl, {:user, "admin"}) - :acl.add_access(:global, :value_rule_1, [{:admin_acl, 10}, {:user_acl, 5}]) + :acl.add_access(:global, :value_rule_1, [{10, [{:acl, :admin_acl}]}, {5, [{:acl, :user_acl}]}]) assert :acl.match_rule(:global, :value_rule_1, :jid.from_string("test1@domain1")) == 5 assert :acl.match_rule(:global, :value_rule_1, :jid.from_string("admin@domain1")) == 10 @@ -91,19 +91,264 @@ defmodule ACLTest do test "mixing IP and user access rules" do :acl.add(:global, :user_acl_1, {:user, "test1"}) :acl.add(:global, :ip_acl_1, {:ip, "127.0.0.0/24"}) - :acl.add_access(:global, :mixed_rule_1, [{:user_acl_1, :allow}, {:ip_acl_1, :allow}]) + :acl.add_access(:global, :mixed_rule_1, [{:allow, [{:acl, :user_acl_1}]}, {:allow, [{:acl, :ip_acl_1}]}]) assert :acl.match_rule(:global, :mixed_rule_1, :jid.from_string("test1@domain1")) == :allow assert :acl.match_rule(:global, :mixed_rule_1, {127,0,0,1}) == :allow - :acl.add_access(:global, :mixed_rule_2, [{:user_acl_1, :deny}, {:ip_acl_1, :allow}]) + :acl.add_access(:global, :mixed_rule_2, [{:deny, [{:acl, :user_acl_1}]}, {:allow, [{:acl, :ip_acl_1}]}]) assert :acl.match_rule(:global, :mixed_rule_2, :jid.from_string("test1@domain1")) == :deny assert :acl.match_rule(:global, :mixed_rule_2, {127,0,0,1}) == :allow end - test "acl:match_access can match directly on user pattern" do - pattern = {:user, {"test1", "domain1"}} - assert :acl.match_access(:global, pattern, :jid.from_string("test1@domain1"), :allow) == :allow - assert :acl.match_access(:global, pattern, :jid.from_string("test2@domain1"), :allow) == :deny + test "access_matches works with predefined access rules" do + :acl.add(:global, :user_acl_2, {:user, "user"}) + :acl.add_access(:global, :user_rule_2, [{:allow, [{:acl, :user_acl_2}]}, {:deny, [:all]}]) + + assert :acl.access_matches(:user_rule_2, %{usr: {"user", "domain1", ""}, ip: {127,0,0,1}}, :global) == :allow + assert :acl.access_matches(:user_rule_2, %{usr: {"user2", "domain1", ""}, ip: {127,0,0,1}}, :global) == :deny + end + + test "access_matches rule all always matches" do + assert :acl.access_matches(:all, %{}, :global) == :allow + assert :acl.access_matches(:all, %{usr: {"user", "domain1", ""}, ip: {127,0,0,1}}, :global) == :allow + end + + test "access_matches rule none never matches" do + assert :acl.access_matches(:none, %{}, :global) == :deny + assert :acl.access_matches(:none, %{usr: {"user", "domain1", ""}, ip: {127,0,0,1}}, :global) == :deny + end + + test "access_matches with not existing rule never matches" do + assert :acl.access_matches(:bleble, %{}, :global) == :deny + assert :acl.access_matches(:bleble, %{usr: {"user", "domain1", ""}, ip: {127,0,0,1}}, :global) == :deny + end + + test "access_matches works with inlined access rules" do + :acl.add(:global, :user_acl_3, {:user, "user"}) + + assert :acl.access_matches([{:allow, [{:acl, :user_acl_3}]}, {:deny, [:all]}], + %{usr: {"user", "domain1", ""}, ip: {127,0,0,1}}, :global) == :allow + assert :acl.access_matches([{:allow, [{:acl, :user_acl_3}]}, {:deny, [:all]}], + %{usr: {"user2", "domain1", ""}, ip: {127,0,0,1}}, :global) == :deny + end + + test "access_matches allow to have acl rules inlined" do + assert :acl.access_matches([{:allow, [{:user, "user"}]}, {:deny, [:all]}], + %{usr: {"user", "domain1", ""}, ip: {127,0,0,1}}, :global) == :allow + assert :acl.access_matches([{:allow, [{:user, "user"}]}, {:deny, [:all]}], + %{usr: {"user2", "domain1", ""}, ip: {127,0,0,1}}, :global) == :deny + end + + test "access_matches test have implicit deny at end" do + assert :acl.access_matches([{:allow, [{:user, "user"}]}], + %{usr: {"user", "domain1", ""}, ip: {127,0,0,1}}, :global) == :allow + assert :acl.access_matches([{:allow, [{:user, "user"}]}], + %{usr: {"user2", "domain1", ""}, ip: {127,0,0,1}}, :global) == :deny + end + + test "access_matches requires that all subrules match" do + rules = [{:allow, [{:user, "user"}, {:ip, {{127,0,0,1}, 32}}]}] + assert :acl.access_matches(rules, %{usr: {"user", "domain1", ""}, ip: {127,0,0,1}}, :global) == :allow + assert :acl.access_matches(rules, %{usr: {"user", "domain1", ""}, ip: {127,0,0,2}}, :global) == :deny + assert :acl.access_matches(rules, %{usr: {"user2", "domain1", ""}, ip: {127,0,0,1}}, :global) == :deny + end + + test "access_matches rules are matched in order" do + rules = [{:allow, [{:user, "user"}]}, {:deny, [{:user, "user2"}]}, {:allow, [{:user_regexp, "user"}]}] + assert :acl.access_matches(rules, %{usr: {"user", "domain1", ""}, ip: {127,0,0,1}}, :global) == :allow + assert :acl.access_matches(rules, %{usr: {"user2", "domain1", ""}, ip: {127,0,0,1}}, :global) == :deny + assert :acl.access_matches(rules, %{usr: {"user22", "domain1", ""}, ip: {127,0,0,1}}, :global) == :allow + end + + test "access_matches rules that require ip but no one is provided don't crash" do + rules = [{:allow, [{:ip, {{127,0,0,1}, 32}}]}, + {:allow, [{:user, "user"}]}, + {:allow, [{:user, "user2"}, {:ip, {{127,0,0,1}, 32}}]}] + assert :acl.access_matches(rules, %{usr: {"user", "domain1", ""}}, :global) == :allow + assert :acl.access_matches(rules, %{usr: {"user2", "domain1", ""}}, :global) == :deny + end + + test "access_matches rules that require usr but no one is provided don't crash" do + rules = [{:allow, [{:ip, {{127,0,0,1}, 32}}]}, + {:allow, [{:user, "user"}]}, + {:allow, [{:user, "user2"}, {:ip, {{127,0,0,2}, 32}}]}] + assert :acl.access_matches(rules, %{ip: {127,0,0,1}}, :global) == :allow + assert :acl.access_matches(rules, %{ip: {127,0,0,2}}, :global) == :deny + end + + test "access_matches rules with all always matches" do + rules = [{:allow, [:all]}, {:deny, {:user, "user"}}] + assert :acl.access_matches(rules, %{}, :global) == :allow + assert :acl.access_matches(rules, %{usr: {"user", "domain1", ""}, ip: {127,0,0,1}}, :global) == :allow + end + + test "access_matches rules with {acl, all} always matches" do + rules = [{:allow, [{:acl, :all}]}, {:deny, {:user, "user"}}] + assert :acl.access_matches(rules, %{}, :global) == :allow + assert :acl.access_matches(rules, %{usr: {"user", "domain1", ""}, ip: {127,0,0,1}}, :global) == :allow + end + + test "access_matches rules with none never matches" do + rules = [{:allow, [:none]}, {:deny, [:all]}] + assert :acl.access_matches(rules, %{}, :global) == :deny + assert :acl.access_matches(rules, %{usr: {"user", "domain1", ""}, ip: {127,0,0,1}}, :global) == :deny + end + + test "access_matches with no rules never matches" do + assert :acl.access_matches([], %{}, :global) == :deny + assert :acl.access_matches([], %{usr: {"user", "domain1", ""}, ip: {127,0,0,1}}, :global) == :deny + end + + test "access_matches ip rule accepts {ip, port}" do + rules = [{:allow, [{:ip, {{127,0,0,1}, 32}}]}] + assert :acl.access_matches(rules, %{ip: {{127,0,0,1}, 5000}}, :global) == :allow + assert :acl.access_matches(rules, %{ip: {{127,0,0,2}, 5000}}, :global) == :deny + end + + test "access_matches user rule works" do + rules = [{:allow, [{:user, "user1"}]}] + assert :acl.access_matches(rules, %{usr: {"user1", "domain1", ""}}, :global) == :allow + assert :acl.access_matches(rules, %{usr: {"user2", "domain1", ""}}, :global) == :deny + assert :acl.access_matches(rules, %{usr: {"user1", "domain3", ""}}, :global) == :deny + end + + test "access_matches 2 arg user rule works" do + rules = [{:allow, [{:user, {"user1", "server1"}}]}] + assert :acl.access_matches(rules, %{usr: {"user1", "server1", ""}}, :global) == :allow + assert :acl.access_matches(rules, %{usr: {"user1", "server2", ""}}, :global) == :deny + assert :acl.access_matches(rules, %{usr: {"user2", "server1", ""}}, :global) == :deny + assert :acl.access_matches(rules, %{usr: {"user2", "server2", ""}}, :global) == :deny + end + + test "access_matches server rule works" do + rules = [{:allow, [{:server, "server1"}]}] + assert :acl.access_matches(rules, %{usr: {"user", "server1", ""}}, :global) == :allow + assert :acl.access_matches(rules, %{usr: {"user", "server2", ""}}, :global) == :deny + end + + test "access_matches resource rule works" do + rules = [{:allow, [{:resource, "res1"}]}] + assert :acl.access_matches(rules, %{usr: {"user", "domain1", "res1"}}, :global) == :allow + assert :acl.access_matches(rules, %{usr: {"user", "domain1", "res2"}}, :global) == :deny + assert :acl.access_matches(rules, %{usr: {"user", "domain3", "res1"}}, :global) == :allow + end + + test "access_matches user_regexp rule works" do + rules = [{:allow, [{:user_regexp, "user[0-9]"}]}] + assert :acl.access_matches(rules, %{usr: {"user1", "domain1", "res1"}}, :global) == :allow + assert :acl.access_matches(rules, %{usr: {"userA", "domain1", "res1"}}, :global) == :deny + assert :acl.access_matches(rules, %{usr: {"user1", "domain3", "res1"}}, :global) == :deny + end + + test "access_matches 2 arg user_regexp rule works" do + rules = [{:allow, [{:user_regexp, {"user[0-9]", "server1"}}]}] + assert :acl.access_matches(rules, %{usr: {"user1", "server1", "res1"}}, :global) == :allow + assert :acl.access_matches(rules, %{usr: {"userA", "server1", "res1"}}, :global) == :deny + assert :acl.access_matches(rules, %{usr: {"user1", "server2", "res1"}}, :global) == :deny + end + + test "access_matches server_regexp rule works" do + rules = [{:allow, [{:server_regexp, "server[0-9]"}]}] + assert :acl.access_matches(rules, %{usr: {"user", "server1", ""}}, :global) == :allow + assert :acl.access_matches(rules, %{usr: {"user", "serverA", ""}}, :global) == :deny + end + + test "access_matches resource_regexp rule works" do + rules = [{:allow, [{:resource_regexp, "res[0-9]"}]}] + assert :acl.access_matches(rules, %{usr: {"user", "domain1", "res1"}}, :global) == :allow + assert :acl.access_matches(rules, %{usr: {"user", "domain1", "resA"}}, :global) == :deny + assert :acl.access_matches(rules, %{usr: {"user", "domain3", "res1"}}, :global) == :allow + end + + test "access_matches node_regexp rule works" do + rules = [{:allow, [{:node_regexp, {"user[0-9]", "server[0-9]"}}]}] + assert :acl.access_matches(rules, %{usr: {"user1", "server1", "res1"}}, :global) == :allow + assert :acl.access_matches(rules, %{usr: {"userA", "server1", "res1"}}, :global) == :deny + assert :acl.access_matches(rules, %{usr: {"user1", "serverA", "res1"}}, :global) == :deny + assert :acl.access_matches(rules, %{usr: {"userA", "serverA", "res1"}}, :global) == :deny + end + + test "access_matches user_glob rule works" do + rules = [{:allow, [{:user_glob, "user?"}]}] + assert :acl.access_matches(rules, %{usr: {"user1", "domain1", "res1"}}, :global) == :allow + assert :acl.access_matches(rules, %{usr: {"user11", "domain1", "res1"}}, :global) == :deny + assert :acl.access_matches(rules, %{usr: {"user1", "domain3", "res1"}}, :global) == :deny + end + + test "access_matches 2 arg user_glob rule works" do + rules = [{:allow, [{:user_glob, {"user?", "server1"}}]}] + assert :acl.access_matches(rules, %{usr: {"user1", "server1", "res1"}}, :global) == :allow + assert :acl.access_matches(rules, %{usr: {"user11", "server1", "res1"}}, :global) == :deny + assert :acl.access_matches(rules, %{usr: {"user1", "server2", "res1"}}, :global) == :deny + end + + test "access_matches server_glob rule works" do + rules = [{:allow, [{:server_glob, "server?"}]}] + assert :acl.access_matches(rules, %{usr: {"user", "server1", ""}}, :global) == :allow + assert :acl.access_matches(rules, %{usr: {"user", "server11", ""}}, :global) == :deny + end + + test "access_matches resource_glob rule works" do + rules = [{:allow, [{:resource_glob, "res?"}]}] + assert :acl.access_matches(rules, %{usr: {"user", "domain1", "res1"}}, :global) == :allow + assert :acl.access_matches(rules, %{usr: {"user", "domain1", "res11"}}, :global) == :deny + assert :acl.access_matches(rules, %{usr: {"user", "domain3", "res1"}}, :global) == :allow + end + + test "access_matches node_glob rule works" do + rules = [{:allow, [{:node_glob, {"user?", "server?"}}]}] + assert :acl.access_matches(rules, %{usr: {"user1", "server1", "res1"}}, :global) == :allow + assert :acl.access_matches(rules, %{usr: {"user11", "server1", "res1"}}, :global) == :deny + assert :acl.access_matches(rules, %{usr: {"user1", "server11", "res1"}}, :global) == :deny + assert :acl.access_matches(rules, %{usr: {"user11", "server11", "res1"}}, :global) == :deny + end + + test "transform_access_rules_config expands allow rule" do + assert :acl.transform_access_rules_config([:allow]) == [{:allow, [:all]}] + end + + test "transform_access_rules_config expands deny rule" do + assert :acl.transform_access_rules_config([:deny]) == [{:deny, [:all]}] + end + + test "transform_access_rules_config expands <integer> rule" do + assert :acl.transform_access_rules_config([100]) == [{100, [:all]}] + end + + test "transform_access_rules_config expands <shaper_name> rule" do + assert :acl.transform_access_rules_config([:fast]) == [{:fast, [:all]}] + end + + test "transform_access_rules_config expands allow: <acl_name> rule" do + assert :acl.transform_access_rules_config([{:allow, :test1}]) == [{:allow, [{:acl, :test1}]}] + end + + test "transform_access_rules_config expands deny: <acl_name> rule" do + assert :acl.transform_access_rules_config([{:deny, :test1}]) == [{:deny, [{:acl, :test1}]}] + end + + test "transform_access_rules_config expands integer: <acl_name> rule" do + assert :acl.transform_access_rules_config([{100, :test1}]) == [{100, [{:acl, :test1}]}] + end + + test "transform_access_rules_config expands <shaper_name>: <acl_name> rule" do + assert :acl.transform_access_rules_config([{:fast, :test1}]) == [{:fast, [{:acl, :test1}]}] + end + + test "transform_access_rules_config expands allow rule (no list)" do + assert :acl.transform_access_rules_config(:allow) == [{:allow, [:all]}] + end + + test "transform_access_rules_config expands deny rule (no list)" do + assert :acl.transform_access_rules_config(:deny) == [{:deny, [:all]}] + end + + test "transform_access_rules_config expands <integer> rule (no list)" do + assert :acl.transform_access_rules_config(100) == [{100, [:all]}] + end + + test "transform_access_rules_config expands <shaper_name> rule (no list)" do + assert :acl.transform_access_rules_config(:fast) == [{:fast, [:all]}] end ## Checking ACL on both user pattern and IP @@ -115,8 +360,8 @@ defmodule ACLTest do test "module can test both IP and user through two independent :acl.match_rule check (deprecated)" do :acl.add(:global, :user_acl, {:user, {"test1", "domain1"}}) :acl.add(:global, :ip_acl, {:ip, "127.0.0.0/24"}) - :acl.add_access(:global, :user_rule, [{:user_acl, :allow}]) - :acl.add_access(:global, :ip_rule, [{:ip_acl, :allow}]) + :acl.add_access(:global, :user_rule, [{:allow, [{:acl, :user_acl}]}]) + :acl.add_access(:global, :ip_rule, [{:allow, [{:acl, :ip_acl}]}]) # acl module in 16.03 is not able to provide a function for compound result: assert :acl.match_rule(:global, :user_rule, :jid.from_string("test1@domain1")) == :allow diff --git a/test/ejabberd_SUITE.erl b/test/ejabberd_SUITE.erl index aa465fb66..d3e7ec668 100644 --- a/test/ejabberd_SUITE.erl +++ b/test/ejabberd_SUITE.erl @@ -162,23 +162,23 @@ init_per_testcase(TestCase, OrigConfig) -> IsMaster = lists:suffix("_master", Test), IsSlave = lists:suffix("_slave", Test), IsCarbons = lists:prefix("carbons_", Test), - User = if IsMaster or IsCarbons -> <<"test_master">>; - IsSlave -> <<"test_slave">>; - true -> <<"test_single">> + User = if IsMaster or IsCarbons -> <<"test_master!#$%^*()`~+-;_=[]{}|\\">>; + IsSlave -> <<"test_slave!#$%^*()`~+-;_=[]{}|\\">>; + true -> <<"test_single!#$%^*()`~+-;_=[]{}|\\">> end, MyResource = if IsMaster and IsCarbons -> MasterResource; IsSlave and IsCarbons -> SlaveResource; true -> Resource end, Slave = if IsCarbons -> - jid:make(<<"test_master">>, Server, SlaveResource); + jid:make(<<"test_master!#$%^*()`~+-;_=[]{}|\\">>, Server, SlaveResource); true -> - jid:make(<<"test_slave">>, Server, Resource) + jid:make(<<"test_slave!#$%^*()`~+-;_=[]{}|\\">>, Server, Resource) end, Master = if IsCarbons -> - jid:make(<<"test_master">>, Server, MasterResource); + jid:make(<<"test_master!#$%^*()`~+-;_=[]{}|\\">>, Server, MasterResource); true -> - jid:make(<<"test_master">>, Server, Resource) + jid:make(<<"test_master!#$%^*()`~+-;_=[]{}|\\">>, Server, Resource) end, Config = set_opt(user, User, set_opt(slave, Slave, @@ -203,6 +203,8 @@ init_per_testcase(TestCase, OrigConfig) -> auth(connect(Config)); sm_resume -> auth(connect(Config)); + sm_resume_failed -> + auth(connect(Config)); test_open_session -> bind(auth(connect(Config))); _ when IsMaster or IsSlave -> @@ -231,6 +233,7 @@ no_db_tests() -> stats, sm, sm_resume, + sm_resume_failed, disco]}, {test_proxy65, [parallel], [proxy65_master, proxy65_slave]}]. @@ -641,6 +644,17 @@ sm_resume(Config) -> ?recv1(#message{from = ServerJID, to = MyJID, body = [Txt]}), ?recv1(#sm_r{}), send(Config, #sm_a{h = 1, xmlns = ?NS_STREAM_MGMT_3}), + %% Send another stanza to increment the server's 'h' for sm_resume_failed. + send(Config, #presence{to = ServerJID}), + close_socket(Config), + {save_config, set_opt(sm_previd, ID, Config)}. + +sm_resume_failed(Config) -> + {sm_resume, SMConfig} = ?config(saved_config, Config), + ID = ?config(sm_previd, SMConfig), + ct:sleep(5000), % Wait for session to time out. + send(Config, #sm_resume{previd = ID, h = 1, xmlns = ?NS_STREAM_MGMT_3}), + ?recv1(#sm_failed{reason = 'item-not-found', h = 4}), disconnect(Config). private(Config) -> @@ -868,7 +882,7 @@ pubsub(Config) -> true = lists:member(?NS_PUBSUB, Features), %% Publish <presence/> element within node "presence" ItemID = randoms:get_string(), - Node = <<"presence">>, + Node = <<"presence!@#$%^&*()'\"`~<>+-/;:_=[]{}|\\">>, Item = #pubsub_item{id = ItemID, xml_els = [xmpp_codec:encode(#presence{})]}, #iq{type = result, @@ -1435,6 +1449,11 @@ muc_master(Config) -> items = [#muc_item{affiliation = member, jid = PeerJID, role = participant}]}]}), + ?recv1(#message{from = Room, + sub_els = [#muc_user{ + items = [#muc_item{affiliation = member, + jid = Localhost, + role = none}]}]}), %% BUG: We should not receive any sub_els! ?recv1(#iq{type = result, id = I1, sub_els = [_|_]}), %% Receive groupchat message from the peer @@ -2255,15 +2274,46 @@ client_state_master(Config) -> ChatState = #message{to = Peer, thread = <<"1">>, sub_els = [#chatstate{type = active}]}, Message = ChatState#message{body = [#text{data = <<"body">>}]}, + PepPayload = xmpp_codec:encode(#presence{}), + PepOne = #message{ + to = Peer, + sub_els = + [#pubsub_event{ + items = + [#pubsub_event_items{ + node = <<"foo-1">>, + items = + [#pubsub_event_item{ + id = <<"pep-1">>, + xml_els = [PepPayload]}]}]}]}, + PepTwo = #message{ + to = Peer, + sub_els = + [#pubsub_event{ + items = + [#pubsub_event_items{ + node = <<"foo-2">>, + items = + [#pubsub_event_item{ + id = <<"pep-2">>, + xml_els = [PepPayload]}]}]}]}, %% Wait for the slave to become inactive. wait_for_slave(Config), - %% Should be dropped: - send(Config, ChatState), %% Should be queued (but see below): send(Config, Presence), %% Should replace the previous presence in the queue: send(Config, Presence#presence{type = unavailable}), - %% Should be sent immediately, together with the previous presence: + %% The following two PEP stanzas should be queued (but see below): + send(Config, PepOne), + send(Config, PepTwo), + %% The following two PEP stanzas should replace the previous two: + send(Config, PepOne), + send(Config, PepTwo), + %% Should be queued (but see below): + send(Config, ChatState), + %% Should replace the previous chat state in the queue: + send(Config, ChatState#message{sub_els = [#chatstate{type = composing}]}), + %% Should be sent immediately, together with the queued stanzas: send(Config, Message), %% Wait for the slave to become active. wait_for_slave(Config), @@ -2277,6 +2327,31 @@ client_state_slave(Config) -> wait_for_master(Config), ?recv1(#presence{from = Peer, type = unavailable, sub_els = [#delay{}]}), + #message{ + from = Peer, + sub_els = + [#pubsub_event{ + items = + [#pubsub_event_items{ + node = <<"foo-1">>, + items = + [#pubsub_event_item{ + id = <<"pep-1">>}]}]}, + #delay{}]} = recv(), + #message{ + from = Peer, + sub_els = + [#pubsub_event{ + items = + [#pubsub_event_items{ + node = <<"foo-2">>, + items = + [#pubsub_event_item{ + id = <<"pep-2">>}]}]}, + #delay{}]} = recv(), + ?recv1(#message{from = Peer, thread = <<"1">>, + sub_els = [#chatstate{type = composing}, + #delay{}]}), ?recv1(#message{from = Peer, thread = <<"1">>, body = [#text{data = <<"body">>}], sub_els = [#chatstate{type = active}]}), diff --git a/test/ejabberd_SUITE_data/cert.pem b/test/ejabberd_SUITE_data/cert.pem index d6429dd68..11e18491f 100644 --- a/test/ejabberd_SUITE_data/cert.pem +++ b/test/ejabberd_SUITE_data/cert.pem @@ -1,51 +1,52 @@ -----BEGIN CERTIFICATE----- -MIIDETCCAcmgAwIBAgIEUbsa1zANBgkqhkiG9w0BAQsFADAAMCIYDzIwMTMwNjE0 -MTMzMDAwWhgPMjAyMzA2MTIxMzMwMDhaMAAwggFSMA0GCSqGSIb3DQEBAQUAA4IB -PwAwggE6AoIBMQCXdtt12OFu2j8tlF4x2Da/kbxyMxFnovJXHNzpx7CE/cGthAR5 -w7Cl92pECog2/d6ryIcjqzzCyCeOVQxIaE3Qz8z6+5UjKh3V/j6CKxcK5g1ER7Qe -UgpE00ahHzvOpVANtrkYPGC0SFuTFL+PaylH4HW1xBSc1HD5/w7S1k1pDTz9x8ZC -Z7JOb6NoYsz+rnmWYY2HOG6pyAyQBapIjgzCamgTStA6jTSgoXmCri/dZnJpqjZc -V6AW7feNmMElhPvL30Cb3QB+9ODjN3pDXRR+Jqilu8ZSrpcvcFHOyKt943id1oC+ -Qu8orA0/kVInX7IuV//TciKzcH5FWz75Kb7hORPzH8M2DQcIKqKKVIwNVeJLKmcG -RcUGsgTaz2j0JTa6YLJoczuasDWgRMT0goQpAgMBAAGjLzAtMAwGA1UdEwEB/wQC -MAAwHQYDVR0OBBYEFBW6Si5OY8NPLagdth/JD8R18WMnMA0GCSqGSIb3DQEBCwUA -A4IBMQAPiHxamUumu203pSVwvpWkpgKKOC2EswyFWQbNC6DWQ3LUkiR7MCiFViYt -yiIyEh9wtfymWNF9uwaR2nVrJD5mK9Rt7xDiaT5ZOgNjLzmLeYqSlG41mCU1bmqg -VbxmI1hvPvv3gQ/+WM0lBC6gPGJbVbzlWAIQ1cmevtL1KqOMveZl3VBPxDJD/K9c -Rbrtx2nBKFDEl6hBljz6gsn4o8pxH3CO7qWpgY/MLwqQzEtTKYnaS9ecywNvj+/F -ZE4SMoekw6AGRyE14/3i2xW6EmIpxVU4O6ahEFq6r6ZFbdtWnog5vT0y+/tRMgXp -kCw8puxT2VsYNeJNOybW1IcyN5yluS/FY8iJokdL1JwvhVBVIWaim+T6iwrva7wC -q1E9Nj30F8UbEkbkNqOdC3UlHQW4 +MIIGbDCCBVSgAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJBVTET +MBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQ +dHkgTHRkMB4XDTE2MDUyNDE3NDIyNVoXDTQzMTAxMDE3NDIyNVowVjELMAkGA1UE +BhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdp +ZGdpdHMgUHR5IEx0ZDEPMA0GA1UEAxMGYWN0aXZlMIGfMA0GCSqGSIb3DQEBAQUA +A4GNADCBiQKBgQC+GTA1D1+yiXgLqUhJXkSj3hj5FiqlBAfJT/8OSXYifY4M4HYv +VQrqER2Fs7jdCaeoGWDvwfK/UOV0b1ROnf+T/2bXFs8EOeqjOz4xG2oexNKVrYj9 +ICYAgmSh6Hf2cZJM/YCAISje93Xl2J2w/N7oFC1ZXasPoBIZv3Fgg7hTtQIDAQAB +o4ID2DCCA9QwCQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5l +cmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFEynWiCoZK4tLDk3KM1wMsbrz9Ug +MB8GA1UdIwQYMBaAFND2ZsvHIjITekPKs0ywLfoNEen5MDMGA1UdHwQsMCowKKAm +oCSGImh0dHA6Ly9sb2NhbGhvc3Q6NTI4MC9kYXRhL2NybC5kZXIwNgYIKwYBBQUH +AQEEKjAoMCYGCCsGAQUFBzABhhpodHRwOi8vbG9jYWxob3N0OjUyODAvb2NzcDAL +BgNVHQ8EBAMCBeAwEwYDVR0lBAwwCgYIKwYBBQUHAwkwggLIBgNVHREEggK/MIIC +u6A4BggrBgEFBQcIBaAsDCp0ZXN0X3NpbmdsZSEjJCVeKigpYH4rLTtfPVtde318 +XEBsb2NhbGhvc3SgPwYIKwYBBQUHCAWgMwwxdGVzdF9zaW5nbGUhIyQlXiooKWB+ +Ky07Xz1bXXt9fFxAbW5lc2lhLmxvY2FsaG9zdKA+BggrBgEFBQcIBaAyDDB0ZXN0 +X3NpbmdsZSEjJCVeKigpYH4rLTtfPVtde318XEBteXNxbC5sb2NhbGhvc3SgPgYI +KwYBBQUHCAWgMgwwdGVzdF9zaW5nbGUhIyQlXiooKWB+Ky07Xz1bXXt9fFxAcGdz +cWwubG9jYWxob3N0oD8GCCsGAQUFBwgFoDMMMXRlc3Rfc2luZ2xlISMkJV4qKClg +fistO189W117fXxcQHNxbGl0ZS5sb2NhbGhvc3SgQAYIKwYBBQUHCAWgNAwydGVz +dF9zaW5nbGUhIyQlXiooKWB+Ky07Xz1bXXt9fFxAZXh0YXV0aC5sb2NhbGhvc3Sg +PQYIKwYBBQUHCAWgMQwvdGVzdF9zaW5nbGUhIyQlXiooKWB+Ky07Xz1bXXt9fFxA +bGRhcC5sb2NhbGhvc3SgPQYIKwYBBQUHCAWgMQwvdGVzdF9zaW5nbGUhIyQlXioo +KWB+Ky07Xz1bXXt9fFxAcDFkYi5sb2NhbGhvc3SgPQYIKwYBBQUHCAWgMQwvdGVz +dF9zaW5nbGUhIyQlXiooKWB+Ky07Xz1bXXt9fFxAcmlhay5sb2NhbGhvc3SgPgYI +KwYBBQUHCAWgMgwwdGVzdF9zaW5nbGUhIyQlXiooKWB+Ky07Xz1bXXt9fFxAcmVk +aXMubG9jYWxob3N0oD4GCCsGAQUFBwgFoDIMMHRlc3Rfc2luZ2xlISMkJV4qKClg +fistO189W117fXxcQG1zc3FsLmxvY2FsaG9zdDANBgkqhkiG9w0BAQUFAAOCAQEA +et4jpmpwlE+2bw+/iqCt7sfU/5nPmQ8YtgMB+32wf7DINNJgkwOdkYJpzhlMXKrh +/bn8+Ybmq6MbK0r2R91Uu858xQf8VKExQm44qaGSyL5Ug3jsAWb3GLZSaWQo37e9 +QdDeP8XijCEyr3rum19tRIdiImsRAxJqwfaE4pUSgfCEQMkvb+6//8HSf9RRPToD +o6eAg8QerEtTfxerEdW/0K1ozOrzSrQembWOu+JjvANRl+p59j+1YOWHzS/yQeZl +K3sjFoCvXPvocRnUznvT+TSdy3ORJSjwfEcP5Crim70amZZ6NeMAxfby9wwmmX0x +zkwPCSUXliXke6T88Olj7Q== -----END CERTIFICATE----- -----BEGIN RSA PRIVATE KEY----- -MIIFegIBAAKCATEAl3bbddjhbto/LZReMdg2v5G8cjMRZ6LyVxzc6cewhP3BrYQE -ecOwpfdqRAqINv3eq8iHI6s8wsgnjlUMSGhN0M/M+vuVIyod1f4+gisXCuYNREe0 -HlIKRNNGoR87zqVQDba5GDxgtEhbkxS/j2spR+B1tcQUnNRw+f8O0tZNaQ08/cfG -QmeyTm+jaGLM/q55lmGNhzhuqcgMkAWqSI4MwmpoE0rQOo00oKF5gq4v3WZyaao2 -XFegFu33jZjBJYT7y99Am90AfvTg4zd6Q10UfiaopbvGUq6XL3BRzsirfeN4ndaA -vkLvKKwNP5FSJ1+yLlf/03Iis3B+RVs++Sm+4TkT8x/DNg0HCCqiilSMDVXiSypn -BkXFBrIE2s9o9CU2umCyaHM7mrA1oETE9IKEKQIDAQABAoIBMG8X8a4FbowFLhO7 -YD+FC9sFBMhqZpiyLrfwZqReID3bdeRUEYhSHU4OI/ZWF0Tmfh1Xjq992Koxbrn5 -7XFqd7DxybJJN0E8kfe0bJrDCjqnNBHh2d3nZLrIkGR7aT2PiSEV5bs+BdwVun0t -2bdS7UtX+l5gvJGvTFJBXtkL8GleGV822Vc5gdIAFkXpOdyPkoTXdpw4qwqBnL8/ -TXMYBIgCrXMhEawcNbgPu4iFev2idoU9vXc7ZYD7+8jWB5LJ34cNngguGrnOjLoE -9c3nZy6uYhhMWtcrSsQlrbN5MtY8w2fPH8nhfA651IxXXVxEajd24t2Csttnl7Vz -WS5c+oPaWwt67naMrYCWG3q1zWhDqZUAulZR4DzWzGP+idLS/ojCRdTZO9D1O+XP -fPi0wJECgZkAxh0rTSMCyrJ3VJqEgSPw3yAa1R9cdrTRvV4vRf13Dh8REaHtWt8W -JeT5WLXL7dOii1St1Fgjo82+4iMqx3PQ2eR/1I6dA7Uy71PaSQTCQnupca2Xx8nT -5KcrASBkDAudiKog01eC+zYrW+CbUb9AogMZLJzZinlWQ36pJVkWd9SOv25Eqcv6 -zJEmzYKpnow/m8WKNogVGpUCgZkAw7hQxs5VYVLp2XtDqRSmxfJsfsbUVo7tZnSU -wmejgeNRs7415ZuT142k7qBImrFdYzFcfh2OZnf6D/VIz4Rl7u5YRYRCha/HOGIy -wTe1huDckJ6lH/BkZ/6f9WSzXnNSNeXQY14WymU5V5qYCAdwECSf+xNuBYNwzA7o -vOxPE690w3Ox2qghzRjzsBqAMgvqSyKlBpoMckUCgZhyKgD39IL5V5qYcGqHGLUH -fzK3OdlItq5e19WaGZPv2Us2w/9JbGEQ+UAPNMQNivWSIPwC77+p9zhWjDlssnrZ -9WkMjhpBNrvhWorhpRJkyWo9jfF3OgEXNJX9kjLVFiRzysYbw8RBC1g1G9ulYfbW -5b4uDTz3JTDmuCi00v+1khGoktySlG80TzjzGKayLNPC6jTZc9XleQKBmA0STUrJ -0wf5+qZMxjsPpwfHZhmde+cACrjyBlFpjJELNpSzmnPoTRpzWlWZnN/AAsWyMUQ3 -AyCy2J+iOSeq5wfrITgbWjoFgF+yp0MiTlxgvjpmbg7RBlOvvM0t2ZDwUMhKvf00 -9n6z/f1s1MSMgp6BY7HoHUv++FSYllCv06Qz7q9zFajN29wP046qZm9xPkegW7cy -KKylAoGYTg94GOWlUTz7Pe9PDrDSFVEAi0LcDmul0ntorvEFDvU2pCRK14gyvl9O -IJKVyYcDAqA3uvT+zMAniuf8KXNUCcYeEpfzpT+e2eznhczO8hI14M5U0X0LA8P2 -vn0Y+yUWb9Ppu/dcjvaUA+qR/UTHqjAlAr3hFTKRxXFoGwwzTXCXvZGKOnzJRTpj -LpjI1RG7Weeoyx/8qDs= +MIICXAIBAAKBgQC+GTA1D1+yiXgLqUhJXkSj3hj5FiqlBAfJT/8OSXYifY4M4HYv +VQrqER2Fs7jdCaeoGWDvwfK/UOV0b1ROnf+T/2bXFs8EOeqjOz4xG2oexNKVrYj9 +ICYAgmSh6Hf2cZJM/YCAISje93Xl2J2w/N7oFC1ZXasPoBIZv3Fgg7hTtQIDAQAB +AoGALddtJJ58eVVlOYqs/+RXsRyR8R9DUV/TcNx1qUBV2KNmafyHA4sCgsd10xQv +9D2rzIGyOp8OpswfSSC/t+WqB9+ezSruzMuX6IURdHZbX6aWWX6maICtPKEEkCmI +gaLxE/ojuOXnTEBTkVuVWtuFL9PsK/WGi/FIDzJbwqTWJ4ECQQDy9DrBAQM96B6u +G4XpFzBsfgJZoS+NaMdCwK+/jgcEpI6oxobK8tuGB6drp5jNSuQ905W9n8XjA6Xq +x8/GH9I5AkEAyE5g05HhMlxBWCq+P70pBDIamdHJcPQVL8+6NXkT+mTqqZxxkUy4 +nMfTh5zE6WfmqYNtrmNBDxXUyaoRSBydXQJACnFnCR7DBekxUGiMc/10LmWoMjQU +eC6Vyg/APiqbsJ5mJ2kJKDYSK4uurZjxn3lloCa1HAZ/GgfxHMtj6e86OQJAetq3 +wIwE12KGIZF1xpo6gfxJHHbzWngaVozN5OYyPq2O0CDH9xpbUK2vK8oXbCDx9J5L +s13lFV+Kd3X7y4LhcQJBAKSFg7ht33l8Sa0TdUkY6Tl1NBMCCLf+np+HYrAbQZux +2NtR6nj2YqeOpEe1ibWZm8tj3dzlTm1FCOIpa+pm114= -----END RSA PRIVATE KEY----- diff --git a/test/ejabberd_SUITE_data/ejabberd.ldif b/test/ejabberd_SUITE_data/ejabberd.ldif index 863a07e4f..a98036480 100644 --- a/test/ejabberd_SUITE_data/ejabberd.ldif +++ b/test/ejabberd_SUITE_data/ejabberd.ldif @@ -15,38 +15,38 @@ ou: groups objectClass: organizationalUnit dn: uid=test_single,ou=users,dc=localhost -uid: test_single -mail: test_single@localhost +uid: test_single!#$%^*()`~+-;_=[]{}|\ +mail: test_single!#$%^*()`~+-;_=[]{}|\@localhost objectClass: person jpegPhoto:: /9g= cn: Test Single -password: password +password: password!@#$%^&*()'"`~<>+-/;:_=[]{}|\ dn: uid=test_master,ou=users,dc=localhost -uid: test_master -mail: test_master@localhost +uid: test_master!#$%^*()`~+-;_=[]{}|\ +mail: test_master!#$%^*()`~+-;_=[]{}|\@localhost objectClass: person jpegPhoto:: /9g= cn: Test Master -password: password +password: password!@#$%^&*()'"`~<>+-/;:_=[]{}|\ dn: uid=test_slave,ou=users,dc=localhost -uid: test_slave -mail: test_slave@localhost +uid: test_slave!#$%^*()`~+-;_=[]{}|\ +mail: test_slave!#$%^*()`~+-;_=[]{}|\@localhost objectClass: person jpegPhoto:: /9g= cn: Test Slave -password: password +password: password!@#$%^&*()'"`~<>+-/;:_=[]{}|\ dn: uid=user2,ou=users,dc=localhost uid: user2 mail: user2@localhost objectClass: person cn: Test User 2 -password: password +password: password!@#$%^&*()'"`~<>+-/;:_=[]{}|\ dn: cn=group1,ou=groups,dc=localhost objectClass: posixGroup -memberUid: test_single +memberUid: test_single!#$%^*()`~+-;_=[]{}|\ memberUid: user2 cn: group1 diff --git a/test/ejabberd_SUITE_data/ejabberd.yml b/test/ejabberd_SUITE_data/ejabberd.yml index 869c24c7a..aca547d99 100644 --- a/test/ejabberd_SUITE_data/ejabberd.yml +++ b/test/ejabberd_SUITE_data/ejabberd.yml @@ -213,8 +213,9 @@ Welcome to this XMPP server." db_type: internal mod_carboncopy: [] mod_client_state: - drop_chat_states: true queue_presence: true + queue_chat_states: true + queue_pep: true mod_adhoc: [] mod_configure: [] mod_disco: [] @@ -269,8 +270,9 @@ Welcome to this XMPP server." db_type: internal mod_carboncopy: [] mod_client_state: - drop_chat_states: true queue_presence: true + queue_chat_states: true + queue_pep: true mod_adhoc: [] mod_configure: [] mod_disco: [] @@ -417,6 +419,7 @@ listen: starttls: true shaper: c2s_shaper access: c2s + resume_timeout: 3 - port: @@s2s_port@@ module: ejabberd_s2s_in diff --git a/test/ejabberd_commands_mock_test.exs b/test/ejabberd_commands_mock_test.exs index 285585034..487cf6a4b 100644 --- a/test/ejabberd_commands_mock_test.exs +++ b/test/ejabberd_commands_mock_test.exs @@ -127,6 +127,8 @@ defmodule EjabberdCommandsMockTest do test "API command can be registered and executed" do + mock_commands_config + # Create & register a mocked command test() -> :result command_name = :test function = :test_command @@ -142,6 +144,8 @@ defmodule EjabberdCommandsMockTest do end test "API command with versions can be registered and executed" do + mock_commands_config + command_name = :test function1 = :test_command1 @@ -409,13 +413,13 @@ defmodule EjabberdCommandsMockTest do :meck.expect(:ejabberd_config, :get_myhosts, fn() -> [@domain] end) :meck.new :acl - :meck.expect(:acl, :match_rule, - fn(@domain, :commands_admin_access, user) -> - case :jlib.make_jid(@admin, @domain, "") do - ^user -> :allow - _ -> :deny - end - (@domain, :all, _user) -> + :meck.expect(:acl, :access_matches, + fn(:commands_admin_access, info, _scope) -> + case info do + %{usr: {@admin, @domain, _}} -> :allow + _ -> :deny + end; + (:all, _, _scope) -> :allow end) end diff --git a/test/elixir_SUITE.erl b/test/elixir_SUITE.erl index 48cc94f8e..aaef9151d 100644 --- a/test/elixir_SUITE.erl +++ b/test/elixir_SUITE.erl @@ -18,6 +18,7 @@ -compile(export_all). init_per_suite(Config) -> + suite:setup_ejabberd_lib_path(Config), check_meck(), code:add_pathz(filename:join(test_dir(), "../include")), Config. diff --git a/test/mod_admin_extra_test.exs b/test/mod_admin_extra_test.exs index 2029cf686..761b07b7c 100644 --- a/test/mod_admin_extra_test.exs +++ b/test/mod_admin_extra_test.exs @@ -43,6 +43,7 @@ defmodule EjabberdModAdminExtraTest do _ -> :ok end :ejabberd_commands.init + :ok = :ejabberd_config.start([@domain], []) :mod_admin_extra.start(@domain, []) :sel_application.start_app(:moka) {:ok, _pid} = :ejabberd_hooks.start_link diff --git a/test/mod_http_api_mock_test.exs b/test/mod_http_api_mock_test.exs index 78832d7a5..47b1fe94a 100644 --- a/test/mod_http_api_mock_test.exs +++ b/test/mod_http_api_mock_test.exs @@ -75,7 +75,7 @@ defmodule ModHttpApiMockTest do :meck.expect(:ejabberd_commands, :get_commands, fn () -> [@acommand] end) :meck.expect(:ejabberd_commands, :execute_command, - fn (:undefined, {@user, @domain, @userpass, false}, @acommand, [], @version) -> + fn (:undefined, {@user, @domain, @userpass, false}, @acommand, [], @version, _) -> :ok end) @@ -129,7 +129,7 @@ defmodule ModHttpApiMockTest do fn () -> [@acommand] end) :meck.expect(:ejabberd_commands, :execute_command, fn (:undefined, {@user, @domain, {:oauth, _token}, false}, - @acommand, [], @version) -> + @acommand, [], @version, _) -> :ok end) diff --git a/test/mod_http_api_test.exs b/test/mod_http_api_test.exs index 9432ae471..99b8d9b28 100644 --- a/test/mod_http_api_test.exs +++ b/test/mod_http_api_test.exs @@ -39,6 +39,7 @@ defmodule ModHttpApiTest do end test "We can expose several commands to API at a time" do + setup_mocks() :ejabberd_config.add_local_option(:commands, [[{:add_commands, [:open_cmd, :user_cmd]}]]) commands = :ejabberd_commands.get_commands() assert Enum.member?(commands, :open_cmd) @@ -46,21 +47,24 @@ defmodule ModHttpApiTest do end test "We can call open commands without authentication" do + setup_mocks() :ejabberd_config.add_local_option(:commands, [[{:add_commands, [:open_cmd]}]]) - request = request(method: :POST, data: "[]") + request = request(method: :POST, ip: {{127,0,0,1},50000}, data: "[]") {200, _, _} = :mod_http_api.process(["open_cmd"], request) end # This related to the commands config file option test "Attempting to access a command that is not exposed as HTTP API returns 401" do + setup_mocks() :ejabberd_config.add_local_option(:commands, []) - request = request(method: :POST, data: "[]") + request = request(method: :POST, ip: {{127,0,0,1},50000}, data: "[]") {401, _, _} = :mod_http_api.process(["open_cmd"], request) end test "Call to user, admin or restricted commands without authentication are rejected" do + setup_mocks() :ejabberd_config.add_local_option(:commands, [[{:add_commands, [:user_cmd, :admin_cmd, :restricted]}]]) - request = request(method: :POST, data: "[]") + request = request(method: :POST, ip: {{127,0,0,1},50000}, data: "[]") {401, _, _} = :mod_http_api.process(["user_cmd"], request) {401, _, _} = :mod_http_api.process(["admin_cmd"], request) {401, _, _} = :mod_http_api.process(["restricted_cmd"], request) @@ -68,6 +72,7 @@ defmodule ModHttpApiTest do @tag pending: true test "If admin_ip_access is enabled, we can call restricted API without authentication from that IP" do + setup_mocks() end # Define a set of test commands that we expose through API @@ -86,10 +91,27 @@ defmodule ModHttpApiTest do end def open_cmd, do: :ok - def user_cmd, do: :ok + def user_cmd(_, _), do: :ok def admin_cmd, do: :ok def restricted_cmd, do: :ok + defp setup_mocks() do + :meck.unload + mock(:gen_mod, :get_module_opt, + fn (_server, :mod_http_api, admin_ip_access, _, _) -> + [{:allow, [{:ip, {{127,0,0,2}, 32}}]}] + end) + end + + defp mock(module, function, fun) do + try do + :meck.new(module) + catch + :error, {:already_started, _pid} -> :ok + end + :meck.expect(module, function, fun) + end + defp unregister_commands(commands) do try do :ejabberd_commands.unregister_commands(commands) diff --git a/test/mod_roster_mock.exs b/test/mod_roster_mock.exs index b1251ba86..ae990a6b1 100644 --- a/test/mod_roster_mock.exs +++ b/test/mod_roster_mock.exs @@ -45,41 +45,32 @@ defmodule ModRosterMock do try do module_mock = :moka.start(module) - :moka.replace(module_mock, :mod_roster, :invalidate_roster_cache, + :moka.replace(module_mock, :mod_roster_mnesia, :invalidate_roster_cache, fn (_user, _server) -> :ok end) :moka.load(module_mock) - roster_mock = :moka.start(:mod_roster) - - :moka.replace(roster_mock, :gen_mod, :db_type, - fn (_host, _opts) -> - {:none} - end) - - :moka.replace(roster_mock, :gen_iq_handler, :add_iq_handler, + roster_mock0 = :moka.start(:mod_roster) + :moka.replace(roster_mock0, :gen_iq_handler, :add_iq_handler, fn (_module, _host, _ns, _m, _f, _iqdisc) -> :ok end) - :moka.replace(roster_mock, :gen_iq_handler, :remove_iq_handler, + :moka.replace(roster_mock0, :gen_iq_handler, :remove_iq_handler, fn (_module, _host, _ns) -> :ok end) - - :moka.replace(roster_mock, :transaction, - fn (_server, function) -> - {:atomic, function.()} + :moka.replace(roster_mock0, :gen_mod, :db_mod, + fn (_host, _mod) -> + :mod_roster_mnesia end) - - :moka.replace(roster_mock, :get_roster, - fn (user, domain) -> - to_records(get_roster(user, domain)) + :moka.replace(roster_mock0, :gen_mod, :db_mod, + fn (_host, _opts, _mod) -> + :mod_roster_mnesia end) - - :moka.replace(roster_mock, :update_roster_t, + :moka.replace(roster_mock0, :update_roster_t, fn (user, domain, {u, d, _r}, item) -> add_roster_item(user, domain, u<>"@"<>d, roster(item, :name), @@ -89,10 +80,32 @@ defmodule ModRosterMock do roster(item, :askmessage)) end) - :moka.replace(roster_mock, :del_roster_t, + :moka.replace(roster_mock0, :del_roster_t, fn (user, domain, jid) -> remove_roster_item(user, domain, :jid.to_string(jid)) end) + :moka.replace(roster_mock0, :get_roster, + fn (user, domain) -> + to_records(get_roster(user, domain)) + end) + + :moka.load(roster_mock0) + + roster_mock = :moka.start(:mod_roster_mnesia) + :moka.replace(roster_mock, :gen_mod, :db_type, + fn (_host, _opts) -> + {:none} + end) + + :moka.replace(roster_mock, :transaction, + fn (_server, function) -> + {:atomic, function.()} + end) + + :moka.replace(roster_mock, :update_tables, + fn () -> + :ok + end) :moka.load(roster_mock) @@ -104,7 +117,7 @@ defmodule ModRosterMock do def mock_with_meck do # mock(:gen_mod, :db_type, -# fn (_server, :mod_roster) -> +# fn (_server, :mod_roster_mnesia) -> # :mnesia # end) # @@ -119,12 +132,16 @@ defmodule ModRosterMock do # {:atomic, :ok} # end) - mock(:mod_roster, :transaction, + mock(:mod_roster_mnesia, :init, + fn (_server, _opts) -> + :ok + end) + mock(:mod_roster_mnesia, :transaction, fn (_server, function) -> {:atomic, function.()} end) - mock(:mod_roster, :update_roster_t, + mock(:mod_roster_mnesia, :update_roster_t, fn (user, domain, {u, d, _r}, item) -> add_roster_item(user, domain, u<>"@"<>d, roster(item, :name), @@ -134,7 +151,7 @@ defmodule ModRosterMock do roster(item, :askmessage)) end) - mock(:mod_roster, :invalidate_roster_cache, + mock(:mod_roster_mnesia, :invalidate_roster_cache, fn (_user, _server) -> :ok end) diff --git a/test/suite.erl b/test/suite.erl index c605ed709..c5593c4cf 100644 --- a/test/suite.erl +++ b/test/suite.erl @@ -12,6 +12,7 @@ -compile(export_all). -include("suite.hrl"). +-include_lib("kernel/include/file.hrl"). %%%=================================================================== %%% API @@ -47,6 +48,7 @@ init_config(Config) -> ]), ConfigPath = filename:join([CWD, "ejabberd.yml"]), ok = file:write_file(ConfigPath, CfgContent), + setup_ejabberd_lib_path(Config), ok = application:load(sasl), ok = application:load(mnesia), ok = application:load(ejabberd), @@ -57,19 +59,40 @@ init_config(Config) -> [{server_port, ct:get_config(c2s_port, 5222)}, {server_host, "localhost"}, {server, ?COMMON_VHOST}, - {user, <<"test_single">>}, - {master_nick, <<"master_nick">>}, - {slave_nick, <<"slave_nick">>}, - {room_subject, <<"hello, world!">>}, + {user, <<"test_single!#$%^*()`~+-;_=[]{}|\\">>}, + {master_nick, <<"master_nick!@#$%^&*()'\"`~<>+-/;:_=[]{}|\\">>}, + {slave_nick, <<"slave_nick!@#$%^&*()'\"`~<>+-/;:_=[]{}|\\">>}, + {room_subject, <<"hello, world!@#$%^&*()'\"`~<>+-/;:_=[]{}|\\">>}, {certfile, CertFile}, {base_dir, BaseDir}, - {resource, <<"resource">>}, - {master_resource, <<"master_resource">>}, - {slave_resource, <<"slave_resource">>}, + {resource, <<"resource!@#$%^&*()'\"`~<>+-/;:_=[]{}|\\">>}, + {master_resource, <<"master_resource!@#$%^&*()'\"`~<>+-/;:_=[]{}|\\">>}, + {slave_resource, <<"slave_resource!@#$%^&*()'\"`~<>+-/;:_=[]{}|\\">>}, {password, <<"password!@#$%^&*()'\"`~<>+-/;:_=[]{}|\\">>}, {backends, get_config_backends()} |Config]. +find_top_dir(Dir) -> + case file:read_file_info(filename:join([Dir, ebin])) of + {ok, #file_info{type = directory}} -> + Dir; + _ -> + find_top_dir(filename:dirname(Dir)) + end. + +setup_ejabberd_lib_path(Config) -> + case code:lib_dir(ejabberd) of + {error, _} -> + DataDir = proplists:get_value(data_dir, Config), + {ok, CWD} = file:get_cwd(), + NewEjPath = filename:join([CWD, "ejabberd-0.0.1"]), + TopDir = find_top_dir(DataDir), + ok = file:make_symlink(TopDir, NewEjPath), + code:replace_path(ejabberd, NewEjPath); + _ -> + ok + end. + %% Read environment variable CT_DB=riak,mysql to limit the backends to test. %% You can thus limit the backend you want to test with: %% CT_BACKENDS=riak,mysql rebar ct suites=ejabberd @@ -294,7 +317,12 @@ sasl_new(<<"DIGEST-MD5">>, User, Server, Password) -> MyResponse = response(User, Password, Nonce, AuthzId, Realm, CNonce, DigestURI, NC, QOP, <<"AUTHENTICATE">>), - Resp = <<"username=\"", User/binary, "\",realm=\"", + SUser = << <<(case Char of + $" -> <<"\\\"">>; + $\\ -> <<"\\\\">>; + _ -> <<Char>> + end)/binary>> || <<Char>> <= User >>, + Resp = <<"username=\"", SUser/binary, "\",realm=\"", Realm/binary, "\",nonce=\"", Nonce/binary, "\",cnonce=\"", CNonce/binary, "\",nc=", NC/binary, ",qop=", QOP/binary, ",digest-uri=\"", |