Compare commits

...

2 Commits

Author SHA1 Message Date
Tulir Asokan 9a8f8433b0 Bump version to 0.6.0 2019-07-09 19:43:56 +03:00
Tulir Asokan 4942789213 Fix vulnerability in event handling 2019-07-09 19:43:37 +03:00
3 changed files with 62 additions and 51 deletions
+1 -1
View File
@@ -1,2 +1,2 @@
__version__ = "0.6.0rc2" __version__ = "0.6.0"
__author__ = "Tulir Asokan <tulir@maunium.net>" __author__ = "Tulir Asokan <tulir@maunium.net>"
+59 -48
View File
@@ -399,12 +399,24 @@ class MatrixHandler:
return (sender == self.az.bot_mxid return (sender == self.az.bot_mxid
or pu.Puppet.get_id_from_mxid(sender) is not None) or pu.Puppet.get_id_from_mxid(sender) is not None)
async def try_handle_event(self, evt: MatrixEvent) -> None: async def try_handle_ephemeral_event(self, evt: MatrixEvent) -> None:
try: try:
await self.handle_event(evt) await self.handle_ephemeral_event(evt)
except Exception: except Exception:
self.log.exception("Error handling manually received Matrix event") self.log.exception("Error handling manually received Matrix event")
async def handle_ephemeral_event(self, evt: MatrixEvent) -> None:
evt_type = evt.get("type", "m.unknown") # type: str
room_id = evt.get("room_id", None) # type: Optional[MatrixRoomID]
sender = evt.get("sender", None) # type: Optional[MatrixUserID]
content = evt.get("content", {}) # type: Dict
if evt_type == "m.receipt":
await self.handle_read_receipts(room_id, self.parse_read_receipts(content))
elif evt_type == "m.presence":
await self.handle_presence(sender, content.get("presence", "offline"))
elif evt_type == "m.typing":
await self.handle_typing(room_id, content.get("user_ids", []))
async def handle_event(self, evt: MatrixEvent) -> None: async def handle_event(self, evt: MatrixEvent) -> None:
if self.filter_matrix_event(evt): if self.filter_matrix_event(evt):
return return
@@ -414,53 +426,52 @@ class MatrixHandler:
room_id = evt.get("room_id", None) # type: Optional[MatrixRoomID] room_id = evt.get("room_id", None) # type: Optional[MatrixRoomID]
event_id = evt.get("event_id", None) # type: Optional[MatrixEventID] event_id = evt.get("event_id", None) # type: Optional[MatrixEventID]
sender = evt.get("sender", None) # type: Optional[MatrixUserID] sender = evt.get("sender", None) # type: Optional[MatrixUserID]
state_key = evt.get("state_key", None)
content = evt.get("content", {}) # type: Dict content = evt.get("content", {}) # type: Dict
if evt_type == "m.room.member": if state_key is not None:
state_key = evt["state_key"] # type: MatrixUserID if evt_type == "m.room.member":
prev_content = evt.get("unsigned", {}).get("prev_content", {}) # type: Dict prev_content = evt.get("unsigned", {}).get("prev_content", {}) # type: Dict
membership = content.get("membership", "") # type: str membership = content.get("membership", "") # type: str
prev_membership = prev_content.get("membership", "leave") # type: str prev_membership = prev_content.get("membership", "leave") # type: str
if membership == prev_membership: if membership == prev_membership:
match = re.compile("@(.+):(.+)").match(state_key) # type: Match match = re.compile("@(.+):(.+)").match(state_key) # type: Match
mxid = match.group(0) # type: str mxid = match.group(0) # type: str
displayname = content.get("displayname", None) or mxid # type: str displayname = content.get("displayname", None) or mxid # type: str
prev_displayname = prev_content.get("displayname", None) or mxid # type: str prev_displayname = prev_content.get("displayname", None) or mxid # type: str
if displayname != prev_displayname: if displayname != prev_displayname:
await self.handle_name_change(room_id, state_key, displayname, await self.handle_name_change(room_id, state_key, displayname,
prev_displayname, event_id) prev_displayname, event_id)
elif membership == "invite": elif membership == "invite":
await self.handle_invite(room_id, state_key, sender) await self.handle_invite(room_id, state_key, sender)
elif prev_membership == "join" and membership == "leave": elif prev_membership == "join" and membership == "leave":
await self.handle_part(room_id, state_key, sender, event_id) await self.handle_part(room_id, state_key, sender, event_id)
elif membership == "join": elif membership == "join":
await self.handle_join(room_id, state_key, event_id) await self.handle_join(room_id, state_key, event_id)
elif evt_type in ("m.room.message", "m.sticker"): elif evt_type == "m.room.power_levels":
if evt_type != "m.room.message": prev_content = evt.get("unsigned", {}).get("prev_content", {})
content["msgtype"] = evt_type await self.handle_power_levels(room_id, sender, evt["content"], prev_content)
await self.handle_message(room_id, sender, content, event_id) elif evt_type in ("m.room.name", "m.room.avatar", "m.room.topic"):
elif evt_type == "m.room.redaction": await self.handle_room_meta(evt_type, room_id, sender, evt["content"])
await self.handle_redaction(room_id, sender, evt["redacts"]) elif evt_type == "m.room.pinned_events":
elif evt_type == "m.room.power_levels": new_events = set(evt["content"]["pinned"])
prev_content = evt.get("unsigned", {}).get("prev_content", {}) try:
await self.handle_power_levels(room_id, sender, evt["content"], prev_content) old_events = set(evt["unsigned"]["prev_content"]["pinned"])
elif evt_type in ("m.room.name", "m.room.avatar", "m.room.topic"): except KeyError:
await self.handle_room_meta(evt_type, room_id, sender, evt["content"]) old_events = set()
elif evt_type == "m.room.pinned_events": await self.handle_room_pin(room_id, sender, new_events, old_events)
new_events = set(evt["content"]["pinned"]) elif evt_type == "m.room.tombstone":
try: await self.handle_room_upgrade(room_id, evt["content"]["replacement_room"])
old_events = set(evt["unsigned"]["prev_content"]["pinned"]) else:
except KeyError: return
old_events = set()
await self.handle_room_pin(room_id, sender, new_events, old_events)
elif evt_type == "m.room.tombstone":
await self.handle_room_upgrade(room_id, evt["content"]["replacement_room"])
elif evt_type == "m.receipt":
await self.handle_read_receipts(room_id, self.parse_read_receipts(content))
elif evt_type == "m.presence":
await self.handle_presence(sender, content.get("presence", "offline"))
elif evt_type == "m.typing":
await self.handle_typing(room_id, content.get("user_ids", []))
else: else:
return if evt_type in ("m.room.message", "m.sticker"):
if evt_type != "m.room.message":
content["msgtype"] = evt_type
await self.handle_message(room_id, sender, content, event_id)
elif evt_type == "m.room.redaction":
await self.handle_redaction(room_id, sender, evt["redacts"])
else:
return
if EVENT_TIME: if EVENT_TIME:
EVENT_TIME.labels(event_type=evt_type).observe(time.time() - start_time) EVENT_TIME.labels(event_type=evt_type).observe(time.time() - start_time)
+2 -2
View File
@@ -221,13 +221,13 @@ class Puppet:
return new_events return new_events
def handle_sync(self, presence: List, ephemeral: Dict) -> None: def handle_sync(self, presence: List, ephemeral: Dict) -> None:
presence_events = [self.mx.try_handle_event(event) for event in presence] presence_events = [self.mx.try_handle_ephemeral_event(event) for event in presence]
for room_id, events in ephemeral.items(): for room_id, events in ephemeral.items():
for event in events: for event in events:
event["room_id"] = room_id event["room_id"] = room_id
ephemeral_events = [self.mx.try_handle_event(event) ephemeral_events = [self.mx.try_handle_ephemeral_event(event)
for events in ephemeral.values() for events in ephemeral.values()
for event in self.filter_events(events)] for event in self.filter_events(events)]