示例#1
0
    async def _find_olm_sessions(self, session: OutboundGroupSession, user_id: UserID,
                                 device_id: DeviceID, device: DeviceIdentity
                                 ) -> SessionEncryptResult:
        key = (user_id, device_id)
        if key in session.users_ignored or key in session.users_shared_with:
            return already_shared
        elif user_id == self.client.mxid and device_id == self.client.device_id:
            session.users_ignored.add(key)
            return already_shared

        if device.trust == TrustState.BLACKLISTED:
            self.log.debug(f"Not encrypting group session {session.id} for {device_id} "
                           f"of {user_id}: device is blacklisted")
            session.users_ignored.add(key)
            return RoomKeyWithheldEventContent(
                room_id=session.room_id, algorithm=EncryptionAlgorithm.MEGOLM_V1,
                session_id=SessionID(session.id), sender_key=self.account.identity_key,
                code=RoomKeyWithheldCode.BLACKLISTED, reason="Device is blacklisted")
        elif not self.allow_unverified_devices and device.trust == TrustState.UNSET:
            self.log.debug(f"Not encrypting group session {session.id} for {device_id} "
                           f"of {user_id}: device is not verified")
            session.users_ignored.add(key)
            return RoomKeyWithheldEventContent(
                room_id=session.room_id, algorithm=EncryptionAlgorithm.MEGOLM_V1,
                session_id=SessionID(session.id), sender_key=self.account.identity_key,
                code=RoomKeyWithheldCode.UNVERIFIED, reason="This device does not encrypt "
                                                            "messages for unverified devices")
        device_session = await self.crypto_store.get_latest_session(device.identity_key)
        if not device_session:
            return key_missing
        session.users_shared_with.add(key)
        return device_session, device
示例#2
0
 async def _encrypt_megolm_event(
         self, room_id: RoomID, event_type: EventType,
         content: Any) -> EncryptedMegolmEventContent:
     self.log.debug(f"Encrypting event of type {event_type} for {room_id}")
     session = await self.crypto_store.get_outbound_group_session(room_id)
     if not session:
         raise EncryptionError("No group session created")
     ciphertext = session.encrypt(
         json.dumps({
             "room_id":
             room_id,
             "type":
             event_type.serialize(),
             "content":
             content.serialize()
             if isinstance(content, Serializable) else content,
         }))
     try:
         relates_to = content.relates_to
     except AttributeError:
         try:
             relates_to = RelatesTo.deserialize(content["m.relates_to"])
         except KeyError:
             relates_to = None
     await self.crypto_store.update_outbound_group_session(session)
     return EncryptedMegolmEventContent(
         sender_key=self.account.identity_key,
         device_id=self.client.device_id,
         ciphertext=ciphertext,
         session_id=SessionID(session.id),
         relates_to=relates_to,
     )
示例#3
0
 async def _new_outbound_group_session(
         self, room_id: RoomID) -> OutboundGroupSession:
     session = OutboundGroupSession(room_id)
     await self._create_group_session(
         self.account.identity_key,
         self.account.signing_key,
         room_id,
         SessionID(session.id),
         session.session_key,
     )
     return session
示例#4
0
 async def update_session(self, key: IdentityKey, session: Session) -> None:
     try:
         assert self._olm_cache[key][SessionID(session.id)] == session
     except (KeyError, AssertionError) as e:
         self.log.warning(
             f"Cached olm session with ID {session.id} "
             f"isn't equal to the one being saved to the database ({e})")
     pickle = session.pickle(self.pickle_key)
     q = (
         "UPDATE crypto_olm_session SET session=$1, last_encrypted=$2, last_decrypted=$3 "
         "WHERE session_id=$4 AND account_id=$5")
     await self.db.execute(q, pickle, session.last_encrypted,
                           session.last_decrypted, session.id,
                           self.account_id)
示例#5
0
 async def get_latest_session(self, key: IdentityKey) -> Session | None:
     q = (
         "SELECT session_id, session, created_at, last_encrypted, last_decrypted "
         "FROM crypto_olm_session WHERE sender_key=$1 AND account_id=$2 "
         "ORDER BY last_decrypted DESC LIMIT 1")
     row = await self.db.fetchrow(q, key, self.account_id)
     if row is None:
         return None
     try:
         return self._olm_cache[key][row["session_id"]]
     except KeyError:
         sess = Session.from_pickle(
             row["session"],
             passphrase=self.pickle_key,
             creation_time=row["created_at"],
             last_encrypted=row["last_encrypted"],
             last_decrypted=row["last_decrypted"],
         )
         self._olm_cache[key][SessionID(sess.id)] = sess
         return sess
示例#6
0
 async def add_session(self, key: IdentityKey, session: Session) -> None:
     if session.id in self._olm_cache[key]:
         self.log.warning(
             f"Cache already contains Olm session with ID {session.id}")
     self._olm_cache[key][SessionID(session.id)] = session
     pickle = session.pickle(self.pickle_key)
     q = """
         INSERT INTO crypto_olm_session (session_id, sender_key, session, created_at,
                                         last_encrypted, last_decrypted, account_id)
         VALUES ($1, $2, $3, $4, $5, $6, $7)
     """
     await self.db.execute(
         q,
         session.id,
         key,
         pickle,
         session.creation_time,
         session.last_encrypted,
         session.last_decrypted,
         self.account_id,
     )
示例#7
0
 async def get_sessions(self, key: IdentityKey) -> list[Session]:
     q = (
         "SELECT session_id, session, created_at, last_encrypted, last_decrypted "
         "FROM crypto_olm_session WHERE sender_key=$1 AND account_id=$2 "
         "ORDER BY last_decrypted DESC")
     rows = await self.db.fetch(q, key, self.account_id)
     sessions = []
     for row in rows:
         try:
             sess = self._olm_cache[key][row["session_id"]]
         except KeyError:
             sess = Session.from_pickle(
                 row["session"],
                 passphrase=self.pickle_key,
                 creation_time=row["created_at"],
                 last_encrypted=row["last_encrypted"],
                 last_decrypted=row["last_decrypted"],
             )
             self._olm_cache[key][SessionID(sess.id)] = sess
         sessions.append(sess)
     return sessions