You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

276 lines
9.7 KiB

  1. # Copyright 2018 New Vector Ltd
  2. # Copyright 2019 Matrix.org Federation C.I.C
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License");
  5. # you may not use this file except in compliance with the License.
  6. # You may obtain a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS,
  12. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. # See the License for the specific language governing permissions and
  14. # limitations under the License.
  15. import logging
  16. from parameterized import parameterized
  17. from twisted.test.proto_helpers import MemoryReactor
  18. from synapse.api.room_versions import KNOWN_ROOM_VERSIONS
  19. from synapse.config.server import DEFAULT_ROOM_VERSION
  20. from synapse.crypto.event_signing import add_hashes_and_signatures
  21. from synapse.events import make_event_from_dict
  22. from synapse.federation.federation_server import server_matches_acl_event
  23. from synapse.rest import admin
  24. from synapse.rest.client import login, room
  25. from synapse.server import HomeServer
  26. from synapse.types import JsonDict
  27. from synapse.util import Clock
  28. from tests import unittest
  29. from tests.unittest import override_config
  30. class FederationServerTests(unittest.FederatingHomeserverTestCase):
  31. servlets = [
  32. admin.register_servlets,
  33. room.register_servlets,
  34. login.register_servlets,
  35. ]
  36. @parameterized.expand([(b"",), (b"foo",), (b'{"limit": Infinity}',)])
  37. def test_bad_request(self, query_content):
  38. """
  39. Querying with bad data returns a reasonable error code.
  40. """
  41. u1 = self.register_user("u1", "pass")
  42. u1_token = self.login("u1", "pass")
  43. room_1 = self.helper.create_room_as(u1, tok=u1_token)
  44. self.inject_room_member(room_1, "@user:other.example.com", "join")
  45. "/get_missing_events/(?P<room_id>[^/]*)/?"
  46. channel = self.make_request(
  47. "POST",
  48. "/_matrix/federation/v1/get_missing_events/%s" % (room_1,),
  49. query_content,
  50. )
  51. self.assertEqual(400, channel.code, channel.result)
  52. self.assertEqual(channel.json_body["errcode"], "M_NOT_JSON")
  53. class ServerACLsTestCase(unittest.TestCase):
  54. def test_blacklisted_server(self):
  55. e = _create_acl_event({"allow": ["*"], "deny": ["evil.com"]})
  56. logging.info("ACL event: %s", e.content)
  57. self.assertFalse(server_matches_acl_event("evil.com", e))
  58. self.assertFalse(server_matches_acl_event("EVIL.COM", e))
  59. self.assertTrue(server_matches_acl_event("evil.com.au", e))
  60. self.assertTrue(server_matches_acl_event("honestly.not.evil.com", e))
  61. def test_block_ip_literals(self):
  62. e = _create_acl_event({"allow_ip_literals": False, "allow": ["*"]})
  63. logging.info("ACL event: %s", e.content)
  64. self.assertFalse(server_matches_acl_event("1.2.3.4", e))
  65. self.assertTrue(server_matches_acl_event("1a.2.3.4", e))
  66. self.assertFalse(server_matches_acl_event("[1:2::]", e))
  67. self.assertTrue(server_matches_acl_event("1:2:3:4", e))
  68. def test_wildcard_matching(self):
  69. e = _create_acl_event({"allow": ["good*.com"]})
  70. self.assertTrue(
  71. server_matches_acl_event("good.com", e),
  72. "* matches 0 characters",
  73. )
  74. self.assertTrue(
  75. server_matches_acl_event("GOOD.COM", e),
  76. "pattern is case-insensitive",
  77. )
  78. self.assertTrue(
  79. server_matches_acl_event("good.aa.com", e),
  80. "* matches several characters, including '.'",
  81. )
  82. self.assertFalse(
  83. server_matches_acl_event("ishgood.com", e),
  84. "pattern does not allow prefixes",
  85. )
  86. class StateQueryTests(unittest.FederatingHomeserverTestCase):
  87. servlets = [
  88. admin.register_servlets,
  89. room.register_servlets,
  90. login.register_servlets,
  91. ]
  92. def test_needs_to_be_in_room(self):
  93. """/v1/state/<room_id> requires the server to be in the room"""
  94. u1 = self.register_user("u1", "pass")
  95. u1_token = self.login("u1", "pass")
  96. room_1 = self.helper.create_room_as(u1, tok=u1_token)
  97. channel = self.make_signed_federation_request(
  98. "GET", "/_matrix/federation/v1/state/%s?event_id=xyz" % (room_1,)
  99. )
  100. self.assertEqual(403, channel.code, channel.result)
  101. self.assertEqual(channel.json_body["errcode"], "M_FORBIDDEN")
  102. class SendJoinFederationTests(unittest.FederatingHomeserverTestCase):
  103. servlets = [
  104. admin.register_servlets,
  105. room.register_servlets,
  106. login.register_servlets,
  107. ]
  108. def prepare(self, reactor: MemoryReactor, clock: Clock, hs: HomeServer):
  109. super().prepare(reactor, clock, hs)
  110. # create the room
  111. creator_user_id = self.register_user("kermit", "test")
  112. tok = self.login("kermit", "test")
  113. self._room_id = self.helper.create_room_as(
  114. room_creator=creator_user_id, tok=tok
  115. )
  116. # a second member on the orgin HS
  117. second_member_user_id = self.register_user("fozzie", "bear")
  118. tok2 = self.login("fozzie", "bear")
  119. self.helper.join(self._room_id, second_member_user_id, tok=tok2)
  120. def _make_join(self, user_id) -> JsonDict:
  121. channel = self.make_signed_federation_request(
  122. "GET",
  123. f"/_matrix/federation/v1/make_join/{self._room_id}/{user_id}"
  124. f"?ver={DEFAULT_ROOM_VERSION}",
  125. )
  126. self.assertEqual(channel.code, 200, channel.json_body)
  127. return channel.json_body
  128. def test_send_join(self):
  129. """happy-path test of send_join"""
  130. joining_user = "@misspiggy:" + self.OTHER_SERVER_NAME
  131. join_result = self._make_join(joining_user)
  132. join_event_dict = join_result["event"]
  133. add_hashes_and_signatures(
  134. KNOWN_ROOM_VERSIONS[DEFAULT_ROOM_VERSION],
  135. join_event_dict,
  136. signature_name=self.OTHER_SERVER_NAME,
  137. signing_key=self.OTHER_SERVER_SIGNATURE_KEY,
  138. )
  139. channel = self.make_signed_federation_request(
  140. "PUT",
  141. f"/_matrix/federation/v2/send_join/{self._room_id}/x",
  142. content=join_event_dict,
  143. )
  144. self.assertEqual(channel.code, 200, channel.json_body)
  145. # we should get complete room state back
  146. returned_state = [
  147. (ev["type"], ev["state_key"]) for ev in channel.json_body["state"]
  148. ]
  149. self.assertCountEqual(
  150. returned_state,
  151. [
  152. ("m.room.create", ""),
  153. ("m.room.power_levels", ""),
  154. ("m.room.join_rules", ""),
  155. ("m.room.history_visibility", ""),
  156. ("m.room.member", "@kermit:test"),
  157. ("m.room.member", "@fozzie:test"),
  158. # nb: *not* the joining user
  159. ],
  160. )
  161. # also check the auth chain
  162. returned_auth_chain_events = [
  163. (ev["type"], ev["state_key"]) for ev in channel.json_body["auth_chain"]
  164. ]
  165. self.assertCountEqual(
  166. returned_auth_chain_events,
  167. [
  168. ("m.room.create", ""),
  169. ("m.room.member", "@kermit:test"),
  170. ("m.room.power_levels", ""),
  171. ("m.room.join_rules", ""),
  172. ],
  173. )
  174. # the room should show that the new user is a member
  175. r = self.get_success(
  176. self.hs.get_state_handler().get_current_state(self._room_id)
  177. )
  178. self.assertEqual(r[("m.room.member", joining_user)].membership, "join")
  179. @override_config({"experimental_features": {"msc3706_enabled": True}})
  180. def test_send_join_partial_state(self):
  181. """When MSC3706 support is enabled, /send_join should return partial state"""
  182. joining_user = "@misspiggy:" + self.OTHER_SERVER_NAME
  183. join_result = self._make_join(joining_user)
  184. join_event_dict = join_result["event"]
  185. add_hashes_and_signatures(
  186. KNOWN_ROOM_VERSIONS[DEFAULT_ROOM_VERSION],
  187. join_event_dict,
  188. signature_name=self.OTHER_SERVER_NAME,
  189. signing_key=self.OTHER_SERVER_SIGNATURE_KEY,
  190. )
  191. channel = self.make_signed_federation_request(
  192. "PUT",
  193. f"/_matrix/federation/v2/send_join/{self._room_id}/x?org.matrix.msc3706.partial_state=true",
  194. content=join_event_dict,
  195. )
  196. self.assertEqual(channel.code, 200, channel.json_body)
  197. # expect a reduced room state
  198. returned_state = [
  199. (ev["type"], ev["state_key"]) for ev in channel.json_body["state"]
  200. ]
  201. self.assertCountEqual(
  202. returned_state,
  203. [
  204. ("m.room.create", ""),
  205. ("m.room.power_levels", ""),
  206. ("m.room.join_rules", ""),
  207. ("m.room.history_visibility", ""),
  208. ],
  209. )
  210. # the auth chain should not include anything already in "state"
  211. returned_auth_chain_events = [
  212. (ev["type"], ev["state_key"]) for ev in channel.json_body["auth_chain"]
  213. ]
  214. self.assertCountEqual(
  215. returned_auth_chain_events,
  216. [
  217. ("m.room.member", "@kermit:test"),
  218. ],
  219. )
  220. # the room should show that the new user is a member
  221. r = self.get_success(
  222. self.hs.get_state_handler().get_current_state(self._room_id)
  223. )
  224. self.assertEqual(r[("m.room.member", joining_user)].membership, "join")
  225. def _create_acl_event(content):
  226. return make_event_from_dict(
  227. {
  228. "room_id": "!a:b",
  229. "event_id": "$a:b",
  230. "type": "m.room.server_acls",
  231. "sender": "@a:b",
  232. "content": content,
  233. }
  234. )