From 50ec2551f8c318abc7e62fcab11823d77754acf5 Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Sun, 29 Mar 2020 14:28:15 +0300 Subject: [PATCH] Remove all automatic matrix-nio state receiving All state is now fed to nio from the appservice state event stream instead of /sync. This should remove all race conditions of trying to encrypt messages before nio is synced. --- mautrix_telegram/matrix.py | 58 ++++++----------------------- mautrix_telegram/portal/metadata.py | 23 +++++++----- requirements.txt | 2 +- 3 files changed, 25 insertions(+), 58 deletions(-) diff --git a/mautrix_telegram/matrix.py b/mautrix_telegram/matrix.py index 8e1b0038..70ab4a33 100644 --- a/mautrix_telegram/matrix.py +++ b/mautrix_telegram/matrix.py @@ -13,7 +13,7 @@ # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . -from typing import Dict, Set, Tuple, Union, Iterable, Optional, TYPE_CHECKING +from typing import Dict, Set, Tuple, Union, Iterable, List, TYPE_CHECKING from mautrix.bridge import BaseMatrixHandler from mautrix.types import (Event, EventType, RoomID, UserID, EventID, ReceiptEvent, ReceiptType, @@ -38,11 +38,6 @@ except ImportError: Histogram = None EVENT_TIME = None -try: - from mautrix.bridge.e2ee import EncryptionManager -except ImportError: - EncryptionManager = None - RoomMetaStateEventContent = Union[RoomNameStateEventContent, RoomAvatarStateEventContent, RoomTopicStateEventContent] @@ -50,31 +45,14 @@ RoomMetaStateEventContent = Union[RoomNameStateEventContent, RoomAvatarStateEven class MatrixHandler(BaseMatrixHandler): bot: 'Bot' commands: 'com.CommandProcessor' - e2ee: Optional[EncryptionManager] previously_typing: Dict[RoomID, Set[UserID]] def __init__(self, context: 'Context') -> None: super(MatrixHandler, self).__init__(context.az, context.config, loop=context.loop, command_processor=com.CommandProcessor(context)) - self.e2ee = None - if self.config["bridge.encryption.allow"]: - if not EncryptionManager: - self.log.error("Encryption enabled in config, but dependencies not installed.") - elif not self.config["bridge.login_shared_secret"]: - self.log.warning("Encryption enabled in config, but login_shared_secret not set.") - else: - self.e2ee = EncryptionManager( - bot_mxid=self.az.bot_mxid, - login_shared_secret=self.config["bridge.login_shared_secret"], - homeserver_address=self.config["homeserver.address"], loop=context.loop) self.bot = context.bot self.previously_typing = {} - async def init_as_bot(self) -> None: - await super().init_as_bot() - if self.e2ee: - await self.e2ee.start() - async def get_user(self, user_id: UserID) -> 'u.User': return await u.User.get_by_mxid(user_id).ensure_started() @@ -129,7 +107,7 @@ class MatrixHandler(BaseMatrixHandler): portal.mxid = room_id e2be_ok = None if self.config["bridge.encryption.default"] and self.e2ee: - e2be_ok = await self._enable_dm_encryption(portal) + e2be_ok = await self.enable_dm_encryption(portal, members=members) portal.save() inviter.register_portal(portal) if e2be_ok is True: @@ -149,27 +127,15 @@ class MatrixHandler(BaseMatrixHandler): await intent.send_notice(room_id, "This puppet will remain inactive until a " "Telegram chat is created for this room.") - async def _enable_dm_encryption(self, portal: po.Portal) -> bool: - try: - await portal.main_intent.invite_user(portal.mxid, self.az.bot_mxid) - await self.az.intent.join_room_by_id(portal.mxid) - await portal.main_intent.send_state_event(portal.mxid, EventType.ROOM_ENCRYPTION, { - "algorithm": "m.megolm.v1.aes-sha2" - }) - # TODO feed info about room to matrix-nio - except Exception: - self.log.warning(f"Failed to enable end-to-bridge encryption in {portal.mxid}", - exc_info=True) - return False - - try: - puppet = pu.Puppet.get(portal.tgid) - await portal.main_intent.set_room_name(portal.mxid, puppet.displayname) - except Exception: - self.log.warning(f"Failed to set room name for {portal.mxid}", exc_info=True) - - portal.encrypted = True - return True + async def enable_dm_encryption(self, portal: po.Portal, members: List[UserID]) -> bool: + ok = await super().enable_dm_encryption(portal, members) + if ok: + try: + puppet = pu.Puppet.get(portal.tgid) + await portal.main_intent.set_room_name(portal.mxid, puppet.displayname) + except Exception: + self.log.warning(f"Failed to set room name for {portal.mxid}", exc_info=True) + return ok async def send_welcome_message(self, room_id: RoomID, inviter: 'u.User') -> None: try: @@ -431,8 +397,6 @@ class MatrixHandler(BaseMatrixHandler): async def handle_event(self, evt: Event) -> None: if evt.type == EventType.ROOM_REDACTION: await self.handle_redaction(evt) - elif evt.type == EventType.ROOM_ENCRYPTED and self.e2ee: - await self.int_handle_event(self.e2ee.decrypt(evt)) async def handle_state_event(self, evt: StateEvent) -> None: if evt.type == EventType.ROOM_POWER_LEVELS: diff --git a/mautrix_telegram/portal/metadata.py b/mautrix_telegram/portal/metadata.py index 3c1a00d3..4b20f69e 100644 --- a/mautrix_telegram/portal/metadata.py +++ b/mautrix_telegram/portal/metadata.py @@ -30,7 +30,7 @@ from telethon.tl.types import ( from mautrix.errors import MForbidden from mautrix.types import (RoomID, UserID, RoomCreatePreset, EventType, Membership, Member, - PowerLevelStateEventContent, RoomAlias) + PowerLevelStateEventContent) from mautrix.appservice import IntentAPI from ..types import TelegramID @@ -316,9 +316,9 @@ class PortalMetadata(BasePortal, ABC): }) if direct: invites.append(self.az.bot_mxid) - # The bridge bot needs to join for e2ee, but that messes up the default name generation - # If/when canonical DMs happen, this might not be necessary anymore. - self.title = puppet.displayname + # The bridge bot needs to join for e2ee, but that messes up the default name + # generation. If/when canonical DMs happen, this might not be necessary anymore. + self.title = puppet.displayname if config["appservice.community_id"]: initial_state.append({ "type": "m.room.related_groups", @@ -336,12 +336,15 @@ class PortalMetadata(BasePortal, ABC): if not room_id: raise Exception(f"Failed to create room") - if self.encrypted and direct: - try: - await self.az.intent.join_room_by_id(room_id) - # TODO feed info about room to matrix-nio - except Exception: - self.log.warning(f"Failed to add bridge bot to new private chat portal {room_id}") + if self.encrypted: + members = [self.main_intent.mxid] + if direct: + try: + await self.az.intent.join_room_by_id(room_id) + members += [self.az.intent.mxid] + except Exception: + self.log.warning(f"Failed to add bridge bot to new private chat {room_id}") + await self.matrix.e2ee.add_room(room_id, members=members, encrypted=True) self.mxid = RoomID(room_id) self.by_mxid[self.mxid] = self diff --git a/requirements.txt b/requirements.txt index 60d6e0d0..89119906 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,6 +4,6 @@ ruamel.yaml>=0.15.35,<0.17 python-magic>=0.4,<0.5 commonmark>=0.8,<0.10 aiohttp>=3,<4 -mautrix==0.5.0.beta7 +mautrix==0.5.0.beta8 telethon>=1.10,<1.12 telethon-session-sqlalchemy>=0.2.14,<0.3