summaryrefslogtreecommitdiff
path: root/poezio/plugin_e2ee.py
diff options
context:
space:
mode:
Diffstat (limited to 'poezio/plugin_e2ee.py')
-rw-r--r--poezio/plugin_e2ee.py85
1 files changed, 74 insertions, 11 deletions
diff --git a/poezio/plugin_e2ee.py b/poezio/plugin_e2ee.py
index d4b26d46..daf00818 100644
--- a/poezio/plugin_e2ee.py
+++ b/poezio/plugin_e2ee.py
@@ -336,7 +336,9 @@ class E2EEPlugin(BasePlugin):
dump_tuple(get_theme().COLOR_CHAR_NACK),
exc,
)
- tab.nack_message(msg, stanza['id'], stanza['from'])
+ # XXX: check before commit. Do we not nack in MUCs?
+ if not isinstance(tab, MucTab):
+ tab.nack_message(msg, stanza['id'], stanza['from'])
# TODO: display exceptions to the user properly
log.error('Exception in encrypt:', exc_info=True)
return None
@@ -353,6 +355,7 @@ class E2EEPlugin(BasePlugin):
if not has_eme and self.encrypted_tags is not None:
for (namespace, tag) in self.encrypted_tags:
if message.xml.find('{%s}%s' % (namespace, tag)) is not None:
+ # TODO: count all encrypted tags.
has_encrypted_tag = True
break
@@ -361,19 +364,73 @@ class E2EEPlugin(BasePlugin):
log.debug('Received %s message: %r', self.encryption_name, message['body'])
- self.decrypt(message, tab)
+ # Get the original JID of the sender. The JID might be None if it
+ # comes from a semi-anonymous MUC for example. Some plugins might be
+ # fine with this so let them handle it.
+ jid = message['from']
+ muctab = tab
+
+ if isinstance(muctab, PrivateTab):
+ muctab = tab.parent_muc
+ jid = None
+
+ if isinstance(muctab, MucTab):
+ nick = message['from'].resource
+ for user in muctab.users:
+ if user.nick == nick:
+ jid = user.jid or None
+ break
+
+ self.decrypt(message, jid, tab)
log.debug('Decrypted %s message: %r', self.encryption_name, message['body'])
return None
async def _encrypt(self, stanza: StanzaBase) -> Optional[StanzaBase]:
- if not isinstance(stanza, Message) or stanza['type'] not in ('chat', 'groupchat'):
+ if not isinstance(stanza, Message) or stanza['type'] not in ('normal', 'chat', 'groupchat'):
raise NothingToEncrypt()
message = stanza
- jid = stanza['to']
- tab = self.core.tabs.by_name_and_class(jid, ChatTab)
- if not self._encryption_enabled(jid):
+ # Find who to encrypt to. If in a groupchat this can be multiple JIDs.
+ # It is possible that we are not able to find a jid (e.g., semi-anon
+ # MUCs). Let the plugin decide what to do with this information.
+ jids = [message['to']] # type: Optional[List[JID]]
+ tab = self.core.tabs.by_jid(message['to'])
+ if tab is None: # When does that ever happen?
+ log.debug('Attempting to encrypt a message to \'%s\' '
+ 'that is not attached to a Tab. ?! Aborting '
+ 'encryption.', message['to'])
+ return None
+
+ parent = None
+ if isinstance(tab, PrivateTab):
+ parent = tab.parent_muc
+ nick = tab.jid.resource
+ jids = None
+
+ for user in parent.users:
+ if user.nick == nick:
+ jids = user.jid or None
+ break
+
+ if isinstance(tab, MucTab):
+ jids = []
+ for user in tab.users:
+ # If the JID of a user is None, assume all others are None and
+ # we are in a (at least) semi-anon room. TODO: Really check if
+ # the room is semi-anon. Currently a moderator of a semi-anon
+ # room will possibly encrypt to everybody, leaking their
+ # public key/identity, and they wouldn't be able to decrypt it
+ # anyway if they don't know the moderator's JID.
+ # TODO: Change MUC to give easier access to this information.
+ if user.jid is None:
+ jids = None
+ break
+ # If we encrypt to all of these JIDs is up to the plugin, we
+ # just tell it who is in the room.
+ jids.append(user.jid)
+
+ if not self._encryption_enabled(tab.jid):
raise NothingToEncrypt()
log.debug('Sending %s message: %r', self.encryption_name, message)
@@ -392,11 +449,13 @@ class E2EEPlugin(BasePlugin):
return None
# Call the enabled encrypt method
- func = self._enabled_tabs[jid]
+ func = self._enabled_tabs[tab.jid]
if iscoroutinefunction(func):
- await func(message, tab, passthrough=True)
+ # pylint: disable=unexpected-keyword-arg
+ await func(message, jids, tab, passthrough=True)
else:
- func(message, tab, passthrough=True)
+ # pylint: disable=unexpected-keyword-arg
+ func(message, jids, tab, passthrough=True)
if has_body:
# Only add EME tag if the message has a body.
@@ -437,13 +496,16 @@ class E2EEPlugin(BasePlugin):
option_name = '%s:%s' % (self.encryption_short_name, fingerprint)
return config.get(option=option_name, section=jid)
- async def decrypt(self, _message: Message, tab: ChatTabs):
+ async def decrypt(self, message: Message, jid: Optional[JID], tab: ChatTab):
"""Decryption method
This is a method the plugin must implement. It is expected that this
method will edit the received message and return nothing.
:param message: Message to be decrypted.
+ :param jid: Real Jid of the sender if available. We might be
+ talking through a semi-anonymous MUC where real JIDs are
+ not available.
:param tab: Tab the message is coming from.
:returns: None
@@ -451,13 +513,14 @@ class E2EEPlugin(BasePlugin):
raise NotImplementedError
- async def encrypt(self, _message: Message, tab: ChatTabs):
+ async def encrypt(self, message: Message, jids: Optional[List[JID]], tab: ChatTabs):
"""Encryption method
This is a method the plugin must implement. It is expected that this
method will edit the received message and return nothing.
:param message: Message to be encrypted.
+ :param jids: Real Jids of all possible recipients.
:param tab: Tab the message is going to.
:returns: None