Mercurial > libervia-backend
comparison sat/plugins/plugin_xep_0384.py @ 3972:5fbdf986670c
plugin pte: Pubsub Target Encryption implementation:
This plugin lets encrypt a few items for a specific set of entities.
rel 382
author | Goffi <goffi@goffi.org> |
---|---|
date | Mon, 31 Oct 2022 13:46:51 +0100 |
parents | 8e7d5796fb23 |
children | db45d49518f6 |
comparison
equal
deleted
inserted
replaced
3971:9b1d74a6b48c | 3972:5fbdf986670c |
---|---|
20 from datetime import datetime | 20 from datetime import datetime |
21 import enum | 21 import enum |
22 import logging | 22 import logging |
23 import time | 23 import time |
24 from typing import \ | 24 from typing import \ |
25 Any, Dict, FrozenSet, List, Literal, NamedTuple, Optional, Set, Type, cast | 25 Any, Dict, FrozenSet, List, Literal, NamedTuple, Optional, Set, Type, Union, cast |
26 import uuid | 26 import uuid |
27 import xml.etree.ElementTree as ET | 27 import xml.etree.ElementTree as ET |
28 from xml.sax.saxutils import quoteattr | 28 from xml.sax.saxutils import quoteattr |
29 | 29 |
30 from typing_extensions import Final, Never, assert_never | 30 from typing_extensions import Final, Never, assert_never |
1579 # These triggers are used by oldmemo, which doesn't do SCE and only applies to | 1579 # These triggers are used by oldmemo, which doesn't do SCE and only applies to |
1580 # messages. Temporarily, until a more fitting trigger for SCE-based encryption is | 1580 # messages. Temporarily, until a more fitting trigger for SCE-based encryption is |
1581 # added, the messageReceived trigger is also used for twomemo. | 1581 # added, the messageReceived trigger is also used for twomemo. |
1582 sat.trigger.add( | 1582 sat.trigger.add( |
1583 "messageReceived", | 1583 "messageReceived", |
1584 self.__message_received_trigger, | 1584 self._message_received_trigger, |
1585 priority=100050 | 1585 priority=100050 |
1586 ) | 1586 ) |
1587 sat.trigger.add( | 1587 sat.trigger.add( |
1588 "sendMessageData", | 1588 "sendMessageData", |
1589 self.__send_message_data_trigger, | 1589 self.__send_message_data_trigger, |
2096 client, | 2096 client, |
2097 session_manager, | 2097 session_manager, |
2098 frozenset(applied_trust_updates) | 2098 frozenset(applied_trust_updates) |
2099 ) | 2099 ) |
2100 | 2100 |
2101 async def __message_received_trigger( | 2101 async def _message_received_trigger( |
2102 self, | 2102 self, |
2103 client: SatXMPPClient, | 2103 client: SatXMPPClient, |
2104 message_elt: domish.Element, | 2104 message_elt: domish.Element, |
2105 post_treat: defer.Deferred | 2105 post_treat: defer.Deferred |
2106 ) -> bool: | 2106 ) -> bool: |
2111 message has fully progressed through the message receiving flow. Can be used | 2111 message has fully progressed through the message receiving flow. Can be used |
2112 to apply treatments to the fully processed message, like marking it as | 2112 to apply treatments to the fully processed message, like marking it as |
2113 encrypted. | 2113 encrypted. |
2114 @return: Whether to continue the message received flow. | 2114 @return: Whether to continue the message received flow. |
2115 """ | 2115 """ |
2116 | |
2117 muc_plaintext_cache_key: Optional[MUCPlaintextCacheKey] = None | 2116 muc_plaintext_cache_key: Optional[MUCPlaintextCacheKey] = None |
2118 | 2117 |
2119 sender_jid = jid.JID(message_elt["from"]) | 2118 sender_jid = jid.JID(message_elt["from"]) |
2120 feedback_jid: jid.JID | 2119 feedback_jid: jid.JID |
2121 | 2120 |
2122 message_type = message_elt.getAttribute("type", "unknown") | 2121 message_type = message_elt.getAttribute("type", C.MESS_TYPE_NORMAL) |
2123 is_muc_message = message_type == C.MESS_TYPE_GROUPCHAT | 2122 is_muc_message = message_type == C.MESS_TYPE_GROUPCHAT |
2124 if is_muc_message: | 2123 if is_muc_message: |
2125 if self.__xep_0045 is None: | 2124 if self.__xep_0045 is None: |
2126 log.warning( | 2125 log.warning( |
2127 "Ignoring MUC message since plugin XEP-0045 is not available." | 2126 "Ignoring MUC message since plugin XEP-0045 is not available." |
2418 if encryption["plugin"].namespace != twomemo.twomemo.NAMESPACE: | 2417 if encryption["plugin"].namespace != twomemo.twomemo.NAMESPACE: |
2419 # Encryption is requested for this recipient, but not with twomemo | 2418 # Encryption is requested for this recipient, but not with twomemo |
2420 return True | 2419 return True |
2421 | 2420 |
2422 # All pre-checks done, we can start encrypting! | 2421 # All pre-checks done, we can start encrypting! |
2423 await self.__encrypt( | 2422 await self.encrypt( |
2424 client, | 2423 client, |
2425 twomemo.twomemo.NAMESPACE, | 2424 twomemo.twomemo.NAMESPACE, |
2426 stanza, | 2425 stanza, |
2427 recipient_bare_jid, | 2426 recipient_bare_jid, |
2428 stanza.getAttribute("type", "unkown") == C.MESS_TYPE_GROUPCHAT, | 2427 stanza.getAttribute("type", C.MESS_TYPE_NORMAL) == C.MESS_TYPE_GROUPCHAT, |
2429 stanza.getAttribute("id", None) | 2428 stanza.getAttribute("id", None) |
2430 ) | 2429 ) |
2431 | 2430 |
2432 # Add a store hint if this is a message stanza | 2431 # Add a store hint if this is a message stanza |
2433 if stanza.name == "message": | 2432 if stanza.name == "message": |
2460 stanza = mess_data["xml"] | 2459 stanza = mess_data["xml"] |
2461 recipient_jid = mess_data["to"] | 2460 recipient_jid = mess_data["to"] |
2462 is_muc_message = mess_data["type"] == C.MESS_TYPE_GROUPCHAT | 2461 is_muc_message = mess_data["type"] == C.MESS_TYPE_GROUPCHAT |
2463 stanza_id = mess_data["uid"] | 2462 stanza_id = mess_data["uid"] |
2464 | 2463 |
2465 await self.__encrypt( | 2464 await self.encrypt( |
2466 client, | 2465 client, |
2467 oldmemo.oldmemo.NAMESPACE, | 2466 oldmemo.oldmemo.NAMESPACE, |
2468 stanza, | 2467 stanza, |
2469 recipient_jid, | 2468 recipient_jid, |
2470 is_muc_message, | 2469 is_muc_message, |
2472 ) | 2471 ) |
2473 | 2472 |
2474 # Add a store hint | 2473 # Add a store hint |
2475 self.__xep_0334.addHintElements(stanza, [ "store" ]) | 2474 self.__xep_0334.addHintElements(stanza, [ "store" ]) |
2476 | 2475 |
2477 async def __encrypt( | 2476 async def encrypt( |
2478 self, | 2477 self, |
2479 client: SatXMPPClient, | 2478 client: SatXMPPClient, |
2480 namespace: Literal["urn:xmpp:omemo:2", "eu.siacs.conversations.axolotl"], | 2479 namespace: Literal["urn:xmpp:omemo:2", "eu.siacs.conversations.axolotl"], |
2481 stanza: domish.Element, | 2480 stanza: domish.Element, |
2482 recipient_jid: jid.JID, | 2481 recipient_jids: Union[jid.JID, Set[jid.JID]], |
2483 is_muc_message: bool, | 2482 is_muc_message: bool, |
2484 stanza_id: Optional[str] | 2483 stanza_id: Optional[str] |
2485 ) -> None: | 2484 ) -> None: |
2486 """ | 2485 """ |
2487 @param client: The client. | 2486 @param client: The client. |
2488 @param namespace: The namespace of the OMEMO version to use. | 2487 @param namespace: The namespace of the OMEMO version to use. |
2489 @param stanza: The stanza. Twomemo will encrypt the whole stanza using SCE, | 2488 @param stanza: The stanza. Twomemo will encrypt the whole stanza using SCE, |
2490 oldmemo will encrypt only the body. The stanza is modified by this call. | 2489 oldmemo will encrypt only the body. The stanza is modified by this call. |
2491 @param recipient_jid: The JID of the recipient. Can be a bare (aka "userhost") JID | 2490 @param recipient_jid: The JID of the recipients. |
2492 but doesn't have to. | 2491 Can be a bare (aka "userhost") JIDs but doesn't have to. |
2492 A single JID can be used. | |
2493 @param is_muc_message: Whether the stanza is a message stanza to a MUC room. | 2493 @param is_muc_message: Whether the stanza is a message stanza to a MUC room. |
2494 @param stanza_id: The id of this stanza. Especially relevant for message stanzas | 2494 @param stanza_id: The id of this stanza. Especially relevant for message stanzas |
2495 to MUC rooms such that the outgoing plaintext can be cached for MUC message | 2495 to MUC rooms such that the outgoing plaintext can be cached for MUC message |
2496 reflection handling. | 2496 reflection handling. |
2497 | 2497 |
2498 @warning: The calling code MUST take care of adding the store message processing | 2498 @warning: The calling code MUST take care of adding the store message processing |
2499 hint to the stanza if applicable! This can be done before or after this call, | 2499 hint to the stanza if applicable! This can be done before or after this call, |
2500 the order doesn't matter. | 2500 the order doesn't matter. |
2501 """ | 2501 """ |
2502 if isinstance(recipient_jids, jid.JID): | |
2503 recipient_jids = {recipient_jids} | |
2504 if not recipient_jids: | |
2505 raise exceptions.InternalError("At least one JID must be specified") | |
2506 recipient_jid = next(iter(recipient_jids)) | |
2502 | 2507 |
2503 muc_plaintext_cache_key: Optional[MUCPlaintextCacheKey] = None | 2508 muc_plaintext_cache_key: Optional[MUCPlaintextCacheKey] = None |
2504 | 2509 |
2505 recipient_bare_jids: Set[str] | 2510 recipient_bare_jids: Set[str] |
2506 feedback_jid: jid.JID | 2511 feedback_jid: jid.JID |
2507 | 2512 |
2508 if is_muc_message: | 2513 if is_muc_message: |
2514 if len(recipient_jids) != 1: | |
2515 raise exceptions.InternalError( | |
2516 'Only one JID can be set when "is_muc_message" is set' | |
2517 ) | |
2509 if self.__xep_0045 is None: | 2518 if self.__xep_0045 is None: |
2510 raise exceptions.InternalError( | 2519 raise exceptions.InternalError( |
2511 "Encryption of MUC message requested, but plugin XEP-0045 is not" | 2520 "Encryption of MUC message requested, but plugin XEP-0045 is not" |
2512 " available." | 2521 " available." |
2513 ) | 2522 ) |
2529 client=client, | 2538 client=client, |
2530 room_jid=room_jid, | 2539 room_jid=room_jid, |
2531 message_uid=stanza_id | 2540 message_uid=stanza_id |
2532 ) | 2541 ) |
2533 else: | 2542 else: |
2534 recipient_bare_jids = { recipient_jid.userhost() } | 2543 recipient_bare_jids = {r.userhost() for r in recipient_jids} |
2535 feedback_jid = recipient_jid.userhostJID() | 2544 feedback_jid = recipient_jid.userhostJID() |
2536 | 2545 |
2537 log.debug( | 2546 log.debug( |
2538 f"Intercepting message that is to be encrypted by {namespace} for" | 2547 f"Intercepting message that is to be encrypted by {namespace} for" |
2539 f" {recipient_bare_jids}" | 2548 f" {recipient_bare_jids}" |